mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Merge with 4.0.4
BitKeeper/etc/logging_ok: auto-union client/mysqldump.c: Auto merged include/Makefile.am: Auto merged include/my_base.h: Auto merged include/my_sys.h: Auto merged include/sslopt-case.h: Auto merged libmysql/libmysql.c: Auto merged libmysql/libmysql.def: Auto merged libmysqld/lib_sql.cc: Auto merged myisam/ft_boolean_search.c: Auto merged myisam/mi_check.c: Auto merged myisam/mi_create.c: Auto merged myisam/myisamchk.c: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/create.result: Auto merged mysql-test/r/innodb.result: Auto merged mysql-test/r/myisam.result: Auto merged mysql-test/r/select.result: Auto merged mysql-test/r/type_set.result: Auto merged mysql-test/t/create.test: Auto merged mysql-test/t/myisam.test: Auto merged sql/Makefile.am: Auto merged sql/filesort.cc: Auto merged sql/ha_innodb.cc: Auto merged sql/ha_myisam.cc: Auto merged sql/handler.h: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_strfunc.cc: Auto merged sql/item_strfunc.h: Auto merged sql/lex.h: Auto merged sql/log.cc: Auto merged sql/log_event.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/net_pkg.cc: Auto merged sql/net_serv.cc: Auto merged sql/opt_range.cc: Auto merged sql/set_var.h: Auto merged sql/slave.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_insert.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_load.cc: Auto merged sql/share/english/errmsg.txt: Auto merged sql/sql_table.cc: Auto merged sql/sql_udf.cc: Auto merged sql/sql_union.cc: Auto merged sql/unireg.h: Auto merged sql/sql_cache.cc: Code cleanup (removed ifdef)
This commit is contained in:
commit
95e772b656
370 changed files with 74781 additions and 5578 deletions
11
.bzrignore
11
.bzrignore
|
@ -51,6 +51,8 @@ Docs/manual.ky
|
|||
Docs/manual.log
|
||||
Docs/manual.pdf
|
||||
Docs/manual.pg
|
||||
Docs/manual.texi.orig
|
||||
Docs/manual.texi.rej
|
||||
Docs/manual.toc
|
||||
Docs/manual.tp
|
||||
Docs/manual.txt
|
||||
|
@ -247,6 +249,7 @@ libmysqld/field.cc
|
|||
libmysqld/field_conv.cc
|
||||
libmysqld/filesort.cc
|
||||
libmysqld/get_password.c
|
||||
libmysqld/gstream.cc
|
||||
libmysqld/ha_berkeley.cc
|
||||
libmysqld/ha_heap.cc
|
||||
libmysqld/ha_innobase.cc
|
||||
|
@ -287,6 +290,7 @@ libmysqld/repl_failsafe.cc
|
|||
libmysqld/set_var.cc
|
||||
libmysqld/simple-test
|
||||
libmysqld/slave.cc
|
||||
libmysqld/spatial.cc
|
||||
libmysqld/sql_acl.cc
|
||||
libmysqld/sql_analyse.cc
|
||||
libmysqld/sql_base.cc
|
||||
|
@ -356,6 +360,8 @@ myisam/myisam.log
|
|||
myisam/myisamchk
|
||||
myisam/myisamlog
|
||||
myisam/myisampack
|
||||
myisam/rt_test
|
||||
myisam/sp_test
|
||||
myisam/test1.MYD
|
||||
myisam/test1.MYI
|
||||
myisam/test2.MYD
|
||||
|
@ -382,6 +388,7 @@ mysql.proj
|
|||
mysqld.S
|
||||
mysqld.sym
|
||||
mysys/#mf_iocache.c#
|
||||
mysys/charset2html
|
||||
mysys/getopt.c
|
||||
mysys/getopt1.c
|
||||
mysys/ste5KbMa
|
||||
|
@ -466,6 +473,7 @@ sql/share/norwegian/errmsg.sys
|
|||
sql/sql_select.cc.orig
|
||||
sql/sql_yacc.cc
|
||||
sql/sql_yacc.h
|
||||
sql/sql_yacc.yy.orig
|
||||
stamp-h
|
||||
stamp-h.in
|
||||
strings/conf_to_src
|
||||
|
@ -485,6 +493,7 @@ support-files/mysql-log-rotate
|
|||
support-files/mysql.server
|
||||
support-files/mysql.spec
|
||||
tags
|
||||
tests/client_test
|
||||
tmp/*
|
||||
tools/my_vsnprintf.c
|
||||
tools/mysqlmanager
|
||||
|
@ -494,3 +503,5 @@ vio/test-ssl
|
|||
vio/test-sslclient
|
||||
vio/test-sslserver
|
||||
vio/viotest-ssl
|
||||
sql_error.cc
|
||||
sql_prepare.cc
|
||||
|
|
|
@ -8,6 +8,6 @@ c_warnings="$c_warnings $debug_extra_warnings"
|
|||
cxx_warnings="$cxx_warnings $debug_extra_warnings"
|
||||
extra_configs="$pentium_configs $debug_configs $static_link"
|
||||
|
||||
extra_configs="$extra_configs "
|
||||
extra_configs="$extra_configs $static_link"
|
||||
|
||||
. "$path/FINISH.sh"
|
||||
|
|
|
@ -3,6 +3,7 @@ Administrator@co3064164-a.rochd1.qld.optushome.com.au
|
|||
Administrator@fred.
|
||||
Miguel@light.local
|
||||
Sinisa@sinisa.nasamreza.org
|
||||
WAX@sergbook.mysql.com
|
||||
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
|
||||
akishkin@work.mysql.com
|
||||
arjen@co3064164-a.bitbike.com
|
||||
|
@ -10,6 +11,7 @@ arjen@fred.bitbike.com
|
|||
arjen@george.bitbike.com
|
||||
bar@bar.mysql.r18.ru
|
||||
bar@bar.udmsearch.izhnet.ru
|
||||
bar@gw.udmsearch.izhnet.ru
|
||||
bell@sanja.is.com.ua
|
||||
davida@isil.mysql.com
|
||||
heikki@donna.mysql.fi
|
||||
|
@ -53,6 +55,7 @@ paul@central.snake.net
|
|||
paul@teton.kitebird.com
|
||||
peter@linux.local
|
||||
peter@mysql.com
|
||||
ram@gw.udmsearch.izhnet.ru
|
||||
ram@ram.(none)
|
||||
root@x3.internalnet
|
||||
salle@geopard.(none)
|
||||
|
@ -62,6 +65,7 @@ serg@build.mysql2.com
|
|||
serg@serg.mysql.com
|
||||
serg@sergbook.mysql.com
|
||||
sinisa@rhols221.adsl.netsonic.fi
|
||||
tfr@beta.frontier86.ee
|
||||
tfr@indrek.tfr.cafe.ee
|
||||
tfr@sarvik.tfr.cafe.ee
|
||||
tim@bitch.mysql.fi
|
||||
|
@ -75,6 +79,7 @@ tonu@hundin.mysql.fi
|
|||
tonu@volk.internalnet
|
||||
tonu@x153.internalnet
|
||||
tonu@x3.internalnet
|
||||
venu@myvenu.com
|
||||
venu@work.mysql.com
|
||||
vva@genie.(none)
|
||||
walrus@mysql.com
|
||||
|
@ -82,4 +87,3 @@ worm@altair.is.lan
|
|||
zak@balfor.local
|
||||
zak@linux.local
|
||||
zgreant@mysql.com
|
||||
tfr@beta.frontier86.ee
|
||||
|
|
|
@ -25,10 +25,10 @@ then
|
|||
echo "Commit successful, notifying developers at $TO"
|
||||
(
|
||||
cat <<EOF
|
||||
List-ID: <bk.mysql-4.0>
|
||||
List-ID: <bk.mysql-4.1>
|
||||
From: $FROM
|
||||
To: $TO
|
||||
Subject: bk commit - 4.0 tree
|
||||
Subject: bk commit - 4.1 tree
|
||||
|
||||
EOF
|
||||
bk changes -v -r+
|
||||
|
@ -41,13 +41,13 @@ EOF
|
|||
echo "Notifying internals list at $INTERNALS"
|
||||
(
|
||||
cat <<EOF
|
||||
List-ID: <bk.mysql-4.0>
|
||||
List-ID: <bk.mysql-4.1>
|
||||
From: $FROM
|
||||
To: $INTERNALS
|
||||
Subject: bk commit into 4.0 tree
|
||||
Subject: bk commit into 4.1 tree
|
||||
|
||||
Below is the list of changes that have just been committed into a local
|
||||
4.0 repository of $USER. When $USER does a push these changes will
|
||||
4.1 repository of $USER. When $USER does a push these changes will
|
||||
be propagated to the main repository and, within 24 hours after the
|
||||
push, to the public repository.
|
||||
For information on how to access the public repository
|
||||
|
@ -68,10 +68,10 @@ EOF
|
|||
echo "Notifying docs list at $DOCS"
|
||||
(
|
||||
cat <<EOF
|
||||
List-ID: <bk.mysql-4.0>
|
||||
List-ID: <bk.mysql-4.1>
|
||||
From: $FROM
|
||||
To: $DOCS
|
||||
Subject: bk commit - 4.0 tree (Manual)
|
||||
Subject: bk commit - 4.1 tree (Manual)
|
||||
|
||||
EOF
|
||||
bk changes -v -r+
|
||||
|
|
|
@ -23324,7 +23324,7 @@ If you need better performance when you start using MySQL in a production
|
|||
environment, you can remove the @code{--log} option from @code{mysql.server}
|
||||
or change it to @code{--log-bin}. @xref{Binary log}.
|
||||
|
||||
The entries in this log are written as @code{mysqld} receives the questions.
|
||||
The entries in this log are written as @code{mysqld} receives the queries.
|
||||
This may be different from the order in which the statements are executed.
|
||||
This is in contrast to the update log and the binary log which are written
|
||||
after the query is executed, but before any locks are released.
|
||||
|
@ -23337,7 +23337,7 @@ after the query is executed, but before any locks are released.
|
|||
@cindex files, update log
|
||||
|
||||
@strong{Note}: the update log is replaced by the binary
|
||||
log. @xref{Binary log}. With this you can do anything that you can do
|
||||
log. @xref{Binary log}. You can do anything with the binary log that you can do
|
||||
with the update log.
|
||||
|
||||
When started with the @code{--log-update[=file_name]} option,
|
||||
|
@ -23352,7 +23352,7 @@ flush-logs}, execute the @code{FLUSH LOGS} statement, or restart the server.
|
|||
|
||||
@strong{Note}: for the above scheme to work, you must not create
|
||||
your own files with the same filename as the update log + some extensions
|
||||
that may be regarded as a number, in the directory used by the update log!
|
||||
that may be regarded as a number in the directory used by the update log!
|
||||
|
||||
If you use the @code{--log} or @code{-l} options, @code{mysqld} writes a
|
||||
general log with a filename of @file{hostname.log}, and restarts and
|
||||
|
@ -23396,8 +23396,8 @@ and the crash.
|
|||
@cindex binary log
|
||||
@cindex files, binary log
|
||||
|
||||
The intention is that the binary log should replace the update log, so
|
||||
we recommend you to switch to this log format as soon as possible!
|
||||
The binary log will replace the now deprecated update log, so
|
||||
we recommend you to switch to this log format as soon as possible.
|
||||
|
||||
The binary log contains all information that is available in the update
|
||||
log in a more efficient format. It also contains information about how long
|
||||
|
@ -23408,10 +23408,10 @@ find a problem query) you should use the general query log. @xref{Query log}.
|
|||
The binary log is also used when you are replicating a slave from a master.
|
||||
@xref{Replication}.
|
||||
|
||||
When started with the @code{--log-bin[=file_name]} option, @code{mysqld}
|
||||
When started with the @code{--log-bin[=file_name]} option @code{mysqld}
|
||||
writes a log file containing all SQL commands that update data. If no
|
||||
file name is given, it defaults to the name of the host machine followed
|
||||
by @code{-bin}. If file name is given, but it doesn't contain a path, the
|
||||
file name is given it defaults to the name of the host machine followed
|
||||
by @code{-bin}. If a file name is given, but doesn't contain a path, the
|
||||
file is written in the data directory.
|
||||
|
||||
If you supply an extension to @code{--log-bin=filename.extension}, the
|
||||
|
@ -23431,14 +23431,9 @@ to the binary log:
|
|||
@multitable @columnfractions .38 .62
|
||||
@item @strong{Option} @tab @strong{Description}
|
||||
|
||||
@item @code{binlog-do-db=database_name} @tab
|
||||
Tells the master it should log updates for the specified database, and
|
||||
exclude all others not explicitly mentioned.
|
||||
(Example: @code{binlog-do-db=some_database})
|
||||
@item @code{binlog-do-db=database_name} @tab Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned. (Example: @code{binlog-do-db=some_database})
|
||||
|
||||
@item @code{binlog-ignore-db=database_name} @tab
|
||||
Tells the master that updates to the given database should not be logged
|
||||
to the binary log (Example: @code{binlog-ignore-db=some_database})
|
||||
@item @code{binlog-ignore-db=database_name} @tab Tells the master that updates to the given database should not be logged to the binary log (Example: @code{binlog-ignore-db=some_database})
|
||||
@end multitable
|
||||
|
||||
To be able to know which different binary log files have been used,
|
||||
|
@ -23463,10 +23458,10 @@ shell> mysqlbinlog log-file | mysql -h server_name
|
|||
@end example
|
||||
|
||||
You can also use the @code{mysqlbinlog} program to read the binary log
|
||||
directly from a remote MySQL server!
|
||||
directly from a remote MySQL server.
|
||||
|
||||
@code{mysqlbinlog --help} will give you more information of how to use
|
||||
this program!
|
||||
this program.
|
||||
|
||||
If you are using @code{BEGIN [WORK]} or @code{SET AUTOCOMMIT=0}, you must
|
||||
use the MySQL binary log for backups instead of the old update log.
|
||||
|
@ -23475,14 +23470,13 @@ The binary logging is done immediately after a query completes but before
|
|||
any locks are released or any commit is done. This ensures that the log
|
||||
will be logged in the execution order.
|
||||
|
||||
Updates to non-transactional tables are stored in the binary log
|
||||
immediately after execution. For transactional tables such as @code{BDB}
|
||||
or @code{InnoDB} tables, all updates (@code{UPDATE}, @code{DELETE}
|
||||
or @code{INSERT}) that change tables are cached until a @code{COMMIT}.
|
||||
Every thread will, on start, allocate a buffer of @code{binlog_cache_size}
|
||||
to buffer queries. If a query is bigger than this, the thread will open
|
||||
a temporary file to handle the bigger cache. The temporary file will
|
||||
be deleted when the thread ends.
|
||||
Updates to a non-transactional table are stored in the binary log at
|
||||
once. For transactional tables such as @code{BDB} ! or @code{InnoDB}
|
||||
tables, all updates are cached until a @code{COMMIT}. Every thread
|
||||
will, on start, allocate a buffer of @code{binlog_cache_size} to buffer
|
||||
queries. If a query is bigger than this, the thread will open a
|
||||
temporary file to handle the bigger cache. The temporary file will be
|
||||
deleted when the thread ends.
|
||||
|
||||
The @code{max_binlog_cache_size} can be used to restrict the total size used
|
||||
to cache a multi-query transaction.
|
||||
|
@ -23505,10 +23499,10 @@ more than @code{long_query_time} to execute. The time to get the initial
|
|||
table locks are not counted as execution time.
|
||||
|
||||
The slow query log is logged after the query is executed and after all
|
||||
locks has been released. This may be different from the order in which
|
||||
locks have been released. This may be different from the order in which
|
||||
the statements are executed.
|
||||
|
||||
If no file name is given, it defaults to the name of the host machine
|
||||
If no filename is given, it defaults to the name of the host machine
|
||||
suffixed with @code{-slow.log}. If a filename is given, but doesn't
|
||||
contain a path, the file is written in the data directory.
|
||||
|
||||
|
@ -23518,8 +23512,8 @@ can become a difficult task. You can pipe the slow query log through the
|
|||
@code{mysqldumpslow} command to get a summary of the queries which
|
||||
appear in the log.
|
||||
|
||||
You are using @code{--log-long-format} then also queries that are not
|
||||
using indexes are printed. @xref{Command-line options}.
|
||||
If you use @code{--log-long-format} also, then queries that do not
|
||||
use indexes are logged as well. @xref{Command-line options}.
|
||||
|
||||
|
||||
@node Log file maintenance, , Slow query log, Log Files
|
||||
|
@ -23529,22 +23523,19 @@ using indexes are printed. @xref{Command-line options}.
|
|||
@cindex maintaining, log files
|
||||
@cindex log files, maintaining
|
||||
|
||||
MySQL has a lot of log files which make it easy to see what is
|
||||
going. @xref{Log Files}. One must however from time to time clean up
|
||||
after @code{MysQL} to ensure that the logs don't take up too much disk
|
||||
space.
|
||||
MySQL has many log files which makes it easy to see what is going on.
|
||||
@xref{Log Files}. One must, however, occasionally clean up
|
||||
after @code{MySQL} to ensure that the logs don't take up too much disk
|
||||
space by either removing or backing up old log files and then telling MySQL
|
||||
to start logging to new files. @xref{Backup}.
|
||||
|
||||
When using MySQL with log files, you will, from time to time,
|
||||
want to remove/backup old log files and tell MySQL to start
|
||||
logging on new files. @xref{Backup}.
|
||||
|
||||
On a Linux (@code{Redhat}) installation, you can use the
|
||||
On a Linux (@code{Redhat}) installation you can use the
|
||||
@code{mysql-log-rotate} script for this. If you installed MySQL
|
||||
from an RPM distribution, the script should have been installed
|
||||
automatically. Note that you should be careful with this if you are using
|
||||
the log for replication!
|
||||
from an RPM distribution the script should have been installed
|
||||
automatically. @strong{Note}: you should be careful with this if you are
|
||||
using the logs for replication.
|
||||
|
||||
On other systems you must install a short script yourself that you
|
||||
On other systems you must install a short script yourself that you can
|
||||
start from @code{cron} to handle log files.
|
||||
|
||||
You can force MySQL to start using new log files by using
|
||||
|
@ -28791,6 +28782,7 @@ and if you can use @code{GLOBAL} or @code{SESSION} with them.
|
|||
@item delayed_insert_limit @tab num @tab GLOBAL
|
||||
@item delayed_insert_timeout @tab num @tab GLOBAL
|
||||
@item delayed_queue_size @tab num @tab GLOBAL
|
||||
@item error_count @tab num @tab LOCAL
|
||||
@item flush @tab bool @tab GLOBAL
|
||||
@item flush_time @tab num @tab GLOBAL
|
||||
@item foreign_key_checks @tab bool @tab SESSION
|
||||
|
@ -28809,6 +28801,7 @@ and if you can use @code{GLOBAL} or @code{SESSION} with them.
|
|||
@item max_binlog_size @tab num @tab GLOBAL
|
||||
@item max_connect_errors @tab num @tab GLOBAL
|
||||
@item max_connections @tab num @tab GLOBAL
|
||||
@item max_error_count @tab num @tab GLOBAL | SESSION
|
||||
@item max_delayed_threads @tab num @tab GLOBAL
|
||||
@item max_heap_table_size @tab num @tab GLOBAL | SESSION
|
||||
@item max_join_size @tab num @tab GLOBAL | SESSION
|
||||
|
@ -28857,6 +28850,7 @@ and if you can use @code{GLOBAL} or @code{SESSION} with them.
|
|||
@item tx_isolation @tab enum @tab GLOBAL | SESSION
|
||||
@item version @tab string @tab GLOBAL
|
||||
@item wait_timeout @tab num @tab GLOBAL | SESSION
|
||||
@item warning_count @tab num @tab LOCAL
|
||||
@item unique_checks @tab bool @tab SESSION
|
||||
@end multitable
|
||||
|
||||
|
@ -36232,8 +36226,10 @@ mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
|
|||
|
||||
This will create a @code{MyISAM} table with three columns, a, b, and c.
|
||||
Notice that the columns from the @code{SELECT} statement are appended to
|
||||
the right side of the table, not overlapped onto it. Take the following
|
||||
example:
|
||||
the right side of the table, not overlapped onto it.
|
||||
Still, the column from the @code{SELECT} will overlap the column from
|
||||
the @code{CREATE} clause if they both have the same name. Take the following
|
||||
examples:
|
||||
|
||||
@example
|
||||
mysql> SELECT * FROM foo;
|
||||
|
@ -36254,6 +36250,18 @@ mysql> SELECT * FROM bar;
|
|||
| NULL | 1 |
|
||||
+------+---+
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
mysql> CREATE TABLE foobar (n FLOAT(3,2), m INT) SELECT n FROM foo;
|
||||
Query OK, 1 row affected (0.02 sec)
|
||||
Records: 1 Duplicates: 0 Warnings: 0
|
||||
|
||||
mysql> SELECT * FROM foobar;
|
||||
+------+------+
|
||||
| n | m |
|
||||
+------+------+
|
||||
| 1.00 | NULL |
|
||||
+------+------+
|
||||
1 row in set (0.00 sec)
|
||||
@end example
|
||||
|
||||
For each row in table @code{foo}, a row is inserted in @code{bar} with
|
||||
|
@ -51273,9 +51281,6 @@ Fixed bug in truncation operator for boolean full-text search.
|
|||
Allow value of @code{--user=#} option for @code{mysqld} to be specified
|
||||
as a numeric user ID.
|
||||
@item
|
||||
Fixed a bug where @code{SQL_CALC_ROWS} returned an incorrect value when used
|
||||
with one table and @code{ORDER BY} and with @code{InnoDB} tables.
|
||||
@item
|
||||
Fixed that @code{SELECT 0 LIMIT 0} doesn't hang thread.
|
||||
@item
|
||||
Fixed some problems with @code{USE/IGNORE INDEX} when using
|
||||
|
|
40
acconfig.h
40
acconfig.h
|
@ -18,6 +18,9 @@
|
|||
|
||||
#undef CRAY_STACKSEG_END
|
||||
|
||||
/* Define the default charset name */
|
||||
#undef DEFAULT_CHARSET_NAME
|
||||
|
||||
/* Version of .frm files */
|
||||
#undef DOT_FRM_VERSION
|
||||
|
||||
|
@ -63,6 +66,43 @@
|
|||
/* READLINE: */
|
||||
#undef HAVE_BSD_SIGNALS
|
||||
|
||||
/* Define charsets you want */
|
||||
#undef HAVE_CHARSET_armscii8
|
||||
#undef HAVE_CHARSET_big5
|
||||
#undef HAVE_CHARSET_cp1251
|
||||
#undef HAVE_CHARSET_cp1257
|
||||
#undef HAVE_CHARSET_croat
|
||||
#undef HAVE_CHARSET_czech
|
||||
#undef HAVE_CHARSET_danish
|
||||
#undef HAVE_CHARSET_dec8
|
||||
#undef HAVE_CHARSET_dos
|
||||
#undef HAVE_CHARSET_estonia
|
||||
#undef HAVE_CHARSET_euc_kr
|
||||
#undef HAVE_CHARSET_gb2312
|
||||
#undef HAVE_CHARSET_gbk
|
||||
#undef HAVE_CHARSET_german1
|
||||
#undef HAVE_CHARSET_greek
|
||||
#undef HAVE_CHARSET_hebrew
|
||||
#undef HAVE_CHARSET_hp8
|
||||
#undef HAVE_CHARSET_hungarian
|
||||
#undef HAVE_CHARSET_koi8_ru
|
||||
#undef HAVE_CHARSET_koi8_ukr
|
||||
#undef HAVE_CHARSET_latin1
|
||||
#undef HAVE_CHARSET_latin1_de
|
||||
#undef HAVE_CHARSET_latin2
|
||||
#undef HAVE_CHARSET_latin5
|
||||
#undef HAVE_CHARSET_sjis
|
||||
#undef HAVE_CHARSET_swe7
|
||||
#undef HAVE_CHARSET_tis620
|
||||
#undef HAVE_CHARSET_ucs2
|
||||
#undef HAVE_CHARSET_ujis
|
||||
#undef HAVE_CHARSET_usa7
|
||||
#undef HAVE_CHARSET_utf8
|
||||
#undef HAVE_CHARSET_win1250
|
||||
#undef HAVE_CHARSET_win1250ch
|
||||
#undef HAVE_CHARSET_win1251ukr
|
||||
#undef HAVE_CHARSET_win1251
|
||||
|
||||
/* ZLIB and compress: */
|
||||
#undef HAVE_COMPRESS
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include <signal.h>
|
||||
#include <violite.h>
|
||||
|
||||
const char *VER= "12.14";
|
||||
const char *VER= "13.0";
|
||||
|
||||
/* Don't try to make a nice table if the data is too big */
|
||||
#define MAX_COLUMN_LENGTH 1024
|
||||
|
@ -346,6 +346,7 @@ int main(int argc,char *argv[])
|
|||
if (!status.batch)
|
||||
ignore_errors=1; // Don't abort monitor
|
||||
signal(SIGINT, mysql_end); // Catch SIGINT to clean up
|
||||
signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up
|
||||
|
||||
/*
|
||||
Run in interactive mode like the ingres/postgres monitor
|
||||
|
@ -871,14 +872,14 @@ static COMMANDS *find_command (char *name,char cmd_char)
|
|||
}
|
||||
else
|
||||
{
|
||||
while (isspace(*name))
|
||||
while (my_isspace(system_charset_info,*name))
|
||||
name++;
|
||||
if (strchr(name,';') || strstr(name,"\\g"))
|
||||
return ((COMMANDS *) 0);
|
||||
if ((end=strcont(name," \t")))
|
||||
{
|
||||
len=(uint) (end - name);
|
||||
while (isspace(*end))
|
||||
while (my_isspace(system_charset_info,*end))
|
||||
end++;
|
||||
if (!*end)
|
||||
end=0; // no arguments to function
|
||||
|
@ -890,7 +891,8 @@ static COMMANDS *find_command (char *name,char cmd_char)
|
|||
for (uint i= 0; commands[i].name; i++)
|
||||
{
|
||||
if (commands[i].func &&
|
||||
((name && !my_casecmp(name,commands[i].name,len) &&
|
||||
((name &&
|
||||
!my_strncasecmp(system_charset_info,name,commands[i].name,len) &&
|
||||
!commands[i].name[len] &&
|
||||
(!end || (end && commands[i].takes_params))) ||
|
||||
!name && commands[i].cmd_char == cmd_char))
|
||||
|
@ -918,12 +920,13 @@ static bool add_line(String &buffer,char *line,char *in_string)
|
|||
|
||||
for (pos=out=line ; (inchar= (uchar) *pos) ; pos++)
|
||||
{
|
||||
if (isspace(inchar) && out == line && buffer.is_empty())
|
||||
if (my_isspace(system_charset_info,inchar) && out == line &&
|
||||
buffer.is_empty())
|
||||
continue;
|
||||
#ifdef USE_MB
|
||||
int l;
|
||||
if (use_mb(default_charset_info) &&
|
||||
(l = my_ismbchar(default_charset_info, pos, strend))) {
|
||||
if (use_mb(system_charset_info) &&
|
||||
(l = my_ismbchar(system_charset_info, pos, strend))) {
|
||||
while (l--)
|
||||
*out++ = *pos++;
|
||||
pos--;
|
||||
|
@ -986,7 +989,7 @@ static bool add_line(String &buffer,char *line,char *in_string)
|
|||
}
|
||||
else if (!*in_string && (inchar == '#' ||
|
||||
inchar == '-' && pos[1] == '-' &&
|
||||
isspace(pos[2])))
|
||||
my_isspace(system_charset_info,pos[2])))
|
||||
break; // comment to end of line
|
||||
else
|
||||
{ // Add found char to buffer
|
||||
|
@ -1362,9 +1365,9 @@ com_clear(String *buffer,char *line __attribute__((unused)))
|
|||
static int
|
||||
com_go(String *buffer,char *line __attribute__((unused)))
|
||||
{
|
||||
char buff[160],time_buff[32];
|
||||
char buff[200], time_buff[32], *pos;
|
||||
MYSQL_RES *result;
|
||||
ulong timer;
|
||||
ulong timer, warnings;
|
||||
uint error=0;
|
||||
|
||||
if (!status.batch)
|
||||
|
@ -1393,7 +1396,8 @@ com_go(String *buffer,char *line __attribute__((unused)))
|
|||
(void) com_print(buffer,0);
|
||||
|
||||
if (skip_updates &&
|
||||
(buffer->length() < 4 || my_sortcmp(buffer->ptr(),"SET ",4)))
|
||||
(buffer->length() < 4 || my_sortcmp(system_charset_info,buffer->ptr(),
|
||||
"SET ",4)))
|
||||
{
|
||||
(void) put_info("Ignoring query to other database",INFO_INFO);
|
||||
return 0;
|
||||
|
@ -1446,7 +1450,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
|
|||
{
|
||||
if (!mysql_num_rows(result) && ! quick)
|
||||
{
|
||||
sprintf(buff,"Empty set%s",time_buff);
|
||||
strmov(buff, "Empty set");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1461,20 +1465,30 @@ com_go(String *buffer,char *line __attribute__((unused)))
|
|||
print_tab_data(result);
|
||||
else
|
||||
print_table_data(result);
|
||||
sprintf(buff,"%ld %s in set%s",
|
||||
sprintf(buff,"%ld %s in set",
|
||||
(long) mysql_num_rows(result),
|
||||
(long) mysql_num_rows(result) == 1 ? "row" : "rows",
|
||||
time_buff);
|
||||
(long) mysql_num_rows(result) == 1 ? "row" : "rows");
|
||||
end_pager();
|
||||
}
|
||||
}
|
||||
else if (mysql_affected_rows(&mysql) == ~(ulonglong) 0)
|
||||
sprintf(buff,"Query OK%s",time_buff);
|
||||
strmov(buff,"Query OK");
|
||||
else
|
||||
sprintf(buff,"Query OK, %ld %s affected%s",
|
||||
sprintf(buff,"Query OK, %ld %s affected",
|
||||
(long) mysql_affected_rows(&mysql),
|
||||
(long) mysql_affected_rows(&mysql) == 1 ? "row" : "rows",
|
||||
time_buff);
|
||||
(long) mysql_affected_rows(&mysql) == 1 ? "row" : "rows");
|
||||
|
||||
pos=strend(buff);
|
||||
if ((warnings= mysql_warning_count(&mysql)))
|
||||
{
|
||||
*pos++= ',';
|
||||
*pos++= ' ';
|
||||
pos=int2str(warnings, pos, 10);
|
||||
pos=strmov(pos, " warning");
|
||||
if (warnings != 1)
|
||||
*pos++= 's';
|
||||
}
|
||||
strmov(pos, time_buff);
|
||||
put_info(buff,INFO_RESULT);
|
||||
if (mysql_info(&mysql))
|
||||
put_info(mysql_info(&mysql),INFO_RESULT);
|
||||
|
@ -1771,8 +1785,9 @@ safe_put_field(const char *pos,ulong length)
|
|||
{
|
||||
#ifdef USE_MB
|
||||
int l;
|
||||
if (use_mb(default_charset_info) &&
|
||||
(l = my_ismbchar(default_charset_info, pos, end))) {
|
||||
if (use_mb(system_charset_info) &&
|
||||
(l = my_ismbchar(system_charset_info, pos, end)))
|
||||
{
|
||||
while (l--)
|
||||
tee_putc(*pos++, PAGER);
|
||||
pos--;
|
||||
|
@ -1832,7 +1847,7 @@ com_tee(String *buffer, char *line __attribute__((unused)))
|
|||
|
||||
if (status.batch)
|
||||
return 0;
|
||||
while (isspace(*line))
|
||||
while (my_isspace(system_charset_info,*line))
|
||||
line++;
|
||||
if (!(param = strchr(line, ' '))) // if outfile wasn't given, use the default
|
||||
{
|
||||
|
@ -1851,11 +1866,12 @@ com_tee(String *buffer, char *line __attribute__((unused)))
|
|||
}
|
||||
|
||||
/* eliminate the spaces before the parameters */
|
||||
while (isspace(*param))
|
||||
while (my_isspace(system_charset_info,*param))
|
||||
param++;
|
||||
end= strmake(file_name, param, sizeof(file_name) - 1);
|
||||
/* remove end space from command line */
|
||||
while (end > file_name && (isspace(end[-1]) || iscntrl(end[-1])))
|
||||
while (end > file_name && (my_isspace(system_charset_info,end[-1]) ||
|
||||
my_iscntrl(system_charset_info,end[-1])))
|
||||
end--;
|
||||
end[0]= 0;
|
||||
if (end == file_name)
|
||||
|
@ -1895,7 +1911,7 @@ com_pager(String *buffer, char *line __attribute__((unused)))
|
|||
if (status.batch)
|
||||
return 0;
|
||||
/* Skip space from file name */
|
||||
while (isspace(*line))
|
||||
while (my_isspace(system_charset_info,*line))
|
||||
line++;
|
||||
if (!(param = strchr(line, ' '))) // if pager was not given, use the default
|
||||
{
|
||||
|
@ -1911,10 +1927,11 @@ com_pager(String *buffer, char *line __attribute__((unused)))
|
|||
}
|
||||
else
|
||||
{
|
||||
while (isspace(*param))
|
||||
while (my_isspace(system_charset_info,*param))
|
||||
param++;
|
||||
end=strmake(pager_name, param, sizeof(pager_name)-1);
|
||||
while (end > pager_name && (isspace(end[-1]) || iscntrl(end[-1])))
|
||||
while (end > pager_name && (my_isspace(system_charset_info,end[-1]) ||
|
||||
my_iscntrl(system_charset_info,end[-1])))
|
||||
end--;
|
||||
end[0]=0;
|
||||
strmov(pager, pager_name);
|
||||
|
@ -2050,7 +2067,7 @@ com_connect(String *buffer, char *line)
|
|||
|
||||
if (buffer)
|
||||
{
|
||||
while (isspace(*line))
|
||||
while (my_isspace(system_charset_info,*line))
|
||||
line++;
|
||||
strnmov(buff,line,sizeof(buff)-1); // Don't destroy history
|
||||
if (buff[0] == '\\') // Short command
|
||||
|
@ -2096,15 +2113,16 @@ static int com_source(String *buffer, char *line)
|
|||
FILE *sql_file;
|
||||
|
||||
/* Skip space from file name */
|
||||
while (isspace(*line))
|
||||
while (my_isspace(system_charset_info,*line))
|
||||
line++;
|
||||
if (!(param = strchr(line, ' '))) // Skip command name
|
||||
return put_info("Usage: \\. <filename> | source <filename>",
|
||||
INFO_ERROR, 0);
|
||||
while (isspace(*param))
|
||||
while (my_isspace(system_charset_info,*param))
|
||||
param++;
|
||||
end=strmake(source_name,param,sizeof(source_name)-1);
|
||||
while (end > source_name && (isspace(end[-1]) || iscntrl(end[-1])))
|
||||
while (end > source_name && (my_isspace(system_charset_info,end[-1]) ||
|
||||
my_iscntrl(system_charset_info,end[-1])))
|
||||
end--;
|
||||
end[0]=0;
|
||||
unpack_filename(source_name,source_name);
|
||||
|
@ -2145,7 +2163,7 @@ com_use(String *buffer __attribute__((unused)), char *line)
|
|||
char *tmp;
|
||||
char buff[256];
|
||||
|
||||
while (isspace(*line))
|
||||
while (my_isspace(system_charset_info,*line))
|
||||
line++;
|
||||
strnmov(buff,line,sizeof(buff)-1); // Don't destroy history
|
||||
if (buff[0] == '\\') // Short command
|
||||
|
@ -2329,7 +2347,7 @@ com_status(String *buffer __attribute__((unused)),
|
|||
tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql));
|
||||
tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql));
|
||||
tee_fprintf(stdout, "Client characterset:\t%s\n",
|
||||
default_charset_info->name);
|
||||
system_charset_info->name);
|
||||
tee_fprintf(stdout, "Server characterset:\t%s\n", mysql.charset->name);
|
||||
if (strstr(mysql_get_host_info(&mysql),"TCP/IP") || ! mysql.unix_socket)
|
||||
tee_fprintf(stdout, "TCP port:\t\t%d\n", mysql.port);
|
||||
|
@ -2438,7 +2456,7 @@ static void remove_cntrl(String &buffer)
|
|||
{
|
||||
char *start,*end;
|
||||
end=(start=(char*) buffer.ptr())+buffer.length();
|
||||
while (start < end && !isgraph(end[-1]))
|
||||
while (start < end && !my_isgraph(system_charset_info,end[-1]))
|
||||
end--;
|
||||
buffer.length((uint) (end-start));
|
||||
}
|
||||
|
|
|
@ -518,7 +518,7 @@ static my_bool test_if_special_chars(const char *str)
|
|||
{
|
||||
#if MYSQL_VERSION_ID >= 32300
|
||||
for ( ; *str ; str++)
|
||||
if (!isvar(*str) && *str != '$')
|
||||
if (!my_isvar(system_charset_info,*str) && *str != '$')
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
|
@ -1036,7 +1036,8 @@ static void dumpTable(uint numFields, char *table)
|
|||
/* change any strings ("inf","nan",..) into NULL */
|
||||
char *ptr = row[i];
|
||||
dynstr_append(&extended_row,
|
||||
(!isalpha(*ptr)) ? ptr : "NULL");
|
||||
(!my_isalpha(system_charset_info,*ptr)) ?
|
||||
ptr : "NULL");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1068,9 +1069,11 @@ static void dumpTable(uint numFields, char *table)
|
|||
char *ptr = row[i];
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "\t\t<%s>%s</%s>\n",
|
||||
field->name,!isalpha(*ptr) ?ptr: "NULL",field->name);
|
||||
field->name,
|
||||
!my_isalpha(system_charset_info,*ptr) ?ptr: "NULL",field->name);
|
||||
else
|
||||
fputs((!isalpha(*ptr)) ? ptr : "NULL", md_result_file);
|
||||
fputs((!my_isalpha(system_charset_info,*ptr)) ?
|
||||
ptr : "NULL", md_result_file);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -311,7 +311,7 @@ static int eval_result = 0;
|
|||
void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
|
||||
void mysql_disable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
|
||||
int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; }
|
||||
int mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
|
||||
my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
|
||||
#endif
|
||||
|
||||
#define MAX_SERVER_ARGS 20
|
||||
|
@ -482,9 +482,9 @@ void init_parser()
|
|||
|
||||
int hex_val(int c)
|
||||
{
|
||||
if (isdigit(c))
|
||||
if (my_isdigit(system_charset_info,c))
|
||||
return c - '0';
|
||||
else if ((c = tolower(c)) >= 'a' && c <= 'f')
|
||||
else if ((c = my_tolower(system_charset_info,c)) >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
else
|
||||
return -1;
|
||||
|
@ -594,7 +594,7 @@ VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw,
|
|||
{
|
||||
const char* save_var_name = var_name, *end;
|
||||
end = (var_name_end) ? *var_name_end : 0;
|
||||
while (isvar(*var_name) && var_name != end)
|
||||
while (my_isvar(system_charset_info,*var_name) && var_name != end)
|
||||
++var_name;
|
||||
if (var_name == save_var_name)
|
||||
{
|
||||
|
@ -757,7 +757,7 @@ int do_server_op(struct st_query* q,const char* op)
|
|||
com_p=strmov(com_p,"_exec ");
|
||||
if (!*p)
|
||||
die("Missing server name in server_%s\n",op);
|
||||
while (*p && !isspace(*p))
|
||||
while (*p && !my_isspace(system_charset_info,*p))
|
||||
{
|
||||
*com_p++=*p++;
|
||||
}
|
||||
|
@ -790,7 +790,7 @@ int do_require_version(struct st_query* q)
|
|||
if (!*p)
|
||||
die("Missing version argument in require_version\n");
|
||||
ver_arg = p;
|
||||
while (*p && !isspace(*p))
|
||||
while (*p && !my_isspace(system_charset_info,*p))
|
||||
p++;
|
||||
*p = 0;
|
||||
ver_arg_len = p - ver_arg;
|
||||
|
@ -820,7 +820,7 @@ int do_source(struct st_query* q)
|
|||
if (!*p)
|
||||
die("Missing file name in source\n");
|
||||
name = p;
|
||||
while (*p && !isspace(*p))
|
||||
while (*p && !my_isspace(system_charset_info,*p))
|
||||
p++;
|
||||
*p = 0;
|
||||
|
||||
|
@ -1057,11 +1057,11 @@ int do_let(struct st_query* q)
|
|||
if (!*p)
|
||||
die("Missing variable name in let\n");
|
||||
var_name = p;
|
||||
while (*p && (*p != '=' || isspace(*p)))
|
||||
while (*p && (*p != '=' || my_isspace(system_charset_info,*p)))
|
||||
p++;
|
||||
var_name_end = p;
|
||||
if (*p == '=') p++;
|
||||
while (*p && isspace(*p))
|
||||
while (*p && my_isspace(system_charset_info,*p))
|
||||
p++;
|
||||
var_val_start = p;
|
||||
return var_set(var_name, var_name_end, var_val_start, q->end);
|
||||
|
@ -1090,8 +1090,8 @@ int do_disable_rpl_parse(struct st_query* q __attribute__((unused)))
|
|||
|
||||
int do_sleep(struct st_query* q, my_bool real_sleep)
|
||||
{
|
||||
char* p=q->first_argument;
|
||||
while (*p && isspace(*p))
|
||||
char *p=q->first_argument;
|
||||
while (*p && my_isspace(system_charset_info,*p))
|
||||
p++;
|
||||
if (!*p)
|
||||
die("Missing argument in sleep\n");
|
||||
|
@ -1107,7 +1107,7 @@ static void get_file_name(char *filename, struct st_query* q)
|
|||
char* p=q->first_argument;
|
||||
strnmov(filename, p, FN_REFLEN);
|
||||
/* Remove end space */
|
||||
while (p > filename && isspace(p[-1]))
|
||||
while (p > filename && my_isspace(system_charset_info,p[-1]))
|
||||
p--;
|
||||
p[0]=0;
|
||||
}
|
||||
|
@ -1193,7 +1193,7 @@ static char *get_string(char **to_ptr, char **from_ptr,
|
|||
if (*from != ' ' && *from)
|
||||
die("Wrong string argument in %s\n", q->query);
|
||||
|
||||
while (isspace(*from)) /* Point to next string */
|
||||
while (my_isspace(system_charset_info,*from)) /* Point to next string */
|
||||
from++;
|
||||
|
||||
*to =0; /* End of string marker */
|
||||
|
@ -1250,8 +1250,8 @@ static void get_replace(struct st_query *q)
|
|||
insert_pointer_name(&to_array,to);
|
||||
}
|
||||
for (i=1,pos=word_end_chars ; i < 256 ; i++)
|
||||
if (isspace(i))
|
||||
*pos++=i;
|
||||
if (my_isspace(system_charset_info,i))
|
||||
*pos++= i;
|
||||
*pos=0; /* End pointer */
|
||||
if (!(glob_replace=init_replace((char**) from_array.typelib.type_names,
|
||||
(char**) to_array.typelib.type_names,
|
||||
|
@ -1287,7 +1287,7 @@ int select_connection(char *p)
|
|||
if (!*p)
|
||||
die("Missing connection name in connect\n");
|
||||
name = p;
|
||||
while (*p && !isspace(*p))
|
||||
while (*p && !my_isspace(system_charset_info,*p))
|
||||
p++;
|
||||
*p = 0;
|
||||
|
||||
|
@ -1313,7 +1313,7 @@ int close_connection(struct st_query* q)
|
|||
if (!*p)
|
||||
die("Missing connection name in connect\n");
|
||||
name = p;
|
||||
while (*p && !isspace(*p))
|
||||
while (*p && !my_isspace(system_charset_info,*p))
|
||||
p++;
|
||||
*p = 0;
|
||||
|
||||
|
@ -1349,11 +1349,13 @@ int close_connection(struct st_query* q)
|
|||
char* safe_get_param(char* str, char** arg, const char* msg)
|
||||
{
|
||||
DBUG_ENTER("safe_get_param");
|
||||
while (*str && isspace(*str)) str++;
|
||||
while (*str && my_isspace(system_charset_info,*str))
|
||||
str++;
|
||||
*arg = str;
|
||||
for (; *str && *str != ',' && *str != ')' ; str++)
|
||||
{
|
||||
if (isspace(*str)) *str = 0;
|
||||
if (my_isspace(system_charset_info,*str))
|
||||
*str = 0;
|
||||
}
|
||||
if (!*str)
|
||||
die(msg);
|
||||
|
@ -1635,7 +1637,7 @@ int read_line(char* buf, int size)
|
|||
{
|
||||
state = R_COMMENT;
|
||||
}
|
||||
else if (isspace(c))
|
||||
else if (my_isspace(system_charset_info,c))
|
||||
{
|
||||
if (c == '\n')
|
||||
start_lineno= ++*lineno; /* Query hasn't started yet */
|
||||
|
@ -1761,7 +1763,7 @@ int read_query(struct st_query** q_ptr)
|
|||
{
|
||||
expected_errno = 0;
|
||||
p++;
|
||||
for (;isdigit(*p);p++)
|
||||
for (;my_isdigit(system_charset_info,*p);p++)
|
||||
expected_errno = expected_errno * 10 + *p - '0';
|
||||
q->expected_errno[0] = expected_errno;
|
||||
q->expected_errno[1] = 0;
|
||||
|
@ -1769,25 +1771,28 @@ int read_query(struct st_query** q_ptr)
|
|||
}
|
||||
}
|
||||
|
||||
while (*p && isspace(*p)) p++ ;
|
||||
while (*p && my_isspace(system_charset_info,*p))
|
||||
p++ ;
|
||||
if (*p == '@')
|
||||
{
|
||||
p++;
|
||||
p1 = q->record_file;
|
||||
while (!isspace(*p) &&
|
||||
while (!my_isspace(system_charset_info,*p) &&
|
||||
p1 < q->record_file + sizeof(q->record_file) - 1)
|
||||
*p1++ = *p++;
|
||||
*p1 = 0;
|
||||
}
|
||||
}
|
||||
while (*p && isspace(*p)) p++;
|
||||
while (*p && my_isspace(system_charset_info,*p))
|
||||
p++;
|
||||
if (!(q->query_buf=q->query=my_strdup(p,MYF(MY_WME))))
|
||||
die(NullS);
|
||||
|
||||
/* Calculate first word and first argument */
|
||||
for (p=q->query; *p && !isspace(*p) ; p++) ;
|
||||
for (p=q->query; *p && !my_isspace(system_charset_info,*p) ; p++) ;
|
||||
q->first_word_len = (uint) (p - q->query);
|
||||
while (*p && isspace(*p)) p++;
|
||||
while (*p && my_isspace(system_charset_info,*p))
|
||||
p++;
|
||||
q->first_argument=p;
|
||||
q->end = strend(q->query);
|
||||
parser.read_lines++;
|
||||
|
@ -2028,6 +2033,36 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
|
|||
dynstr_append_mem(ds, val, len);
|
||||
}
|
||||
|
||||
/*
|
||||
Append all results to the dynamic string separated with '\t'
|
||||
*/
|
||||
|
||||
static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
|
||||
{
|
||||
MYSQL_ROW row;
|
||||
int num_fields= mysql_num_fields(res);
|
||||
unsigned long *lengths;
|
||||
while ((row = mysql_fetch_row(res)))
|
||||
{
|
||||
int i;
|
||||
lengths = mysql_fetch_lengths(res);
|
||||
for (i = 0; i < num_fields; i++)
|
||||
{
|
||||
const char *val= row[i];
|
||||
ulonglong len= lengths[i];
|
||||
if (!val)
|
||||
{
|
||||
val = "NULL";
|
||||
len = 4;
|
||||
}
|
||||
if (i)
|
||||
dynstr_append_mem(ds, "\t", 1);
|
||||
replace_dynstr_append_mem(ds, val, len);
|
||||
}
|
||||
dynstr_append_mem(ds, "\n", 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* flags control the phased/stages of query execution to be performed
|
||||
|
@ -2038,12 +2073,7 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
|
|||
int run_query(MYSQL* mysql, struct st_query* q, int flags)
|
||||
{
|
||||
MYSQL_RES* res = 0;
|
||||
MYSQL_FIELD* fields;
|
||||
MYSQL_ROW row;
|
||||
int num_fields,i, error = 0;
|
||||
unsigned long* lengths;
|
||||
char* val;
|
||||
int len;
|
||||
int i, error = 0;
|
||||
DYNAMIC_STRING *ds;
|
||||
DYNAMIC_STRING ds_tmp;
|
||||
DYNAMIC_STRING eval_query;
|
||||
|
@ -2152,45 +2182,37 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (!res)
|
||||
goto end;
|
||||
|
||||
if (!disable_result_log)
|
||||
if (!disable_result_log && res)
|
||||
{
|
||||
fields = mysql_fetch_fields(res);
|
||||
num_fields = mysql_num_fields(res);
|
||||
int num_fields= mysql_num_fields(res);
|
||||
MYSQL_FIELD *fields= mysql_fetch_fields(res);
|
||||
for (i = 0; i < num_fields; i++)
|
||||
{
|
||||
if (i)
|
||||
dynstr_append_mem(ds, "\t", 1);
|
||||
dynstr_append(ds, fields[i].name);
|
||||
}
|
||||
|
||||
dynstr_append_mem(ds, "\n", 1);
|
||||
|
||||
while ((row = mysql_fetch_row(res)))
|
||||
{
|
||||
lengths = mysql_fetch_lengths(res);
|
||||
for (i = 0; i < num_fields; i++)
|
||||
{
|
||||
val = (char*)row[i];
|
||||
len = lengths[i];
|
||||
|
||||
if (!val)
|
||||
{
|
||||
val = (char*)"NULL";
|
||||
len = 4;
|
||||
}
|
||||
|
||||
if (i)
|
||||
dynstr_append_mem(ds, "\t", 1);
|
||||
replace_dynstr_append_mem(ds, val, len);
|
||||
}
|
||||
dynstr_append_mem(ds, "\n", 1);
|
||||
}
|
||||
if (glob_replace)
|
||||
free_replace();
|
||||
append_result(ds, res);
|
||||
}
|
||||
|
||||
/* Add all warnings to the result */
|
||||
if (!disable_result_log && mysql_warning_count(mysql))
|
||||
{
|
||||
MYSQL_RES *warn_res= mysql_warnings(mysql);
|
||||
if (!warn_res)
|
||||
verbose_msg("Warning count is %d but didn't get any warnings\n",
|
||||
mysql_warning_count(mysql));
|
||||
else
|
||||
{
|
||||
dynstr_append_mem(ds, "Warnings:\n", 10);
|
||||
append_result(ds, warn_res);
|
||||
mysql_free_result(warn_res);
|
||||
}
|
||||
}
|
||||
if (glob_replace)
|
||||
free_replace();
|
||||
|
||||
if (record)
|
||||
{
|
||||
if (!q->record_file[0] && !result_file)
|
||||
|
@ -2301,7 +2323,8 @@ static void var_from_env(const char* name, const char* def_val)
|
|||
static void init_var_hash()
|
||||
{
|
||||
VAR* v;
|
||||
if (hash_init(&var_hash, 1024, 0, 0, get_var_key, var_free, MYF(0)))
|
||||
if (hash_init(&var_hash, system_charset_info,
|
||||
1024, 0, 0, get_var_key, var_free, MYF(0)))
|
||||
die("Variable hash initialization failed");
|
||||
var_from_env("MASTER_MYPORT", "9306");
|
||||
var_from_env("SLAVE_MYPORT", "9307");
|
||||
|
|
|
@ -234,7 +234,7 @@ bool String::fill(uint32 max_length,char fill_char)
|
|||
|
||||
void String::strip_sp()
|
||||
{
|
||||
while (str_length && isspace(Ptr[str_length-1]))
|
||||
while (str_length && my_isspace(str_charset,Ptr[str_length-1]))
|
||||
str_length--;
|
||||
}
|
||||
|
||||
|
@ -296,10 +296,10 @@ uint32 String::numchars()
|
|||
register uint32 n=0,mblen;
|
||||
register const char *mbstr=Ptr;
|
||||
register const char *end=mbstr+str_length;
|
||||
if (use_mb(default_charset_info))
|
||||
if (use_mb(str_charset))
|
||||
{
|
||||
while (mbstr < end) {
|
||||
if ((mblen=my_ismbchar(default_charset_info, mbstr,end))) mbstr+=mblen;
|
||||
if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen;
|
||||
else ++mbstr;
|
||||
++n;
|
||||
}
|
||||
|
@ -316,11 +316,11 @@ int String::charpos(int i,uint32 offset)
|
|||
register uint32 mblen;
|
||||
register const char *mbstr=Ptr+offset;
|
||||
register const char *end=Ptr+str_length;
|
||||
if (use_mb(default_charset_info))
|
||||
if (use_mb(str_charset))
|
||||
{
|
||||
if (i<=0) return i;
|
||||
while (i && mbstr < end) {
|
||||
if ((mblen=my_ismbchar(default_charset_info, mbstr,end))) mbstr+=mblen;
|
||||
if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen;
|
||||
else ++mbstr;
|
||||
--i;
|
||||
}
|
||||
|
@ -361,6 +361,39 @@ skipp:
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
Search after a string without regarding to case
|
||||
This needs to be replaced when we have character sets per string
|
||||
*/
|
||||
|
||||
int String::strstr_case(const String &s,uint32 offset)
|
||||
{
|
||||
if (s.length()+offset <= str_length)
|
||||
{
|
||||
if (!s.length())
|
||||
return ((int) offset); // Empty string is always found
|
||||
|
||||
register const char *str = Ptr+offset;
|
||||
register const char *search=s.ptr();
|
||||
const char *end=Ptr+str_length-s.length()+1;
|
||||
const char *search_end=s.ptr()+s.length();
|
||||
skipp:
|
||||
while (str != end)
|
||||
{
|
||||
if (str_charset->sort_order[*str++] == str_charset->sort_order[*search])
|
||||
{
|
||||
register char *i,*j;
|
||||
i=(char*) str; j=(char*) search+1;
|
||||
while (j != search_end)
|
||||
if (str_charset->sort_order[*i++] !=
|
||||
str_charset->sort_order[*j++])
|
||||
goto skipp;
|
||||
return (int) (str-Ptr) -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Search string from end. Offset is offset to the end of string
|
||||
|
@ -428,6 +461,44 @@ bool String::replace(uint32 offset,uint32 arg_length,const String &to)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
// added by Holyfoot for "geometry" needs
|
||||
int String::reserve(uint32 space_needed, uint32 grow_by)
|
||||
{
|
||||
if (Alloced_length < str_length + space_needed)
|
||||
{
|
||||
if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void String::qs_append(const char *str)
|
||||
{
|
||||
int len = strlen(str);
|
||||
memcpy(Ptr + str_length, str, len + 1);
|
||||
str_length += len;
|
||||
}
|
||||
|
||||
void String::qs_append(double d)
|
||||
{
|
||||
char *buff = Ptr + str_length;
|
||||
sprintf(buff,"%.14g", d);
|
||||
str_length += strlen(buff);
|
||||
}
|
||||
|
||||
void String::qs_append(double *d)
|
||||
{
|
||||
double ld;
|
||||
float8get(ld, d);
|
||||
qs_append(ld);
|
||||
}
|
||||
|
||||
void String::qs_append(const char &c)
|
||||
{
|
||||
Ptr[str_length] = c;
|
||||
str_length += sizeof(c);
|
||||
}
|
||||
|
||||
|
||||
int sortcmp(const String *x,const String *y)
|
||||
{
|
||||
|
@ -436,15 +507,15 @@ int sortcmp(const String *x,const String *y)
|
|||
uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
|
||||
|
||||
#ifdef USE_STRCOLL
|
||||
if (use_strcoll(default_charset_info))
|
||||
if (use_strcoll(x->str_charset))
|
||||
{
|
||||
#ifndef CMP_ENDSPACE
|
||||
while (x_len && isspace(s[x_len-1]))
|
||||
while (x_len && my_isspace(x->str_charset,s[x_len-1]))
|
||||
x_len--;
|
||||
while (y_len && isspace(t[y_len-1]))
|
||||
while (y_len && my_isspace(x->str_charset,t[y_len-1]))
|
||||
y_len--;
|
||||
#endif
|
||||
return my_strnncoll(default_charset_info,
|
||||
return my_strnncoll(x->str_charset,
|
||||
(unsigned char *)s,x_len,(unsigned char *)t,y_len);
|
||||
}
|
||||
else
|
||||
|
@ -454,9 +525,10 @@ int sortcmp(const String *x,const String *y)
|
|||
y_len-=len;
|
||||
while (len--)
|
||||
{
|
||||
if (my_sort_order[(uchar) *s++] != my_sort_order[(uchar) *t++])
|
||||
return ((int) my_sort_order[(uchar) s[-1]] -
|
||||
(int) my_sort_order[(uchar) t[-1]]);
|
||||
if (x->str_charset->sort_order[(uchar) *s++] !=
|
||||
x->str_charset->sort_order[(uchar) *t++])
|
||||
return ((int) x->str_charset->sort_order[(uchar) s[-1]] -
|
||||
(int) x->str_charset->sort_order[(uchar) t[-1]]);
|
||||
}
|
||||
#ifndef CMP_ENDSPACE
|
||||
/* Don't compare end space in strings */
|
||||
|
@ -465,14 +537,14 @@ int sortcmp(const String *x,const String *y)
|
|||
{
|
||||
const char *end=t+y_len;
|
||||
for (; t != end ; t++)
|
||||
if (!isspace(*t))
|
||||
if (!my_isspace(x->str_charset,*t))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *end=s+x_len;
|
||||
for (; s != end ; s++)
|
||||
if (!isspace(*s))
|
||||
if (!my_isspace(x->str_charset,*s))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -520,11 +592,10 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
|
|||
/* Make it easier to handle different charactersets */
|
||||
|
||||
#ifdef USE_MB
|
||||
#define INC_PTR(A,B) A+=((use_mb_flag && \
|
||||
my_ismbchar(default_charset_info,A,B)) ? \
|
||||
my_ismbchar(default_charset_info,A,B) : 1)
|
||||
#define INC_PTR(cs,A,B) A+=((use_mb_flag && \
|
||||
my_ismbchar(cs,A,B)) ? my_ismbchar(cs,A,B) : 1)
|
||||
#else
|
||||
#define INC_PTR(A,B) A++
|
||||
#define INC_PTR(cs,A,B) A++
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -535,18 +606,18 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
|
|||
*/
|
||||
|
||||
#ifdef LIKE_CMP_TOUPPER
|
||||
#define likeconv(A) (uchar) toupper(A)
|
||||
#define likeconv(s,A) (uchar) my_toupper(s,A)
|
||||
#else
|
||||
#define likeconv(A) (uchar) my_sort_order[(uchar) (A)]
|
||||
#define likeconv(s,A) (uchar) (s)->sort_order[(uchar) (A)]
|
||||
#endif
|
||||
|
||||
static int wild_case_compare(const char *str,const char *str_end,
|
||||
const char *wildstr,const char *wildend,
|
||||
char escape)
|
||||
int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *str_end,
|
||||
const char *wildstr,const char *wildend,
|
||||
char escape)
|
||||
{
|
||||
int result= -1; // Not found, using wildcards
|
||||
#ifdef USE_MB
|
||||
bool use_mb_flag=use_mb(default_charset_info);
|
||||
bool use_mb_flag=use_mb(cs);
|
||||
#endif
|
||||
while (wildstr != wildend)
|
||||
{
|
||||
|
@ -557,7 +628,7 @@ static int wild_case_compare(const char *str,const char *str_end,
|
|||
#ifdef USE_MB
|
||||
int l;
|
||||
if (use_mb_flag &&
|
||||
(l = my_ismbchar(default_charset_info, wildstr, wildend)))
|
||||
(l = my_ismbchar(cs, wildstr, wildend)))
|
||||
{
|
||||
if (str+l > str_end || memcmp(str, wildstr, l) != 0)
|
||||
return 1;
|
||||
|
@ -566,7 +637,7 @@ static int wild_case_compare(const char *str,const char *str_end,
|
|||
}
|
||||
else
|
||||
#endif
|
||||
if (str == str_end || likeconv(*wildstr++) != likeconv(*str++))
|
||||
if (str == str_end || likeconv(cs,*wildstr++) != likeconv(cs,*str++))
|
||||
return(1); // No match
|
||||
if (wildstr == wildend)
|
||||
return (str != str_end); // Match if both are at end
|
||||
|
@ -576,9 +647,9 @@ static int wild_case_compare(const char *str,const char *str_end,
|
|||
{
|
||||
do
|
||||
{
|
||||
if (str == str_end) // Skipp one char if possible
|
||||
if (str == str_end) // Skip one char if possible
|
||||
return (result);
|
||||
INC_PTR(str,str_end);
|
||||
INC_PTR(cs,str,str_end);
|
||||
} while (++wildstr < wildend && *wildstr == wild_one);
|
||||
if (wildstr == wildend)
|
||||
break;
|
||||
|
@ -595,7 +666,7 @@ static int wild_case_compare(const char *str,const char *str_end,
|
|||
{
|
||||
if (str == str_end)
|
||||
return (-1);
|
||||
INC_PTR(str,str_end);
|
||||
INC_PTR(cs,str,str_end);
|
||||
continue;
|
||||
}
|
||||
break; // Not a wild character
|
||||
|
@ -613,10 +684,10 @@ static int wild_case_compare(const char *str,const char *str_end,
|
|||
int mblen;
|
||||
LINT_INIT(mblen);
|
||||
if (use_mb_flag)
|
||||
mblen = my_ismbchar(default_charset_info, wildstr, wildend);
|
||||
mblen = my_ismbchar(cs, wildstr, wildend);
|
||||
#endif
|
||||
INC_PTR(wildstr,wildend); // This is compared trough cmp
|
||||
cmp=likeconv(cmp);
|
||||
INC_PTR(cs,wildstr,wildend); // This is compared trough cmp
|
||||
cmp=likeconv(cs,cmp);
|
||||
do
|
||||
{
|
||||
#ifdef USE_MB
|
||||
|
@ -634,26 +705,26 @@ static int wild_case_compare(const char *str,const char *str_end,
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if (!my_ismbchar(default_charset_info, str, str_end) &&
|
||||
likeconv(*str) == cmp)
|
||||
else if (!my_ismbchar(cs, str, str_end) &&
|
||||
likeconv(cs,*str) == cmp)
|
||||
{
|
||||
str++;
|
||||
break;
|
||||
}
|
||||
INC_PTR(str, str_end);
|
||||
INC_PTR(cs,str, str_end);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* USE_MB */
|
||||
while (str != str_end && likeconv(*str) != cmp)
|
||||
while (str != str_end && likeconv(cs,*str) != cmp)
|
||||
str++;
|
||||
if (str++ == str_end) return (-1);
|
||||
#ifdef USE_MB
|
||||
}
|
||||
#endif
|
||||
{
|
||||
int tmp=wild_case_compare(str,str_end,wildstr,wildend,escape);
|
||||
int tmp=wild_case_compare(cs,str,str_end,wildstr,wildend,escape);
|
||||
if (tmp <= 0)
|
||||
return (tmp);
|
||||
}
|
||||
|
@ -667,17 +738,23 @@ static int wild_case_compare(const char *str,const char *str_end,
|
|||
|
||||
int wild_case_compare(String &match,String &wild, char escape)
|
||||
{
|
||||
return wild_case_compare(match.ptr(),match.ptr()+match.length(),
|
||||
wild.ptr(), wild.ptr()+wild.length(),escape);
|
||||
DBUG_ENTER("wild_case_compare");
|
||||
DBUG_PRINT("enter",("match='%s', wild='%s', escape='%c'"
|
||||
,match.ptr(),wild.ptr(),escape));
|
||||
DBUG_RETURN(wild_case_compare(match.str_charset,match.ptr(),match.ptr()+match.length(),
|
||||
wild.ptr(), wild.ptr()+wild.length(),escape));
|
||||
}
|
||||
|
||||
/*
|
||||
** The following is used when using LIKE on binary strings
|
||||
*/
|
||||
|
||||
static int wild_compare(const char *str,const char *str_end,
|
||||
const char *wildstr,const char *wildend,char escape)
|
||||
int wild_compare(const char *str,const char *str_end,
|
||||
const char *wildstr,const char *wildend,char escape)
|
||||
{
|
||||
DBUG_ENTER("wild_compare");
|
||||
DBUG_PRINT("enter",("str='%s', str_end='%s', wildstr='%s', wildend='%s', escape='%c'"
|
||||
,str,str_end,wildstr,wildend,escape));
|
||||
int result= -1; // Not found, using wildcards
|
||||
while (wildstr != wildend)
|
||||
{
|
||||
|
@ -686,17 +763,21 @@ static int wild_compare(const char *str,const char *str_end,
|
|||
if (*wildstr == escape && wildstr+1 != wildend)
|
||||
wildstr++;
|
||||
if (str == str_end || *wildstr++ != *str++)
|
||||
return(1);
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (wildstr == wildend)
|
||||
return (str != str_end); // Match if both are at end
|
||||
{
|
||||
DBUG_RETURN(str != str_end); // Match if both are at end
|
||||
}
|
||||
result=1; // Found an anchor char
|
||||
}
|
||||
if (*wildstr == wild_one)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (str == str_end) // Skipp one char if possible
|
||||
return (result);
|
||||
if (str == str_end) // Skip one char if possible
|
||||
DBUG_RETURN(result);
|
||||
str++;
|
||||
} while (*++wildstr == wild_one && wildstr != wildend);
|
||||
if (wildstr == wildend)
|
||||
|
@ -713,17 +794,22 @@ static int wild_compare(const char *str,const char *str_end,
|
|||
if (*wildstr == wild_one)
|
||||
{
|
||||
if (str == str_end)
|
||||
return (-1);
|
||||
{
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
str++;
|
||||
continue;
|
||||
}
|
||||
break; // Not a wild character
|
||||
}
|
||||
if (wildstr == wildend)
|
||||
return(0); // Ok if wild_many is last
|
||||
{
|
||||
DBUG_RETURN(0); // Ok if wild_many is last
|
||||
}
|
||||
if (str == str_end)
|
||||
return -1;
|
||||
|
||||
{
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
char cmp;
|
||||
if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
|
||||
cmp= *++wildstr;
|
||||
|
@ -732,22 +818,32 @@ static int wild_compare(const char *str,const char *str_end,
|
|||
{
|
||||
while (str != str_end && *str != cmp)
|
||||
str++;
|
||||
if (str++ == str_end) return (-1);
|
||||
if (str++ == str_end)
|
||||
{
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
{
|
||||
int tmp=wild_compare(str,str_end,wildstr,wildend,escape);
|
||||
if (tmp <= 0)
|
||||
return (tmp);
|
||||
{
|
||||
DBUG_RETURN(tmp);
|
||||
}
|
||||
}
|
||||
} while (str != str_end && wildstr[0] != wild_many);
|
||||
return(-1);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
}
|
||||
return (str != str_end ? 1 : 0);
|
||||
DBUG_RETURN(str != str_end ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
int wild_compare(String &match,String &wild, char escape)
|
||||
{
|
||||
return wild_compare(match.ptr(),match.ptr()+match.length(),
|
||||
wild.ptr(), wild.ptr()+wild.length(),escape);
|
||||
DBUG_ENTER("wild_compare");
|
||||
DBUG_PRINT("enter",("match='%s', wild='%s', escape='%c'"
|
||||
,match.ptr(),wild.ptr(),escape));
|
||||
DBUG_RETURN(wild_compare(match.ptr(),match.ptr()+match.length(),
|
||||
wild.ptr(), wild.ptr()+wild.length(),escape));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,31 +24,57 @@
|
|||
#define NOT_FIXED_DEC 31
|
||||
#endif
|
||||
|
||||
class String;
|
||||
int sortcmp(const String *a,const String *b);
|
||||
int stringcmp(const String *a,const String *b);
|
||||
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
|
||||
int wild_case_compare(String &match,String &wild,char escape);
|
||||
int wild_compare(String &match,String &wild,char escape);
|
||||
|
||||
class String
|
||||
{
|
||||
char *Ptr;
|
||||
uint32 str_length,Alloced_length;
|
||||
bool alloced;
|
||||
CHARSET_INFO *str_charset;
|
||||
public:
|
||||
String()
|
||||
{ Ptr=0; str_length=Alloced_length=0; alloced=0; }
|
||||
{
|
||||
Ptr=0; str_length=Alloced_length=0; alloced=0;
|
||||
str_charset=default_charset_info;
|
||||
}
|
||||
String(uint32 length_arg)
|
||||
{ alloced=0; Alloced_length=0; (void) real_alloc(length_arg); }
|
||||
{
|
||||
alloced=0; Alloced_length=0; (void) real_alloc(length_arg);
|
||||
str_charset=default_charset_info;
|
||||
}
|
||||
String(const char *str)
|
||||
{ Ptr=(char*) str; str_length=(uint) strlen(str); Alloced_length=0; alloced=0;}
|
||||
{
|
||||
Ptr=(char*) str; str_length=(uint) strlen(str); Alloced_length=0; alloced=0;
|
||||
str_charset=default_charset_info;
|
||||
}
|
||||
String(const char *str,uint32 len)
|
||||
{ Ptr=(char*) str; str_length=len; Alloced_length=0; alloced=0;}
|
||||
{
|
||||
Ptr=(char*) str; str_length=len; Alloced_length=0; alloced=0;
|
||||
str_charset=default_charset_info;
|
||||
}
|
||||
String(char *str,uint32 len)
|
||||
{ Ptr=(char*) str; Alloced_length=str_length=len; alloced=0;}
|
||||
{
|
||||
Ptr=(char*) str; Alloced_length=str_length=len; alloced=0;
|
||||
str_charset=default_charset_info;
|
||||
}
|
||||
String(const String &str)
|
||||
{ Ptr=str.Ptr ; str_length=str.str_length ;
|
||||
Alloced_length=str.Alloced_length; alloced=0; }
|
||||
|
||||
{
|
||||
Ptr=str.Ptr ; str_length=str.str_length ;
|
||||
Alloced_length=str.Alloced_length; alloced=0;
|
||||
str_charset=str.str_charset;
|
||||
}
|
||||
static void *operator new(size_t size) { return (void*) sql_alloc((uint) size); }
|
||||
static void operator delete(void *ptr_arg,size_t size) /*lint -e715 */
|
||||
{ sql_element_free(ptr_arg); }
|
||||
~String() { free(); }
|
||||
|
||||
inline CHARSET_INFO *charset() const { return str_charset; }
|
||||
inline uint32 length() const { return str_length;}
|
||||
inline uint32 alloced_length() const { return Alloced_length;}
|
||||
inline char& operator [] (uint32 i) const { return Ptr[i]; }
|
||||
|
@ -124,7 +150,7 @@ public:
|
|||
char *new_ptr;
|
||||
if (!(new_ptr=(char*) my_realloc(Ptr,arg_length,MYF(0))))
|
||||
{
|
||||
(void) my_free(Ptr,MYF(0));
|
||||
Alloced_length = 0;
|
||||
real_alloc(arg_length);
|
||||
}
|
||||
else
|
||||
|
@ -153,6 +179,7 @@ public:
|
|||
bool append(const char *s,uint32 arg_length=0);
|
||||
bool append(IO_CACHE* file, uint32 arg_length);
|
||||
int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
|
||||
int strstr_case(const String &s,uint32 offset=0);
|
||||
int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
|
||||
bool replace(uint32 offset,uint32 arg_length,const String &to);
|
||||
inline bool append(char chr)
|
||||
|
@ -171,8 +198,8 @@ public:
|
|||
}
|
||||
bool fill(uint32 max_length,char fill);
|
||||
void strip_sp();
|
||||
inline void caseup() { ::caseup(Ptr,str_length); }
|
||||
inline void casedn() { ::casedn(Ptr,str_length); }
|
||||
inline void caseup() { my_caseup(str_charset,Ptr,str_length); }
|
||||
inline void casedn() { my_casedn(str_charset,Ptr,str_length); }
|
||||
friend int sortcmp(const String *a,const String *b);
|
||||
friend int stringcmp(const String *a,const String *b);
|
||||
friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
|
||||
|
@ -180,4 +207,49 @@ public:
|
|||
friend int wild_compare(String &match,String &wild,char escape);
|
||||
uint32 numchars();
|
||||
int charpos(int i,uint32 offset=0);
|
||||
|
||||
// added by Holyfoot for "geometry" needs
|
||||
int reserve(uint32 space_needed)
|
||||
{
|
||||
return realloc(str_length + space_needed);
|
||||
}
|
||||
int reserve(uint32 space_needed, uint32 grow_by);
|
||||
|
||||
// these append operations do NOT check alloced memory
|
||||
// q_*** methods writes values of parameters itself
|
||||
// qs_*** methods writes string representation of value
|
||||
void q_append(const char &c)
|
||||
{
|
||||
Ptr[str_length++] = c;
|
||||
}
|
||||
void q_append(const uint32 &n)
|
||||
{
|
||||
int4store(Ptr + str_length, n);
|
||||
str_length += 4;
|
||||
}
|
||||
void q_append(double d)
|
||||
{
|
||||
float8store(Ptr + str_length, d);
|
||||
str_length += 8;
|
||||
}
|
||||
void q_append(double *d)
|
||||
{
|
||||
float8store(Ptr + str_length, *d);
|
||||
str_length += 8;
|
||||
}
|
||||
void q_append(const char *data, uint32 data_len)
|
||||
{
|
||||
memcpy(Ptr + str_length, data, data_len);
|
||||
str_length += data_len;
|
||||
}
|
||||
|
||||
void WriteAtPosition(int position, uint32 value)
|
||||
{
|
||||
int4store(Ptr + position,value);
|
||||
}
|
||||
|
||||
void qs_append(const char *str);
|
||||
void qs_append(double d);
|
||||
void qs_append(double *d);
|
||||
void qs_append(const char &c);
|
||||
};
|
||||
|
|
343
configure.in
343
configure.in
|
@ -4,13 +4,13 @@ dnl Process this file with autoconf to produce a configure script.
|
|||
AC_INIT(sql/mysqld.cc)
|
||||
AC_CANONICAL_SYSTEM
|
||||
# The Docs Makefile.am parses this line!
|
||||
AM_INIT_AUTOMAKE(mysql, 4.0.5-beta)
|
||||
AM_INIT_AUTOMAKE(mysql, 4.1.0-alpha)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
PROTOCOL_VERSION=10
|
||||
DOT_FRM_VERSION=6
|
||||
# See the libtool docs for information on how to do shared lib versions.
|
||||
SHARED_LIB_VERSION=11:0:0
|
||||
SHARED_LIB_VERSION=12:0:0
|
||||
|
||||
# Set all version vars based on $VERSION. How do we do this more elegant ?
|
||||
# Remember that regexps needs to quote [ and ] since this is run through m4
|
||||
|
@ -654,10 +654,13 @@ AC_ARG_WITH(mysqld-user,
|
|||
AC_SUBST(MYSQLD_USER)
|
||||
|
||||
# If we should allow LOAD DATA LOCAL
|
||||
AC_MSG_CHECKING(if we should should enable LOAD DATA LOCAL by default)
|
||||
AC_MSG_CHECKING(If we should should enable LOAD DATA LOCAL by default)
|
||||
AC_ARG_ENABLE(local-infile,
|
||||
[ --enable-local-infile Enable LOAD DATA LOCAL INFILE (default: disabled)],
|
||||
[ ENABLED_LOCAL_INFILE=$enableval ],
|
||||
Enable LOAD DATA LOCAL INFILE (default: disabled)],
|
||||
[
|
||||
ENABLED_LOCAL_INFILE=$enableval
|
||||
AC_DEFINE(ENABLED_LOCAL_INFILE)
|
||||
],
|
||||
[ ENABLED_LOCAL_INFILE=no ]
|
||||
)
|
||||
if test "$ENABLED_LOCAL_INFILE" = "yes"
|
||||
|
@ -1979,18 +1982,20 @@ fi
|
|||
AC_SUBST(readline_dir)
|
||||
AC_SUBST(readline_link)
|
||||
|
||||
|
||||
dnl In order to add new charset, you must add charset name to
|
||||
dnl this CHARSETS_AVAILABLE list and sql/share/charsets/Index.
|
||||
dnl If the character set uses strcoll or other special handling,
|
||||
dnl you must also create strings/ctype-$charset_name.c
|
||||
|
||||
AC_DIVERT_PUSH(0)
|
||||
CHARSETS_AVAILABLE="big5 cp1251 cp1257
|
||||
CHARSETS_AVAILABLE="armscii8 big5 cp1251 cp1257
|
||||
croat czech danish dec8 dos estonia euc_kr gb2312 gbk
|
||||
german1 greek hebrew hp8 hungarian koi8_ru koi8_ukr
|
||||
latin1 latin1_de latin2 latin5 sjis swe7 tis620 ujis
|
||||
usa7 win1250 win1251ukr"
|
||||
latin1 latin1_de latin2 latin5 sjis swe7 tis620 ucs2 ujis
|
||||
usa7 utf8 win1250 win1250ch win1251ukr"
|
||||
CHARSETS_DEPRECATED="win1251"
|
||||
CHARSETS_COMPLEX="big5 czech euc_kr gb2312 gbk latin1_de sjis tis620 ucs2 ujis utf8 win1250ch"
|
||||
DEFAULT_CHARSET=latin1
|
||||
AC_DIVERT_POP
|
||||
|
||||
|
@ -2014,208 +2019,154 @@ AC_MSG_CHECKING("character sets")
|
|||
if test "$extra_charsets" = none; then
|
||||
CHARSETS=""
|
||||
elif test "$extra_charsets" = complex; then
|
||||
CHARSETS=`/bin/ls -1 $srcdir/strings/ctype-*.c | \
|
||||
sed -e 's;^.*/ctype-;;' -e 's;.c$;;'`
|
||||
CHARSETS=`echo $CHARSETS` # get rid of line breaks
|
||||
CHARSETS="$CHARSETS_COMPLEX"
|
||||
elif test "$extra_charsets" = all; then
|
||||
CHARSETS="$CHARSETS_AVAILABLE $CHARSETS_DEPRECATED"
|
||||
else
|
||||
if test "$extra_charsets" = all; then
|
||||
CHARSETS="$CHARSETS_AVAILABLE $CHARSETS_DEPRECATED"
|
||||
else
|
||||
CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'`
|
||||
fi
|
||||
CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'`
|
||||
fi
|
||||
|
||||
# Ensure that the default_charset is first in CHARSETS
|
||||
TMP_CHARSETS="$default_charset "
|
||||
for i in $CHARSETS
|
||||
do
|
||||
if test $i != $default_charset
|
||||
then
|
||||
TMP_CHARSETS="$TMP_CHARSETS $i"
|
||||
fi
|
||||
done
|
||||
CHARSETS=$TMP_CHARSETS
|
||||
CHARSETS="$DEFAULT_CHARSET $CHARSETS"
|
||||
|
||||
use_mb="no"
|
||||
|
||||
# Check if charsets are all good
|
||||
for cs in $CHARSETS
|
||||
do
|
||||
charset_okay=0
|
||||
for charset in $CHARSETS_AVAILABLE $CHARSETS_DEPRECATED
|
||||
do
|
||||
if test $cs = $charset; then charset_okay=1; fi
|
||||
done
|
||||
if test $charset_okay = 0;
|
||||
then
|
||||
AC_MSG_ERROR([Charset $cs not available. (Available $CHARSETS_AVAILABLE).
|
||||
See the Installation chapter in the Reference Manual.]);
|
||||
fi
|
||||
done
|
||||
|
||||
CHARSET_SRCS=""
|
||||
CHARSETS_NEED_SOURCE=""
|
||||
CHARSET_DECLARATIONS=""
|
||||
CHARSET_COMP_CS_INIT="CHARSET_INFO compiled_charsets[[]] = {"
|
||||
|
||||
want_use_strcoll=0
|
||||
want_use_mb=0
|
||||
|
||||
index_file="$srcdir/sql/share/charsets/Index"
|
||||
|
||||
for c in $CHARSETS
|
||||
do
|
||||
# get the charset number from $index_file
|
||||
changequote(,)dnl
|
||||
subpat='^'"${c}"'[ ][ ]*\([0-9][0-9]*\)[^0-9]*$'
|
||||
number=`sed -e "/$subpat/!d" -e 's//\1/' $index_file`
|
||||
changequote([,])dnl
|
||||
# some sanity checking....
|
||||
if test X"$number" = X
|
||||
then
|
||||
AC_MSG_ERROR([No number was found in $index_file for the $c character set. This is a bug in the MySQL distribution. Please report this message to bugs@lists.mysql.com.])
|
||||
fi
|
||||
|
||||
cs_file="$srcdir/strings/ctype-$c.c"
|
||||
if test -f $cs_file
|
||||
then
|
||||
CHARSET_SRCS="${CHARSET_SRCS}ctype-$c.c "
|
||||
# get the strxfrm multiplier and max mb len from files
|
||||
subpat='^.*\\.configure\\. strxfrm_multiply_'"${c}"'='
|
||||
strx=`$AWK 'sub("'"$subpat"'", "") { print }' $cs_file`
|
||||
subpat='^.*\\.configure\\. mbmaxlen_'"${c}"'='
|
||||
maxl=`$AWK 'sub("'"$subpat"'", "") { print }' $cs_file`
|
||||
|
||||
CHARSET_DECLARATIONS="$CHARSET_DECLARATIONS
|
||||
|
||||
/* declarations for the ${c} character set, filled in by configure */
|
||||
extern uchar ctype_${c}[[]], to_lower_${c}[[]], to_upper_${c}[[]], sort_order_${c}[[]];"
|
||||
else
|
||||
CHARSETS_NEED_SOURCE="$CHARSETS_NEED_SOURCE $c"
|
||||
strx=''
|
||||
maxl=''
|
||||
fi
|
||||
|
||||
CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
|
||||
|
||||
/* this information is filled in by configure */
|
||||
{
|
||||
$number, /* number */
|
||||
\"$c\", /* name */
|
||||
ctype_${c},
|
||||
to_lower_${c},
|
||||
to_upper_${c},
|
||||
sort_order_${c},"
|
||||
|
||||
if test -n "$strx"
|
||||
then
|
||||
want_use_strcoll=1
|
||||
|
||||
CHARSET_DECLARATIONS="$CHARSET_DECLARATIONS
|
||||
extern int my_strcoll_${c}(const uchar *, const uchar *);
|
||||
extern int my_strxfrm_${c}(uchar *, const uchar *, int);
|
||||
extern int my_strnncoll_${c}(const uchar *, int, const uchar *, int);
|
||||
extern int my_strnxfrm_${c}(uchar *, const uchar *, int, int);
|
||||
extern my_bool my_like_range_${c}(const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);"
|
||||
|
||||
CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
|
||||
$strx, /* strxfrm_multiply */
|
||||
my_strcoll_${c},
|
||||
my_strxfrm_${c},
|
||||
my_strnncoll_${c},
|
||||
my_strnxfrm_${c},
|
||||
my_like_range_${c},"
|
||||
else
|
||||
CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
|
||||
0, /* strxfrm_multiply */
|
||||
NULL, /* strcoll */
|
||||
NULL, /* strxfrm */
|
||||
NULL, /* strnncoll */
|
||||
NULL, /* strnxfrm */
|
||||
NULL, /* like_range */"
|
||||
fi
|
||||
|
||||
if test -n "$maxl"
|
||||
then
|
||||
want_use_mb=1
|
||||
|
||||
CHARSET_DECLARATIONS="$CHARSET_DECLARATIONS
|
||||
extern int ismbchar_${c}(const char *, const char *);
|
||||
extern my_bool ismbhead_${c}(uint);
|
||||
extern int mbcharlen_${c}(uint);"
|
||||
|
||||
|
||||
CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
|
||||
$maxl, /* mbmaxlen */
|
||||
ismbchar_${c},
|
||||
ismbhead_${c},
|
||||
mbcharlen_${c}"
|
||||
else
|
||||
CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
|
||||
0, /* mbmaxlen */
|
||||
NULL, /* ismbchar */
|
||||
NULL, /* ismbhead */
|
||||
NULL /* mbcharlen */"
|
||||
fi
|
||||
CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
|
||||
},"
|
||||
case $cs in
|
||||
armscii8)
|
||||
AC_DEFINE(HAVE_CHARSET_armscii8)
|
||||
use_mb="yes"
|
||||
;;
|
||||
big5)
|
||||
AC_DEFINE(HAVE_CHARSET_big5)
|
||||
use_mb="yes"
|
||||
;;
|
||||
cp1251)
|
||||
AC_DEFINE(HAVE_CHARSET_cp1251)
|
||||
;;
|
||||
cp1257)
|
||||
AC_DEFINE(HAVE_CHARSET_cp1257)
|
||||
;;
|
||||
croat)
|
||||
AC_DEFINE(HAVE_CHARSET_croat)
|
||||
;;
|
||||
czech)
|
||||
AC_DEFINE(HAVE_CHARSET_czech)
|
||||
;;
|
||||
danish)
|
||||
AC_DEFINE(HAVE_CHARSET_danish)
|
||||
;;
|
||||
dec8)
|
||||
AC_DEFINE(HAVE_CHARSET_dec8)
|
||||
;;
|
||||
dos)
|
||||
AC_DEFINE(HAVE_CHARSET_dos)
|
||||
;;
|
||||
estonia)
|
||||
AC_DEFINE(HAVE_CHARSET_estonia)
|
||||
;;
|
||||
euc_kr)
|
||||
AC_DEFINE(HAVE_CHARSET_euc_kr)
|
||||
use_mb="yes"
|
||||
;;
|
||||
gb2312)
|
||||
AC_DEFINE(HAVE_CHARSET_gb2312)
|
||||
use_mb="yes"
|
||||
;;
|
||||
gbk)
|
||||
AC_DEFINE(HAVE_CHARSET_gbk)
|
||||
use_mb="yes"
|
||||
;;
|
||||
german1)
|
||||
AC_DEFINE(HAVE_CHARSET_german1)
|
||||
;;
|
||||
greek)
|
||||
AC_DEFINE(HAVE_CHARSET_greek)
|
||||
;;
|
||||
hebrew)
|
||||
AC_DEFINE(HAVE_CHARSET_hebrew)
|
||||
;;
|
||||
hp8)
|
||||
AC_DEFINE(HAVE_CHARSET_hp8)
|
||||
;;
|
||||
hungarian)
|
||||
AC_DEFINE(HAVE_CHARSET_hungarian)
|
||||
;;
|
||||
koi8_ru)
|
||||
AC_DEFINE(HAVE_CHARSET_koi8_ru)
|
||||
;;
|
||||
koi8_ukr)
|
||||
AC_DEFINE(HAVE_CHARSET_koi8_ukr)
|
||||
;;
|
||||
latin1)
|
||||
AC_DEFINE(HAVE_CHARSET_latin1)
|
||||
;;
|
||||
latin1_de)
|
||||
AC_DEFINE(HAVE_CHARSET_latin1_de)
|
||||
;;
|
||||
latin2)
|
||||
AC_DEFINE(HAVE_CHARSET_latin2)
|
||||
;;
|
||||
latin5)
|
||||
AC_DEFINE(HAVE_CHARSET_latin5)
|
||||
;;
|
||||
sjis)
|
||||
AC_DEFINE(HAVE_CHARSET_sjis)
|
||||
use_mb="yes"
|
||||
;;
|
||||
swe7)
|
||||
AC_DEFINE(HAVE_CHARSET_swe7)
|
||||
;;
|
||||
tis620)
|
||||
AC_DEFINE(HAVE_CHARSET_tis620)
|
||||
;;
|
||||
ucs2)
|
||||
AC_DEFINE(HAVE_CHARSET_ucs2)
|
||||
use_mb="yes"
|
||||
;;
|
||||
ujis)
|
||||
AC_DEFINE(HAVE_CHARSET_ujis)
|
||||
use_mb="yes"
|
||||
;;
|
||||
usa7)
|
||||
AC_DEFINE(HAVE_CHARSET_usa7)
|
||||
;;
|
||||
utf8)
|
||||
AC_DEFINE(HAVE_CHARSET_utf8)
|
||||
use_mb="yes"
|
||||
;;
|
||||
win1250)
|
||||
AC_DEFINE(HAVE_CHARSET_win1250)
|
||||
;;
|
||||
win1250ch)
|
||||
AC_DEFINE(HAVE_CHARSET_win1250ch)
|
||||
;;
|
||||
win1251)
|
||||
AC_DEFINE(HAVE_CHARSET_win1251)
|
||||
;;
|
||||
win1251ukr)
|
||||
AC_DEFINE(HAVE_CHARSET_win1251ukr)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([Charset $cs not available. (Available $CHARSETS_AVAILABLE).
|
||||
See the Installation chapter in the Reference Manual.]);
|
||||
esac
|
||||
done
|
||||
|
||||
CHARSET_COMP_CS_INIT="$CHARSET_COMP_CS_INIT
|
||||
|
||||
/* this information is filled in by configure */
|
||||
{
|
||||
0, /* end-of-list marker */
|
||||
NullS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};"
|
||||
|
||||
|
||||
if test $want_use_strcoll = 1
|
||||
then
|
||||
AC_DEFINE(USE_STRCOLL)
|
||||
fi
|
||||
|
||||
if test $want_use_mb = 1
|
||||
dnl Always compile latin1
|
||||
AC_DEFINE(HAVE_CHARSET_latin1)
|
||||
|
||||
if test "$use_mb" = "yes"
|
||||
then
|
||||
AC_DEFINE(USE_MB)
|
||||
AC_DEFINE(USE_MB_IDENT)
|
||||
fi
|
||||
|
||||
# Temporary hack for USE_STRCOLL
|
||||
AC_DEFINE(USE_STRCOLL)
|
||||
|
||||
AC_SUBST(default_charset)
|
||||
AC_SUBST(CHARSET_SRCS)
|
||||
CHARSET_OBJS="`echo "$CHARSET_SRCS" | sed -e 's/\.c /.o /g'`"
|
||||
AC_SUBST(CHARSET_OBJS)
|
||||
AC_SUBST(CHARSETS_NEED_SOURCE)
|
||||
|
||||
dnl We can't use AC_SUBST because these substitutions are too long.
|
||||
dnl I don't want to use sed, either, because there's a reason why
|
||||
dnl autoconf breaks up the substitution commands. So we'll just
|
||||
dnl write to a file and #include it.
|
||||
dnl AC_SUBST(CHARSET_DECLARATIONS)
|
||||
dnl AC_SUBST(CHARSET_COMP_CS_INIT)
|
||||
dnl sed -e "s%@CHARSET_DECLARATIONS@%$CHARSET_DECLARATIONS%g" \
|
||||
dnl -e "s%@CHARSET_COMP_CS_INIT@%$CHARSET_COMP_CS_INIT%g" \
|
||||
dnl $srcdir/strings/ctype.c.in > $srcdir/strings/ctype.c
|
||||
|
||||
cat <<EOF > $srcdir/strings/ctype_autoconf.c
|
||||
/* This file is generated automatically by configure. */$CHARSET_DECLARATIONS
|
||||
|
||||
$CHARSET_COMP_CS_INIT
|
||||
EOF
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_CHARSET_NAME,"$default_charset")
|
||||
|
||||
AC_MSG_RESULT([default: $default_charset; compiled in: $CHARSETS])
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ static int get_answer(QUESTION_WIDGET* w)
|
|||
char c;
|
||||
if (!fgets(buf,sizeof(buf),w->in))
|
||||
die("Failed fgets on input stream");
|
||||
switch ((c=tolower(*buf)))
|
||||
switch ((c=my_tolower(system_charset_info,*buf)))
|
||||
{
|
||||
case '\n':
|
||||
return w->default_ind;
|
||||
|
|
|
@ -113,7 +113,7 @@ char *argv[];
|
|||
exit(1);
|
||||
|
||||
for (i=1,pos=word_end_chars ; i < 256 ; i++)
|
||||
if (isspace(i))
|
||||
if (my_isspace(system_charset_info,i))
|
||||
*pos++=i;
|
||||
*pos=0;
|
||||
if (!(replace=init_replace((char**) from.typelib.type_names,
|
||||
|
|
|
@ -175,9 +175,9 @@ trace dump and specify the path to it with -s or --symbols-file");
|
|||
static uchar hex_val(char c)
|
||||
{
|
||||
uchar l;
|
||||
if (isdigit(c))
|
||||
if (my_isdigit(system_charset_info,c))
|
||||
return c - '0';
|
||||
l = tolower(c);
|
||||
l = my_tolower(system_charset_info,c);
|
||||
if (l < 'a' || l > 'f')
|
||||
return HEX_INVALID;
|
||||
return (uchar)10 + ((uchar)c - (uchar)'a');
|
||||
|
@ -203,9 +203,11 @@ static int init_sym_entry(SYM_ENTRY* se, char* buf)
|
|||
|
||||
if (!se->addr)
|
||||
return -1;
|
||||
while (isspace(*buf++)) ;
|
||||
while (my_isspace(system_charset_info,*buf++))
|
||||
/* empty */;
|
||||
|
||||
while (isspace(*buf++)) ; /* skip more space */
|
||||
while (my_isspace(system_charset_info,*buf++))
|
||||
/* empty - skip more space */;
|
||||
--buf;
|
||||
/* now we are on the symbol */
|
||||
for (p = se->symbol, p_end = se->symbol + sizeof(se->symbol) - 1;
|
||||
|
@ -285,7 +287,8 @@ static void do_resolve()
|
|||
while (fgets(buf, sizeof(buf), fp_dump))
|
||||
{
|
||||
p = buf;
|
||||
while(isspace(*p))
|
||||
/* skip space */
|
||||
while (my_isspace(system_charset_info,*p))
|
||||
++p;
|
||||
|
||||
if (*p++ == '0' && *p++ == 'x')
|
||||
|
|
|
@ -122,7 +122,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
ip = *argv++;
|
||||
|
||||
if (isdigit(ip[0]))
|
||||
if (my_isdigit(system_charset_info,ip[0]))
|
||||
{
|
||||
taddr = inet_addr(ip);
|
||||
if (taddr == htonl(INADDR_BROADCAST))
|
||||
|
|
|
@ -20,10 +20,12 @@
|
|||
|
||||
static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
|
||||
ulong blength, my_bool print_status);
|
||||
static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
|
||||
my_bool print_status);
|
||||
|
||||
/* Returns 0 if the HEAP is ok */
|
||||
|
||||
int heap_check_heap(HP_INFO *info,my_bool print_status)
|
||||
int heap_check_heap(HP_INFO *info, my_bool print_status)
|
||||
{
|
||||
int error;
|
||||
uint key;
|
||||
|
@ -31,8 +33,13 @@ int heap_check_heap(HP_INFO *info,my_bool print_status)
|
|||
DBUG_ENTER("heap_check_keys");
|
||||
|
||||
for (error=key=0 ; key < share->keys ; key++)
|
||||
error|=check_one_key(share->keydef+key,key, share->records,share->blength,
|
||||
print_status);
|
||||
{
|
||||
if (share->keydef[key].algorithm == HA_KEY_ALG_BTREE)
|
||||
error|= check_one_rb_key(info, key, share->records, print_status);
|
||||
else
|
||||
error|= check_one_key(share->keydef + key, key, share->records,
|
||||
share->blength, print_status);
|
||||
}
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
@ -50,8 +57,8 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
|
|||
for (i=found=max_links=seek=0 ; i < records ; i++)
|
||||
{
|
||||
hash_info=hp_find_hash(&keydef->block,i);
|
||||
if (_hp_mask(_hp_rec_hashnr(keydef,hash_info->ptr_to_rec),
|
||||
blength,records) == i)
|
||||
if (hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
|
||||
blength,records) == i)
|
||||
{
|
||||
found++;
|
||||
seek++;
|
||||
|
@ -59,8 +66,8 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
|
|||
while ((hash_info=hash_info->next_key) && found < records + 1)
|
||||
{
|
||||
seek+= ++links;
|
||||
if ((rec_link=_hp_mask(_hp_rec_hashnr(keydef,hash_info->ptr_to_rec),
|
||||
blength,records))
|
||||
if ((rec_link = hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
|
||||
blength, records))
|
||||
!= i)
|
||||
{
|
||||
DBUG_PRINT("error",("Record in wrong link: Link %d Record: %lx Record-link %d", i,hash_info->ptr_to_rec,rec_link));
|
||||
|
@ -87,3 +94,46 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
|
|||
(float) seek / (float) (records ? records : 1));
|
||||
return error;
|
||||
}
|
||||
|
||||
static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
|
||||
my_bool print_status)
|
||||
{
|
||||
HP_KEYDEF *keydef= info->s->keydef + keynr;
|
||||
int error= 0;
|
||||
ulong found= 0;
|
||||
byte *key, *recpos;
|
||||
uint key_length;
|
||||
uint not_used;
|
||||
|
||||
if ((key= tree_search_edge(&keydef->rb_tree, info->parents,
|
||||
&info->last_pos, offsetof(TREE_ELEMENT, left))))
|
||||
{
|
||||
do
|
||||
{
|
||||
memcpy(&recpos, key + (*keydef->get_key_length)(keydef,key), sizeof(byte*));
|
||||
key_length= hp_rb_make_key(keydef, info->recbuf, recpos, 0);
|
||||
if (ha_key_cmp(keydef->seg, info->recbuf, key, key_length,
|
||||
SEARCH_FIND | SEARCH_SAME, ¬_used))
|
||||
{
|
||||
error= 1;
|
||||
DBUG_PRINT("error",("Record in wrong link: Link %d Record: %lx\n",
|
||||
link, recpos));
|
||||
}
|
||||
else
|
||||
{
|
||||
found++;
|
||||
}
|
||||
key= tree_search_next(&keydef->rb_tree, &info->last_pos,
|
||||
offsetof(TREE_ELEMENT, left),
|
||||
offsetof(TREE_ELEMENT, right));
|
||||
} while (key);
|
||||
}
|
||||
if (found != records)
|
||||
{
|
||||
DBUG_PRINT("error",("Found %ld of %ld records"));
|
||||
error= 1;
|
||||
}
|
||||
if (print_status)
|
||||
printf("Key: %d records: %ld\n", keynr, records);
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
|
||||
#include "heapdef.h"
|
||||
|
||||
int _hp_rectest(register HP_INFO *info, register const byte *old)
|
||||
int hp_rectest(register HP_INFO *info, register const byte *old)
|
||||
{
|
||||
DBUG_ENTER("_hp_rectest");
|
||||
DBUG_ENTER("hp_rectest");
|
||||
|
||||
if (memcmp(info->current_ptr,old,(size_t) info->s->reclength))
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <my_pthread.h>
|
||||
#endif
|
||||
#include "heap.h" /* Structs & some defines */
|
||||
#include "my_tree.h"
|
||||
|
||||
/* Some extern variables */
|
||||
|
||||
|
@ -29,10 +30,10 @@ extern LIST *heap_open_list,*heap_share_list;
|
|||
#define test_active(info) \
|
||||
if (!(info->update & HA_STATE_AKTIV))\
|
||||
{ my_errno=HA_ERR_NO_ACTIVE_RECORD; DBUG_RETURN(-1); }
|
||||
#define hp_find_hash(A,B) ((HASH_INFO*) _hp_find_block((A),(B)))
|
||||
#define hp_find_hash(A,B) ((HASH_INFO*) hp_find_block((A),(B)))
|
||||
|
||||
/* Find pos for record and update it in info->current_ptr */
|
||||
#define _hp_find_record(info,pos) (info)->current_ptr= _hp_find_block(&(info)->s->block,pos)
|
||||
#define hp_find_record(info,pos) (info)->current_ptr= hp_find_block(&(info)->s->block,pos)
|
||||
|
||||
typedef struct st_hp_hash_info
|
||||
{
|
||||
|
@ -40,40 +41,52 @@ typedef struct st_hp_hash_info
|
|||
byte *ptr_to_rec;
|
||||
} HASH_INFO;
|
||||
|
||||
typedef struct {
|
||||
HA_KEYSEG *keyseg;
|
||||
uint key_length;
|
||||
uint search_flag;
|
||||
} heap_rb_param;
|
||||
|
||||
/* Prototypes for intern functions */
|
||||
|
||||
extern HP_SHARE *_hp_find_named_heap(const char *name);
|
||||
extern int _hp_rectest(HP_INFO *info,const byte *old);
|
||||
extern void _hp_delete_file_from_open_list(HP_INFO *info);
|
||||
extern byte *_hp_find_block(HP_BLOCK *info,ulong pos);
|
||||
extern int _hp_get_new_block(HP_BLOCK *info, ulong* alloc_length);
|
||||
extern void _hp_free(HP_SHARE *info);
|
||||
extern byte *_hp_free_level(HP_BLOCK *block,uint level,HP_PTRS *pos,
|
||||
byte *last_pos);
|
||||
extern int _hp_write_key(HP_SHARE *info,HP_KEYDEF *keyinfo,
|
||||
const byte *record,byte *recpos);
|
||||
extern int _hp_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
|
||||
const byte *record,byte *recpos,int flag);
|
||||
extern HP_SHARE *hp_find_named_heap(const char *name);
|
||||
extern int hp_rectest(HP_INFO *info,const byte *old);
|
||||
extern byte *hp_find_block(HP_BLOCK *info,ulong pos);
|
||||
extern int hp_get_new_block(HP_BLOCK *info, ulong* alloc_length);
|
||||
extern void hp_free(HP_SHARE *info);
|
||||
extern byte *hp_free_level(HP_BLOCK *block,uint level,HP_PTRS *pos,
|
||||
byte *last_pos);
|
||||
extern int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
|
||||
const byte *record, byte *recpos);
|
||||
extern int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
|
||||
const byte *record, byte *recpos);
|
||||
extern int hp_rb_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
|
||||
const byte *record,byte *recpos,int flag);
|
||||
extern int hp_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
|
||||
const byte *record,byte *recpos,int flag);
|
||||
extern HASH_INFO *_heap_find_hash(HP_BLOCK *block,ulong pos);
|
||||
extern byte *_hp_search(HP_INFO *info,HP_KEYDEF *keyinfo,const byte *key,
|
||||
uint nextflag);
|
||||
extern byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo,
|
||||
const byte *key,
|
||||
HASH_INFO *pos);
|
||||
extern ulong _hp_hashnr(HP_KEYDEF *keyinfo,const byte *key);
|
||||
extern ulong _hp_rec_hashnr(HP_KEYDEF *keyinfo,const byte *rec);
|
||||
extern ulong _hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
|
||||
extern void _hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
|
||||
extern byte *hp_search(HP_INFO *info,HP_KEYDEF *keyinfo,const byte *key,
|
||||
uint nextflag);
|
||||
extern byte *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo,
|
||||
const byte *key, HASH_INFO *pos);
|
||||
extern ulong hp_hashnr(HP_KEYDEF *keyinfo,const byte *key);
|
||||
extern ulong hp_rec_hashnr(HP_KEYDEF *keyinfo,const byte *rec);
|
||||
extern ulong hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
|
||||
extern void hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
|
||||
HASH_INFO *newlink);
|
||||
extern int _hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
|
||||
const byte *rec2);
|
||||
extern int _hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
|
||||
const byte *key);
|
||||
extern void _hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
|
||||
extern int hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
|
||||
const byte *rec2);
|
||||
extern int hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
|
||||
const byte *key);
|
||||
extern void hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
|
||||
extern uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
|
||||
const byte *rec, byte *recpos);
|
||||
extern uint hp_rb_key_length(HP_KEYDEF *keydef, const byte *key);
|
||||
extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key);
|
||||
extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
|
||||
extern int _hp_close(register HP_INFO *info);
|
||||
extern void _hp_clear(HP_SHARE *info);
|
||||
|
||||
extern int hp_close(register HP_INFO *info);
|
||||
extern void hp_clear(HP_SHARE *info);
|
||||
extern uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old);
|
||||
#ifdef THREAD
|
||||
extern pthread_mutex_t THR_LOCK_heap;
|
||||
#else
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
/* Find record according to record-position */
|
||||
|
||||
byte *_hp_find_block(HP_BLOCK *block, ulong pos)
|
||||
byte *hp_find_block(HP_BLOCK *block, ulong pos)
|
||||
{
|
||||
reg1 int i;
|
||||
reg3 HP_PTRS *ptr;
|
||||
|
@ -37,7 +37,7 @@ byte *_hp_find_block(HP_BLOCK *block, ulong pos)
|
|||
/* get one new block-of-records. Alloc ptr to block if neaded */
|
||||
/* Interrupts are stopped to allow ha_panic in interrupts */
|
||||
|
||||
int _hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
|
||||
int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
|
||||
{
|
||||
reg1 uint i,j;
|
||||
HP_PTRS *root;
|
||||
|
@ -84,7 +84,7 @@ int _hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
|
|||
|
||||
/* free all blocks under level */
|
||||
|
||||
byte *_hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
|
||||
byte *hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
|
||||
{
|
||||
int i,max_pos;
|
||||
byte *next_ptr;
|
||||
|
@ -99,7 +99,7 @@ byte *_hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
|
|||
|
||||
next_ptr=(byte*) (pos+1);
|
||||
for (i=0 ; i < max_pos ; i++)
|
||||
next_ptr=_hp_free_level(block,level-1,
|
||||
next_ptr=hp_free_level(block,level-1,
|
||||
(HP_PTRS*) pos->blocks[i],next_ptr);
|
||||
}
|
||||
if ((byte*) pos != last_pos)
|
||||
|
|
|
@ -24,25 +24,33 @@
|
|||
|
||||
void heap_clear(HP_INFO *info)
|
||||
{
|
||||
_hp_clear(info->s);
|
||||
hp_clear(info->s);
|
||||
}
|
||||
|
||||
void _hp_clear(HP_SHARE *info)
|
||||
void hp_clear(HP_SHARE *info)
|
||||
{
|
||||
uint key;
|
||||
DBUG_ENTER("_hp_clear");
|
||||
DBUG_ENTER("hp_clear");
|
||||
|
||||
if (info->block.levels)
|
||||
VOID(_hp_free_level(&info->block,info->block.levels,info->block.root,
|
||||
VOID(hp_free_level(&info->block,info->block.levels,info->block.root,
|
||||
(byte*) 0));
|
||||
info->block.levels=0;
|
||||
for (key=0 ; key < info->keys ; key++)
|
||||
{
|
||||
HP_BLOCK *block= &info->keydef[key].block;
|
||||
if (block->levels)
|
||||
VOID(_hp_free_level(block,block->levels,block->root,(byte*) 0));
|
||||
block->levels=0;
|
||||
block->last_allocated=0;
|
||||
HP_KEYDEF *keyinfo = info->keydef + key;
|
||||
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||
{
|
||||
delete_tree(&keyinfo->rb_tree);
|
||||
}
|
||||
else
|
||||
{
|
||||
HP_BLOCK *block= &keyinfo->block;
|
||||
if (block->levels)
|
||||
VOID(hp_free_level(block,block->levels,block->root,(byte*) 0));
|
||||
block->levels=0;
|
||||
block->last_allocated=0;
|
||||
}
|
||||
}
|
||||
info->records=info->deleted=info->data_length=info->index_length=0;
|
||||
info->blength=1;
|
||||
|
|
|
@ -26,16 +26,16 @@ int heap_close(HP_INFO *info)
|
|||
int tmp;
|
||||
DBUG_ENTER("heap_close");
|
||||
pthread_mutex_lock(&THR_LOCK_heap);
|
||||
tmp= _hp_close(info);
|
||||
tmp= hp_close(info);
|
||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||
DBUG_RETURN(tmp);
|
||||
}
|
||||
|
||||
|
||||
int _hp_close(register HP_INFO *info)
|
||||
int hp_close(register HP_INFO *info)
|
||||
{
|
||||
int error=0;
|
||||
DBUG_ENTER("_hp_close");
|
||||
DBUG_ENTER("hp_close");
|
||||
#ifndef DBUG_OFF
|
||||
if (info->s->changed && heap_check_heap(info,0))
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ int _hp_close(register HP_INFO *info)
|
|||
info->s->changed=0;
|
||||
heap_open_list=list_delete(heap_open_list,&info->open_list);
|
||||
if (!--info->s->open_count && info->s->delete_on_close)
|
||||
_hp_free(info->s); /* Table was deleted */
|
||||
hp_free(info->s); /* Table was deleted */
|
||||
my_free((gptr) info,MYF(0));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
|
171
heap/hp_create.c
171
heap/hp_create.c
|
@ -14,30 +14,156 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
/*
|
||||
Create is done by simply remove the database from memory if it exists.
|
||||
Open creates the database when neaded
|
||||
*/
|
||||
|
||||
#include "heapdef.h"
|
||||
|
||||
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2);
|
||||
static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
|
||||
ulong max_records);
|
||||
|
||||
int heap_create(const char *name)
|
||||
int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
|
||||
uint reclength, ulong max_records, ulong min_records)
|
||||
{
|
||||
reg1 HP_SHARE *share;
|
||||
uint i, j, key_segs, max_length, length;
|
||||
HP_SHARE *share;
|
||||
HA_KEYSEG *keyseg;
|
||||
|
||||
DBUG_ENTER("heap_create");
|
||||
pthread_mutex_lock(&THR_LOCK_heap);
|
||||
if ((share=_hp_find_named_heap(name)))
|
||||
|
||||
if ((share= hp_find_named_heap(name)) && share->open_count == 0)
|
||||
{
|
||||
if (share->open_count == 0)
|
||||
_hp_free(share);
|
||||
hp_free(share);
|
||||
share= NULL;
|
||||
}
|
||||
else
|
||||
|
||||
if (!share)
|
||||
{
|
||||
my_errno=ENOENT;
|
||||
HP_KEYDEF *keyinfo;
|
||||
DBUG_PRINT("info",("Initializing new table"));
|
||||
for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
|
||||
{
|
||||
bzero((char*) &keyinfo->block,sizeof(keyinfo->block));
|
||||
bzero((char*) &keyinfo->rb_tree ,sizeof(keyinfo->rb_tree));
|
||||
for (j= length= 0; j < keyinfo->keysegs; j++)
|
||||
{
|
||||
length+= keyinfo->seg[j].length;
|
||||
if (keyinfo->seg[j].null_bit)
|
||||
{
|
||||
if (!(keyinfo->flag & HA_NULL_ARE_EQUAL))
|
||||
keyinfo->flag|= HA_NULL_PART_KEY;
|
||||
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||
keyinfo->rb_tree.size_of_element++;
|
||||
}
|
||||
}
|
||||
keyinfo->length= length;
|
||||
length+= keyinfo->rb_tree.size_of_element +
|
||||
((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(byte*) : 0);
|
||||
if (length > max_length)
|
||||
max_length= length;
|
||||
key_segs+= keyinfo->keysegs;
|
||||
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||
{
|
||||
key_segs++; /* additional HA_KEYTYPE_END segment */
|
||||
if (keyinfo->flag & HA_NULL_PART_KEY)
|
||||
keyinfo->get_key_length= hp_rb_null_key_length;
|
||||
else
|
||||
keyinfo->get_key_length= hp_rb_key_length;
|
||||
}
|
||||
}
|
||||
if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
|
||||
keys*sizeof(HP_KEYDEF)+
|
||||
key_segs*sizeof(HA_KEYSEG),
|
||||
MYF(MY_ZEROFILL))))
|
||||
{
|
||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
share->keydef= (HP_KEYDEF*) (share + 1);
|
||||
keyseg= (HA_KEYSEG*) (share->keydef + keys);
|
||||
init_block(&share->block, reclength + 1, min_records, max_records);
|
||||
/* Fix keys */
|
||||
memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
|
||||
for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++)
|
||||
{
|
||||
uint nsegs= keydef[i].keysegs;
|
||||
|
||||
if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
|
||||
{
|
||||
init_tree(&keyinfo->rb_tree, 0, 0, sizeof(byte*),
|
||||
(qsort_cmp2)keys_compare, 1, NULL, NULL);
|
||||
keyinfo->delete_key= hp_rb_delete_key;
|
||||
keyinfo->write_key= hp_rb_write_key;
|
||||
nsegs++;
|
||||
}
|
||||
else
|
||||
{
|
||||
init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
|
||||
max_records);
|
||||
keyinfo->delete_key= hp_delete_key;
|
||||
keyinfo->write_key= hp_write_key;
|
||||
}
|
||||
keyinfo->seg= keyseg;
|
||||
memcpy(keyseg, keydef[i].seg,
|
||||
(size_t) (sizeof(keyseg[0]) * nsegs));
|
||||
keyseg+= nsegs;
|
||||
}
|
||||
|
||||
share->min_records= min_records;
|
||||
share->max_records= max_records;
|
||||
share->data_length= share->index_length= 0;
|
||||
share->reclength= reclength;
|
||||
share->blength= 1;
|
||||
share->keys= keys;
|
||||
share->max_key_length= max_length;
|
||||
share->changed= 0;
|
||||
if (!(share->name= my_strdup(name,MYF(0))))
|
||||
{
|
||||
my_free((gptr) share,MYF(0));
|
||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
#ifdef THREAD
|
||||
thr_lock_init(&share->lock);
|
||||
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
|
||||
#endif
|
||||
share->open_list.data= (void*) share;
|
||||
heap_share_list= list_add(heap_share_list,&share->open_list);
|
||||
}
|
||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||
DBUG_RETURN(0);
|
||||
} /* heap_create */
|
||||
|
||||
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2)
|
||||
{
|
||||
uint not_used;
|
||||
return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
|
||||
param->search_flag, ¬_used);
|
||||
}
|
||||
|
||||
static void init_block(HP_BLOCK *block, uint reclength, ulong min_records,
|
||||
ulong max_records)
|
||||
{
|
||||
uint i,recbuffer,records_in_block;
|
||||
|
||||
max_records= max(min_records,max_records);
|
||||
if (!max_records)
|
||||
max_records= 1000; /* As good as quess as anything */
|
||||
recbuffer= (uint) (reclength + sizeof(byte**) - 1) & ~(sizeof(byte**) - 1);
|
||||
records_in_block= max_records / 10;
|
||||
if (records_in_block < 10 && max_records)
|
||||
records_in_block= 10;
|
||||
if (!records_in_block || records_in_block*recbuffer >
|
||||
(my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
|
||||
records_in_block= (my_default_record_cache_size - sizeof(HP_PTRS) *
|
||||
HP_MAX_LEVELS) / recbuffer + 1;
|
||||
block->records_in_block= records_in_block;
|
||||
block->recbuffer= recbuffer;
|
||||
block->last_allocated= 0L;
|
||||
|
||||
for (i= 0; i <= HP_MAX_LEVELS; i++)
|
||||
block->level_info[i].records_under_level=
|
||||
(!i ? 1 : i == 1 ? records_in_block :
|
||||
HP_PTRS_IN_NOD * block->level_info[i - 1].records_under_level);
|
||||
}
|
||||
|
||||
int heap_delete_table(const char *name)
|
||||
|
@ -47,32 +173,31 @@ int heap_delete_table(const char *name)
|
|||
DBUG_ENTER("heap_delete_table");
|
||||
|
||||
pthread_mutex_lock(&THR_LOCK_heap);
|
||||
if ((share=_hp_find_named_heap(name)))
|
||||
if ((share= hp_find_named_heap(name)))
|
||||
{
|
||||
if (share->open_count == 0)
|
||||
_hp_free(share);
|
||||
hp_free(share);
|
||||
else
|
||||
share->delete_on_close=1;
|
||||
result=0;
|
||||
share->delete_on_close= 1;
|
||||
result= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
result=my_errno=ENOENT;
|
||||
result= my_errno=ENOENT;
|
||||
}
|
||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
void _hp_free(HP_SHARE *share)
|
||||
void hp_free(HP_SHARE *share)
|
||||
{
|
||||
heap_share_list=list_delete(heap_share_list,&share->open_list);
|
||||
_hp_clear(share); /* Remove blocks from memory */
|
||||
heap_share_list= list_delete(heap_share_list, &share->open_list);
|
||||
hp_clear(share); /* Remove blocks from memory */
|
||||
#ifdef THREAD
|
||||
thr_lock_delete(&share->lock);
|
||||
VOID(pthread_mutex_destroy(&share->intern_lock));
|
||||
#endif
|
||||
my_free((gptr) share->name,MYF(0));
|
||||
my_free((gptr) share,MYF(0));
|
||||
my_free((gptr) share->name, MYF(0));
|
||||
my_free((gptr) share, MYF(0));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -20,25 +20,26 @@
|
|||
|
||||
int heap_delete(HP_INFO *info, const byte *record)
|
||||
{
|
||||
uint key;
|
||||
byte *pos;
|
||||
HP_SHARE *share=info->s;
|
||||
HP_KEYDEF *keydef, *end, *p_lastinx;
|
||||
DBUG_ENTER("heap_delete");
|
||||
DBUG_PRINT("enter",("info: %lx record: %lx",info,record));
|
||||
|
||||
test_active(info);
|
||||
|
||||
if (info->opt_flag & READ_CHECK_USED && _hp_rectest(info,record))
|
||||
if (info->opt_flag & READ_CHECK_USED && hp_rectest(info,record))
|
||||
DBUG_RETURN(my_errno); /* Record changed */
|
||||
share->changed=1;
|
||||
|
||||
if ( --(share->records) < share->blength >> 1) share->blength>>=1;
|
||||
pos=info->current_ptr;
|
||||
|
||||
for (key=0 ; key < share->keys ; key++)
|
||||
p_lastinx = share->keydef + info->lastinx;
|
||||
for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
|
||||
keydef++)
|
||||
{
|
||||
if (_hp_delete_key(info,share->keydef+key,record,pos,
|
||||
key == (uint) info->lastinx))
|
||||
if ((*keydef->delete_key)(info, keydef, record, pos, keydef == p_lastinx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -49,22 +50,39 @@ int heap_delete(HP_INFO *info, const byte *record)
|
|||
share->deleted++;
|
||||
info->current_hash_ptr=0;
|
||||
DBUG_RETURN(0);
|
||||
err:
|
||||
err:
|
||||
if (++(share->records) == share->blength)
|
||||
share->blength+= share->blength;
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
|
||||
/*
|
||||
Remove one key from rb-tree
|
||||
*/
|
||||
int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
||||
const byte *record, byte *recpos, int flag)
|
||||
{
|
||||
heap_rb_param custom_arg;
|
||||
|
||||
if (flag)
|
||||
info->last_pos= NULL; /* For heap_rnext/heap_rprev */
|
||||
|
||||
custom_arg.keyseg= keyinfo->seg;
|
||||
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
|
||||
custom_arg.search_flag= SEARCH_SAME;
|
||||
return tree_delete(&keyinfo->rb_tree, info->recbuf, &custom_arg);
|
||||
}
|
||||
|
||||
/* Remove one key from hash-table */
|
||||
/* Flag is set if we want's to correct info->current_ptr */
|
||||
|
||||
int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
||||
int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
||||
const byte *record, byte *recpos, int flag)
|
||||
{
|
||||
ulong blength,pos2,pos_hashnr,lastpos_hashnr;
|
||||
HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
|
||||
HP_SHARE *share=info->s;
|
||||
DBUG_ENTER("_hp_delete_key");
|
||||
DBUG_ENTER("hp_delete_key");
|
||||
|
||||
blength=share->blength;
|
||||
if (share->records+1 == blength)
|
||||
|
@ -74,13 +92,13 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
|||
|
||||
/* Search after record with key */
|
||||
pos= hp_find_hash(&keyinfo->block,
|
||||
_hp_mask(_hp_rec_hashnr(keyinfo,record),blength,
|
||||
share->records+1));
|
||||
hp_mask(hp_rec_hashnr(keyinfo, record), blength,
|
||||
share->records + 1));
|
||||
gpos = pos3 = 0;
|
||||
|
||||
while (pos->ptr_to_rec != recpos)
|
||||
{
|
||||
if (flag && !_hp_rec_key_cmp(keyinfo,record,pos->ptr_to_rec))
|
||||
if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
|
||||
last_ptr=pos; /* Previous same key */
|
||||
gpos=pos;
|
||||
if (!(pos=pos->next_key))
|
||||
|
@ -113,33 +131,33 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
|||
DBUG_RETURN (0);
|
||||
|
||||
/* Move the last key (lastpos) */
|
||||
lastpos_hashnr=_hp_rec_hashnr(keyinfo,lastpos->ptr_to_rec);
|
||||
lastpos_hashnr = hp_rec_hashnr(keyinfo, lastpos->ptr_to_rec);
|
||||
/* pos is where lastpos should be */
|
||||
pos=hp_find_hash(&keyinfo->block,_hp_mask(lastpos_hashnr,share->blength,
|
||||
pos=hp_find_hash(&keyinfo->block, hp_mask(lastpos_hashnr, share->blength,
|
||||
share->records));
|
||||
if (pos == empty) /* Move to empty position. */
|
||||
{
|
||||
empty[0]=lastpos[0];
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
pos_hashnr=_hp_rec_hashnr(keyinfo,pos->ptr_to_rec);
|
||||
pos_hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
|
||||
/* pos3 is where the pos should be */
|
||||
pos3= hp_find_hash(&keyinfo->block,
|
||||
_hp_mask(pos_hashnr,share->blength,share->records));
|
||||
hp_mask(pos_hashnr, share->blength, share->records));
|
||||
if (pos != pos3)
|
||||
{ /* pos is on wrong posit */
|
||||
empty[0]=pos[0]; /* Save it here */
|
||||
pos[0]=lastpos[0]; /* This shold be here */
|
||||
_hp_movelink(pos,pos3,empty); /* Fix link to pos */
|
||||
hp_movelink(pos, pos3, empty); /* Fix link to pos */
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
pos2= _hp_mask(lastpos_hashnr,blength,share->records+1);
|
||||
if (pos2 == _hp_mask(pos_hashnr,blength,share->records+1))
|
||||
pos2= hp_mask(lastpos_hashnr, blength, share->records + 1);
|
||||
if (pos2 == hp_mask(pos_hashnr, blength, share->records + 1))
|
||||
{ /* Identical key-positions */
|
||||
if (pos2 != share->records)
|
||||
{
|
||||
empty[0]=lastpos[0];
|
||||
_hp_movelink(lastpos,pos,empty);
|
||||
hp_movelink(lastpos, pos, empty);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
pos3= pos; /* Link pos->next after lastpos */
|
||||
|
@ -147,7 +165,7 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
|||
else pos3= 0; /* Different positions merge */
|
||||
|
||||
empty[0]=lastpos[0];
|
||||
_hp_movelink(pos3,empty,pos->next_key);
|
||||
hp_movelink(pos3, empty, pos->next_key);
|
||||
pos->next_key=empty;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
|
196
heap/hp_hash.c
196
heap/hp_hash.c
|
@ -19,30 +19,73 @@
|
|||
#include "heapdef.h"
|
||||
#include <m_ctype.h>
|
||||
|
||||
ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, const byte *start_key,
|
||||
uint start_key_len,
|
||||
enum ha_rkey_function start_search_flag,
|
||||
const byte *end_key, uint end_key_len,
|
||||
enum ha_rkey_function end_search_flag)
|
||||
{
|
||||
ha_rows start_pos, end_pos;
|
||||
HP_KEYDEF *keyinfo= info->s->keydef + inx;
|
||||
TREE *rb_tree = &keyinfo->rb_tree;
|
||||
heap_rb_param custom_arg;
|
||||
|
||||
info->lastinx = inx;
|
||||
custom_arg.keyseg = keyinfo->seg;
|
||||
custom_arg.search_flag = SEARCH_FIND | SEARCH_SAME;
|
||||
custom_arg.key_length = start_key_len;
|
||||
if (start_key)
|
||||
{
|
||||
hp_rb_pack_key(keyinfo, info->recbuf, start_key);
|
||||
start_pos= tree_record_pos(rb_tree, info->recbuf, start_search_flag,
|
||||
&custom_arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
start_pos= 0;
|
||||
}
|
||||
|
||||
custom_arg.key_length = end_key_len;
|
||||
if (end_key)
|
||||
{
|
||||
hp_rb_pack_key(keyinfo, info->recbuf, end_key);
|
||||
end_pos= tree_record_pos(rb_tree, info->recbuf, end_search_flag,
|
||||
&custom_arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
end_pos= rb_tree->elements_in_tree + (ha_rows)1;
|
||||
}
|
||||
|
||||
if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
|
||||
return HA_POS_ERROR;
|
||||
return end_pos < start_pos ? (ha_rows) 0 :
|
||||
(end_pos == start_pos ? (ha_rows) 1 : end_pos - start_pos);
|
||||
}
|
||||
|
||||
/* Search after a record based on a key */
|
||||
/* Sets info->current_ptr to found record */
|
||||
/* next_flag: Search=0, next=1, prev =2, same =3 */
|
||||
|
||||
byte *_hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
||||
byte *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
||||
uint nextflag)
|
||||
{
|
||||
reg1 HASH_INFO *pos,*prev_ptr;
|
||||
int flag;
|
||||
uint old_nextflag;
|
||||
HP_SHARE *share=info->s;
|
||||
DBUG_ENTER("_hp_search");
|
||||
|
||||
DBUG_ENTER("hp_search");
|
||||
old_nextflag=nextflag;
|
||||
flag=1;
|
||||
prev_ptr=0;
|
||||
|
||||
if (share->records)
|
||||
{
|
||||
pos=hp_find_hash(&keyinfo->block,_hp_mask(_hp_hashnr(keyinfo,key),
|
||||
share->blength,share->records));
|
||||
pos=hp_find_hash(&keyinfo->block, hp_mask(hp_hashnr(keyinfo, key),
|
||||
share->blength, share->records));
|
||||
do
|
||||
{
|
||||
if (!_hp_key_cmp(keyinfo,pos->ptr_to_rec,key))
|
||||
if (!hp_key_cmp(keyinfo, pos->ptr_to_rec, key))
|
||||
{
|
||||
switch (nextflag) {
|
||||
case 0: /* Search after key */
|
||||
|
@ -74,8 +117,8 @@ byte *_hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
|||
{
|
||||
flag=0; /* Reset flag */
|
||||
if (hp_find_hash(&keyinfo->block,
|
||||
_hp_mask(_hp_rec_hashnr(keyinfo,pos->ptr_to_rec),
|
||||
share->blength,share->records)) != pos)
|
||||
hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec),
|
||||
share->blength, share->records)) != pos)
|
||||
break; /* Wrong link */
|
||||
}
|
||||
}
|
||||
|
@ -102,14 +145,14 @@ byte *_hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
|||
since last read !
|
||||
*/
|
||||
|
||||
byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
||||
byte *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
||||
HASH_INFO *pos)
|
||||
{
|
||||
DBUG_ENTER("_hp_search_next");
|
||||
DBUG_ENTER("hp_search_next");
|
||||
|
||||
while ((pos= pos->next_key))
|
||||
{
|
||||
if (!_hp_key_cmp(keyinfo,pos->ptr_to_rec,key))
|
||||
if (! hp_key_cmp(keyinfo, pos->ptr_to_rec, key))
|
||||
{
|
||||
info->current_hash_ptr=pos;
|
||||
DBUG_RETURN (info->current_ptr= pos->ptr_to_rec);
|
||||
|
@ -124,7 +167,7 @@ byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
|||
|
||||
/* Calculate pos according to keys */
|
||||
|
||||
ulong _hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
|
||||
ulong hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
|
||||
{
|
||||
if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1));
|
||||
return (hashnr & ((buffmax >> 1) -1));
|
||||
|
@ -133,7 +176,7 @@ ulong _hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
|
|||
|
||||
/* Change link from pos to new_link */
|
||||
|
||||
void _hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
|
||||
void hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
|
||||
{
|
||||
HASH_INFO *old_link;
|
||||
do
|
||||
|
@ -149,10 +192,11 @@ void _hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
|
|||
|
||||
/* Calc hashvalue for a key */
|
||||
|
||||
ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
||||
ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
||||
{
|
||||
register ulong nr=1, nr2=4;
|
||||
HP_KEYSEG *seg,*endseg;
|
||||
/*register*/
|
||||
ulong nr=1, nr2=4;
|
||||
HA_KEYSEG *seg,*endseg;
|
||||
|
||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||
{
|
||||
|
@ -170,11 +214,17 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
|||
}
|
||||
if (seg->type == HA_KEYTYPE_TEXT)
|
||||
{
|
||||
for (; pos < (uchar*) key ; pos++)
|
||||
if (seg->charset->hash_sort)
|
||||
seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,&nr2);
|
||||
else
|
||||
{
|
||||
nr^=(ulong) ((((uint) nr & 63)+nr2) *
|
||||
((uint) my_sort_order[(uint) *pos])) + (nr << 8);
|
||||
nr2+=3;
|
||||
register uchar *sort_order=seg->charset->sort_order;
|
||||
for (; pos < (uchar*) key ; pos++)
|
||||
{
|
||||
nr^=(ulong) ((((uint) nr & 63)+nr2) *
|
||||
((uint) sort_order[(uint) *pos])) + (nr << 8);
|
||||
nr2+=3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -191,10 +241,11 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
|||
|
||||
/* Calc hashvalue for a key in a record */
|
||||
|
||||
ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
||||
ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
||||
{
|
||||
register ulong nr=1, nr2=4;
|
||||
HP_KEYSEG *seg,*endseg;
|
||||
/*register*/
|
||||
ulong nr=1, nr2=4;
|
||||
HA_KEYSEG *seg,*endseg;
|
||||
|
||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||
{
|
||||
|
@ -209,11 +260,18 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
|||
}
|
||||
if (seg->type == HA_KEYTYPE_TEXT)
|
||||
{
|
||||
for (; pos < end ; pos++)
|
||||
if (seg->charset->hash_sort)
|
||||
seg->charset->hash_sort(seg->charset,pos,end-pos,&nr,&nr2);
|
||||
else
|
||||
{
|
||||
nr^=(ulong) ((((uint) nr & 63)+nr2)*
|
||||
((uint) my_sort_order[(uint) *pos]))+ (nr << 8);
|
||||
nr2+=3;
|
||||
register uchar *sort_order=seg->charset->sort_order;
|
||||
|
||||
for (; pos < end ; pos++)
|
||||
{
|
||||
nr^=(ulong) ((((uint) nr & 63)+nr2)*
|
||||
((uint) sort_order[(uint) *pos]))+ (nr << 8);
|
||||
nr2+=3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -245,10 +303,10 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
|||
* far, and works well on both numbers and strings.
|
||||
*/
|
||||
|
||||
ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
||||
ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
||||
{
|
||||
register ulong nr=0;
|
||||
HP_KEYSEG *seg,*endseg;
|
||||
HA_KEYSEG *seg,*endseg;
|
||||
|
||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||
{
|
||||
|
@ -286,10 +344,10 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
|||
|
||||
/* Calc hashvalue for a key in a record */
|
||||
|
||||
ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
||||
ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
||||
{
|
||||
register ulong nr=0;
|
||||
HP_KEYSEG *seg,*endseg;
|
||||
HA_KEYSEG *seg,*endseg;
|
||||
|
||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||
{
|
||||
|
@ -327,9 +385,9 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
|||
|
||||
/* Compare keys for two records. Returns 0 if they are identical */
|
||||
|
||||
int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
|
||||
int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
|
||||
{
|
||||
HP_KEYSEG *seg,*endseg;
|
||||
HA_KEYSEG *seg,*endseg;
|
||||
|
||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||
{
|
||||
|
@ -343,7 +401,7 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
|
|||
}
|
||||
if (seg->type == HA_KEYTYPE_TEXT)
|
||||
{
|
||||
if (my_sortcmp(rec1+seg->start,rec2+seg->start,seg->length))
|
||||
if (my_sortcmp(seg->charset,rec1+seg->start,rec2+seg->start,seg->length))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
@ -357,9 +415,9 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
|
|||
|
||||
/* Compare a key in a record to a whole key */
|
||||
|
||||
int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
|
||||
int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
|
||||
{
|
||||
HP_KEYSEG *seg,*endseg;
|
||||
HA_KEYSEG *seg,*endseg;
|
||||
|
||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ;
|
||||
seg < endseg ;
|
||||
|
@ -375,7 +433,7 @@ int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
|
|||
}
|
||||
if (seg->type == HA_KEYTYPE_TEXT)
|
||||
{
|
||||
if (my_sortcmp(rec+seg->start,key,seg->length))
|
||||
if (my_sortcmp(seg->charset,rec+seg->start,key,seg->length))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
@ -390,9 +448,9 @@ int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
|
|||
|
||||
/* Copy a key from a record to a keybuffer */
|
||||
|
||||
void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
|
||||
void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
|
||||
{
|
||||
HP_KEYSEG *seg,*endseg;
|
||||
HA_KEYSEG *seg,*endseg;
|
||||
|
||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||
{
|
||||
|
@ -403,7 +461,65 @@ void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
|
|||
}
|
||||
}
|
||||
|
||||
uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
|
||||
const byte *rec, byte *recpos)
|
||||
{
|
||||
byte *start_key= key;
|
||||
HA_KEYSEG *seg, *endseg;
|
||||
|
||||
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
|
||||
{
|
||||
if (seg->null_bit)
|
||||
{
|
||||
if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
|
||||
continue;
|
||||
}
|
||||
memcpy(key, rec + seg->start, (size_t) seg->length);
|
||||
key+= seg->length;
|
||||
}
|
||||
memcpy(key, &recpos, sizeof(byte*));
|
||||
return key - start_key;
|
||||
}
|
||||
|
||||
uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old)
|
||||
{
|
||||
HA_KEYSEG *seg, *endseg;
|
||||
uchar *start_key= key;
|
||||
|
||||
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg;
|
||||
old+= seg->length, seg++)
|
||||
{
|
||||
if (seg->null_bit)
|
||||
{
|
||||
if (!(*key++= (char) 1 - *old++))
|
||||
continue;
|
||||
}
|
||||
memcpy((byte*) key, old, seg->length);
|
||||
key+= seg->length;
|
||||
}
|
||||
return key - start_key;
|
||||
}
|
||||
|
||||
uint hp_rb_key_length(HP_KEYDEF *keydef,
|
||||
const byte *key __attribute__((unused)))
|
||||
{
|
||||
return keydef->length;
|
||||
}
|
||||
|
||||
uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key)
|
||||
{
|
||||
const byte *start_key= key;
|
||||
HA_KEYSEG *seg, *endseg;
|
||||
|
||||
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
|
||||
{
|
||||
if (seg->null_bit && !*key++)
|
||||
continue;
|
||||
key+= seg->length;
|
||||
}
|
||||
return key - start_key;
|
||||
}
|
||||
|
||||
/*
|
||||
Test if any of the key parts are NULL.
|
||||
Return:
|
||||
|
@ -413,7 +529,7 @@ void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
|
|||
|
||||
my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const byte *record)
|
||||
{
|
||||
HP_KEYSEG *seg,*endseg;
|
||||
HA_KEYSEG *seg,*endseg;
|
||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||
{
|
||||
if (seg->null_bit && (record[seg->null_pos] & seg->null_bit))
|
||||
|
|
143
heap/hp_open.c
143
heap/hp_open.c
|
@ -21,159 +21,72 @@
|
|||
#include "hp_static.c" /* Stupid vms-linker */
|
||||
#endif
|
||||
|
||||
static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
|
||||
ulong max_records);
|
||||
#include "my_sys.h"
|
||||
|
||||
/* open a heap database. */
|
||||
|
||||
HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef,
|
||||
uint reclength, ulong max_records, ulong min_records)
|
||||
HP_INFO *heap_open(const char *name, int mode)
|
||||
{
|
||||
uint i,j,key_segs,max_length,length;
|
||||
HP_INFO *info;
|
||||
HP_SHARE *share;
|
||||
HP_KEYSEG *keyseg;
|
||||
|
||||
DBUG_ENTER("heap_open");
|
||||
|
||||
pthread_mutex_lock(&THR_LOCK_heap);
|
||||
if (!(share=_hp_find_named_heap(name)))
|
||||
if (!(share= hp_find_named_heap(name)))
|
||||
{
|
||||
DBUG_PRINT("info",("Initializing new table"));
|
||||
for (i=key_segs=max_length=0 ; i < keys ; i++)
|
||||
{
|
||||
key_segs+= keydef[i].keysegs;
|
||||
bzero((char*) &keydef[i].block,sizeof(keydef[i].block));
|
||||
for (j=length=0 ; j < keydef[i].keysegs; j++)
|
||||
{
|
||||
length+=keydef[i].seg[j].length;
|
||||
if (keydef[i].seg[j].null_bit &&
|
||||
!(keydef[i].flag & HA_NULL_ARE_EQUAL))
|
||||
keydef[i].flag |= HA_NULL_PART_KEY;
|
||||
}
|
||||
keydef[i].length=length;
|
||||
if (length > max_length)
|
||||
max_length=length;
|
||||
}
|
||||
if (!(share = (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
|
||||
keys*sizeof(HP_KEYDEF)+
|
||||
key_segs*sizeof(HP_KEYSEG),
|
||||
MYF(MY_ZEROFILL))))
|
||||
{
|
||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
share->keydef=(HP_KEYDEF*) (share+1);
|
||||
keyseg=(HP_KEYSEG*) (share->keydef+keys);
|
||||
init_block(&share->block,reclength+1,min_records,max_records);
|
||||
/* Fix keys */
|
||||
memcpy(share->keydef,keydef,(size_t) (sizeof(keydef[0])*keys));
|
||||
for (i=0 ; i < keys ; i++)
|
||||
{
|
||||
share->keydef[i].seg=keyseg;
|
||||
memcpy(keyseg,keydef[i].seg,
|
||||
(size_t) (sizeof(keyseg[0])*keydef[i].keysegs));
|
||||
keyseg+=keydef[i].keysegs;
|
||||
init_block(&share->keydef[i].block,sizeof(HASH_INFO),min_records,
|
||||
max_records);
|
||||
}
|
||||
|
||||
share->min_records=min_records;
|
||||
share->max_records=max_records;
|
||||
share->data_length=share->index_length=0;
|
||||
share->reclength=reclength;
|
||||
share->blength=1;
|
||||
share->keys=keys;
|
||||
share->max_key_length=max_length;
|
||||
share->changed=0;
|
||||
if (!(share->name=my_strdup(name,MYF(0))))
|
||||
{
|
||||
my_free((gptr) share,MYF(0));
|
||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
#ifdef THREAD
|
||||
thr_lock_init(&share->lock);
|
||||
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
|
||||
#endif
|
||||
share->open_list.data=(void*) share;
|
||||
heap_share_list=list_add(heap_share_list,&share->open_list);
|
||||
my_errno= ENOENT;
|
||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
if (!(info= (HP_INFO*) my_malloc((uint) sizeof(HP_INFO)+
|
||||
share->max_key_length,
|
||||
if (!(info= (HP_INFO*) my_malloc((uint) sizeof(HP_INFO) +
|
||||
2 * share->max_key_length,
|
||||
MYF(MY_ZEROFILL))))
|
||||
{
|
||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
share->open_count++;
|
||||
share->open_count++;
|
||||
#ifdef THREAD
|
||||
thr_lock_data_init(&share->lock,&info->lock,NULL);
|
||||
#endif
|
||||
info->open_list.data=(void*) info;
|
||||
heap_open_list=list_add(heap_open_list,&info->open_list);
|
||||
info->open_list.data= (void*) info;
|
||||
heap_open_list= list_add(heap_open_list,&info->open_list);
|
||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||
|
||||
info->s=share;
|
||||
info->lastkey=(byte*) (info+1);
|
||||
info->mode=mode;
|
||||
info->s= share;
|
||||
info->lastkey= (byte*) (info + 1);
|
||||
info->recbuf= (byte*) (info->lastkey + share->max_key_length);
|
||||
info->mode= mode;
|
||||
info->current_record= (ulong) ~0L; /* No current record */
|
||||
info->current_ptr=0;
|
||||
info->current_hash_ptr=0;
|
||||
info->lastinx= info->errkey= -1;
|
||||
info->update=0;
|
||||
info->current_ptr= 0;
|
||||
info->current_hash_ptr= 0;
|
||||
info->lastinx= info->errkey= -1;
|
||||
info->update= 0;
|
||||
#ifndef DBUG_OFF
|
||||
info->opt_flag=READ_CHECK_USED; /* Check when changing */
|
||||
info->opt_flag= READ_CHECK_USED; /* Check when changing */
|
||||
#endif
|
||||
DBUG_PRINT("exit",("heap: %lx reclength: %d records_in_block: %d",
|
||||
info,share->reclength,share->block.records_in_block));
|
||||
DBUG_RETURN(info);
|
||||
} /* heap_open */
|
||||
|
||||
}
|
||||
|
||||
/* map name to a heap-nr. If name isn't found return 0 */
|
||||
|
||||
HP_SHARE *_hp_find_named_heap(const char *name)
|
||||
HP_SHARE *hp_find_named_heap(const char *name)
|
||||
{
|
||||
LIST *pos;
|
||||
HP_SHARE *info;
|
||||
DBUG_ENTER("heap_find");
|
||||
DBUG_PRINT("enter",("name: %s",name));
|
||||
|
||||
for (pos=heap_share_list ; pos ; pos=pos->next)
|
||||
for (pos= heap_share_list; pos; pos= pos->next)
|
||||
{
|
||||
info=(HP_SHARE*) pos->data;
|
||||
if (!strcmp(name,info->name))
|
||||
info= (HP_SHARE*) pos->data;
|
||||
if (!strcmp(name, info->name))
|
||||
{
|
||||
DBUG_PRINT("exit",("Old heap_database: %lx",info));
|
||||
DBUG_PRINT("exit", ("Old heap_database: %lx",info));
|
||||
DBUG_RETURN(info);
|
||||
}
|
||||
}
|
||||
DBUG_RETURN((HP_SHARE *)0);
|
||||
DBUG_RETURN((HP_SHARE *) 0);
|
||||
}
|
||||
|
||||
|
||||
static void init_block(HP_BLOCK *block, uint reclength, ulong min_records,
|
||||
ulong max_records)
|
||||
{
|
||||
uint i,recbuffer,records_in_block;
|
||||
|
||||
max_records=max(min_records,max_records);
|
||||
if (!max_records)
|
||||
max_records=1000; /* As good as quess as anything */
|
||||
recbuffer=(uint) (reclength+sizeof(byte**)-1) & ~(sizeof(byte**)-1);
|
||||
records_in_block=max_records/10;
|
||||
if (records_in_block < 10 && max_records)
|
||||
records_in_block=10;
|
||||
if (!records_in_block || records_in_block*recbuffer >
|
||||
(my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
|
||||
records_in_block=(my_default_record_cache_size-sizeof(HP_PTRS)*
|
||||
HP_MAX_LEVELS)/recbuffer+1;
|
||||
block->records_in_block=records_in_block;
|
||||
block->recbuffer=recbuffer;
|
||||
block->last_allocated= 0L;
|
||||
|
||||
for (i=0 ; i <= HP_MAX_LEVELS ; i++)
|
||||
block->level_info[i].records_under_level=
|
||||
(!i ? 1 : i == 1 ? records_in_block :
|
||||
HP_PTRS_IN_NOD * block->level_info[i-1].records_under_level);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ int heap_panic(enum ha_panic_function flag)
|
|||
next_open=element->next; /* Save if close */
|
||||
switch (flag) {
|
||||
case HA_PANIC_CLOSE:
|
||||
_hp_close(info);
|
||||
hp_close(info);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -45,7 +45,7 @@ int heap_panic(enum ha_panic_function flag)
|
|||
case HA_PANIC_CLOSE:
|
||||
{
|
||||
if (!share->open_count)
|
||||
_hp_free(share);
|
||||
hp_free(share);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -27,7 +27,7 @@ int heap_rename(const char *old_name, const char *new_name)
|
|||
DBUG_ENTER("heap_rename");
|
||||
|
||||
pthread_mutex_lock(&THR_LOCK_heap);
|
||||
if ((info=_hp_find_named_heap(old_name)))
|
||||
if ((info = hp_find_named_heap(old_name)))
|
||||
{
|
||||
if (!(name_buff=(char*) my_strdup(new_name,MYF(MY_WME))))
|
||||
{
|
||||
|
|
|
@ -18,11 +18,43 @@
|
|||
|
||||
/* Read first record with the current key */
|
||||
|
||||
int heap_rfirst(HP_INFO *info, byte *record)
|
||||
int heap_rfirst(HP_INFO *info, byte *record, int inx)
|
||||
{
|
||||
HP_SHARE *share = info->s;
|
||||
HP_KEYDEF *keyinfo = share->keydef + inx;
|
||||
|
||||
DBUG_ENTER("heap_rfirst");
|
||||
info->current_record=0;
|
||||
info->current_hash_ptr=0;
|
||||
info->update=HA_STATE_PREV_FOUND;
|
||||
DBUG_RETURN(heap_rnext(info,record));
|
||||
info->lastinx= inx;
|
||||
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||
{
|
||||
byte *pos;
|
||||
|
||||
if ((pos = tree_search_edge(&keyinfo->rb_tree, info->parents,
|
||||
&info->last_pos, offsetof(TREE_ELEMENT, left))))
|
||||
{
|
||||
memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
|
||||
sizeof(byte*));
|
||||
info->current_ptr = pos;
|
||||
memcpy(record, pos, (size_t)share->reclength);
|
||||
info->update = HA_STATE_AKTIV;
|
||||
}
|
||||
else
|
||||
{
|
||||
my_errno = HA_ERR_END_OF_FILE;
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(info->s->records))
|
||||
{
|
||||
my_errno=HA_ERR_END_OF_FILE;
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
info->current_record=0;
|
||||
info->current_hash_ptr=0;
|
||||
info->update=HA_STATE_PREV_FOUND;
|
||||
DBUG_RETURN(heap_rnext(info,record));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,29 +16,60 @@
|
|||
|
||||
#include "heapdef.h"
|
||||
|
||||
int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
|
||||
int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
{
|
||||
byte *pos;
|
||||
HP_SHARE *share=info->s;
|
||||
HP_SHARE *share= info->s;
|
||||
HP_KEYDEF *keyinfo= share->keydef + inx;
|
||||
DBUG_ENTER("heap_rkey");
|
||||
DBUG_PRINT("enter",("base: %lx inx: %d",info,inx));
|
||||
|
||||
if ((uint) inx >= share->keys)
|
||||
{
|
||||
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
|
||||
DBUG_RETURN(my_errno= HA_ERR_WRONG_INDEX);
|
||||
}
|
||||
info->lastinx=inx;
|
||||
info->current_record = (ulong) ~0L; /* For heap_rrnd() */
|
||||
info->lastinx= inx;
|
||||
info->current_record= (ulong) ~0L; /* For heap_rrnd() */
|
||||
|
||||
if (!(pos=_hp_search(info,share->keydef+inx,key,0)))
|
||||
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||
{
|
||||
info->update=0;
|
||||
DBUG_RETURN(my_errno);
|
||||
heap_rb_param custom_arg;
|
||||
|
||||
hp_rb_pack_key(keyinfo, info->recbuf, key);
|
||||
|
||||
custom_arg.keyseg= info->s->keydef[inx].seg;
|
||||
custom_arg.key_length= key_len;
|
||||
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
|
||||
/* for next rkey() after deletion */
|
||||
if (find_flag == HA_READ_AFTER_KEY)
|
||||
info->last_find_flag= HA_READ_KEY_OR_NEXT;
|
||||
else if (find_flag == HA_READ_BEFORE_KEY)
|
||||
info->last_find_flag= HA_READ_KEY_OR_PREV;
|
||||
else
|
||||
info->last_find_flag= find_flag;
|
||||
info->lastkey_len= key_len;
|
||||
if (!(pos= tree_search_key(&keyinfo->rb_tree, info->recbuf, info->parents,
|
||||
&info->last_pos, find_flag, &custom_arg)))
|
||||
{
|
||||
info->update= 0;
|
||||
DBUG_RETURN(my_errno= HA_ERR_KEY_NOT_FOUND);
|
||||
}
|
||||
memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos), sizeof(byte*));
|
||||
info->current_ptr= pos;
|
||||
}
|
||||
memcpy(record,pos,(size_t) share->reclength);
|
||||
info->update=HA_STATE_AKTIV;
|
||||
if (!(share->keydef[inx].flag & HA_NOSAME))
|
||||
memcpy(info->lastkey,key,(size_t) share->keydef[inx].length);
|
||||
else
|
||||
{
|
||||
if (!(pos= hp_search(info, share->keydef + inx, key, 0)))
|
||||
{
|
||||
info->update= 0;
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
if (!(keyinfo->flag & HA_NOSAME))
|
||||
memcpy(info->lastkey, key, (size_t) keyinfo->length);
|
||||
}
|
||||
memcpy(record, pos, (size_t) share->reclength);
|
||||
info->update= HA_STATE_AKTIV;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -47,5 +78,5 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
|
|||
|
||||
gptr heap_find(HP_INFO *info, int inx, const byte *key)
|
||||
{
|
||||
return _hp_search(info,info->s->keydef+inx,key,0);
|
||||
return hp_search(info, info->s->keydef + inx, key, 0);
|
||||
}
|
||||
|
|
|
@ -19,11 +19,38 @@
|
|||
/* Read first record with the current key */
|
||||
|
||||
|
||||
int heap_rlast(HP_INFO *info, byte *record)
|
||||
int heap_rlast(HP_INFO *info, byte *record, int inx)
|
||||
{
|
||||
HP_SHARE *share= info->s;
|
||||
HP_KEYDEF *keyinfo= share->keydef + inx;
|
||||
|
||||
DBUG_ENTER("heap_rlast");
|
||||
info->current_ptr=0;
|
||||
info->current_hash_ptr=0;
|
||||
info->update=HA_STATE_NEXT_FOUND;
|
||||
DBUG_RETURN(heap_rprev(info,record));
|
||||
info->lastinx= inx;
|
||||
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||
{
|
||||
byte *pos;
|
||||
|
||||
if ((pos = tree_search_edge(&keyinfo->rb_tree, info->parents,
|
||||
&info->last_pos, offsetof(TREE_ELEMENT, right))))
|
||||
{
|
||||
memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
|
||||
sizeof(byte*));
|
||||
info->current_ptr = pos;
|
||||
memcpy(record, pos, (size_t)share->reclength);
|
||||
info->update = HA_STATE_AKTIV;
|
||||
}
|
||||
else
|
||||
{
|
||||
my_errno = HA_ERR_END_OF_FILE;
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
info->current_ptr=0;
|
||||
info->current_hash_ptr=0;
|
||||
info->update=HA_STATE_NEXT_FOUND;
|
||||
DBUG_RETURN(heap_rprev(info,record));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,27 +22,58 @@ int heap_rnext(HP_INFO *info, byte *record)
|
|||
{
|
||||
byte *pos;
|
||||
HP_SHARE *share=info->s;
|
||||
HP_KEYDEF *keyinfo;
|
||||
DBUG_ENTER("heap_rnext");
|
||||
|
||||
if (info->lastinx < 0)
|
||||
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
|
||||
|
||||
if (info->current_hash_ptr)
|
||||
pos= _hp_search_next(info,share->keydef+info->lastinx, info->lastkey,
|
||||
info->current_hash_ptr);
|
||||
keyinfo = share->keydef + info->lastinx;
|
||||
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||
{
|
||||
heap_rb_param custom_arg;
|
||||
|
||||
if (info->last_pos)
|
||||
pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos,
|
||||
offsetof(TREE_ELEMENT, left),
|
||||
offsetof(TREE_ELEMENT, right));
|
||||
else
|
||||
{
|
||||
custom_arg.keyseg = keyinfo->seg;
|
||||
custom_arg.key_length = info->lastkey_len;
|
||||
custom_arg.search_flag = SEARCH_SAME | SEARCH_FIND;
|
||||
pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents,
|
||||
&info->last_pos, info->last_find_flag, &custom_arg);
|
||||
}
|
||||
if (pos)
|
||||
{
|
||||
memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
|
||||
sizeof(byte*));
|
||||
info->current_ptr = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
my_errno = HA_ERR_KEY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!info->current_ptr && (info->update & HA_STATE_NEXT_FOUND))
|
||||
{
|
||||
pos=0; /* Read next after last */
|
||||
my_errno=HA_ERR_KEY_NOT_FOUND;
|
||||
}
|
||||
else if (!info->current_ptr) /* Deleted or first call */
|
||||
pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 0);
|
||||
if (info->current_hash_ptr)
|
||||
pos= hp_search_next(info, keyinfo, info->lastkey,
|
||||
info->current_hash_ptr);
|
||||
else
|
||||
pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 1);
|
||||
{
|
||||
if (!info->current_ptr && (info->update & HA_STATE_NEXT_FOUND))
|
||||
{
|
||||
pos=0; /* Read next after last */
|
||||
my_errno=HA_ERR_KEY_NOT_FOUND;
|
||||
}
|
||||
else if (!info->current_ptr) /* Deleted or first call */
|
||||
pos= hp_search(info, keyinfo, info->lastkey, 0);
|
||||
else
|
||||
pos= hp_search(info, keyinfo, info->lastkey, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pos)
|
||||
{
|
||||
info->update=HA_STATE_NEXT_FOUND; /* For heap_rprev */
|
||||
|
|
|
@ -23,22 +23,53 @@ int heap_rprev(HP_INFO *info, byte *record)
|
|||
{
|
||||
byte *pos;
|
||||
HP_SHARE *share=info->s;
|
||||
HP_KEYDEF *keyinfo;
|
||||
DBUG_ENTER("heap_rprev");
|
||||
|
||||
if (info->lastinx < 0)
|
||||
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
|
||||
|
||||
if (info->current_ptr || (info->update & HA_STATE_NEXT_FOUND))
|
||||
keyinfo = share->keydef + info->lastinx;
|
||||
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||
{
|
||||
if ((info->update & HA_STATE_DELETED))
|
||||
pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 3);
|
||||
heap_rb_param custom_arg;
|
||||
|
||||
if (info->last_pos)
|
||||
pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos,
|
||||
offsetof(TREE_ELEMENT, right),
|
||||
offsetof(TREE_ELEMENT, left));
|
||||
else
|
||||
pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 2);
|
||||
{
|
||||
custom_arg.keyseg = keyinfo->seg;
|
||||
custom_arg.key_length = keyinfo->length;
|
||||
custom_arg.search_flag = SEARCH_SAME;
|
||||
pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents,
|
||||
&info->last_pos, info->last_find_flag, &custom_arg);
|
||||
}
|
||||
if (pos)
|
||||
{
|
||||
memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
|
||||
sizeof(byte*));
|
||||
info->current_ptr = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
my_errno = HA_ERR_KEY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pos=0; /* Read next after last */
|
||||
my_errno=HA_ERR_KEY_NOT_FOUND;
|
||||
if (info->current_ptr || (info->update & HA_STATE_NEXT_FOUND))
|
||||
{
|
||||
if ((info->update & HA_STATE_DELETED))
|
||||
pos= hp_search(info, share->keydef + info->lastinx, info->lastkey, 3);
|
||||
else
|
||||
pos= hp_search(info, share->keydef + info->lastinx, info->lastkey, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
pos=0; /* Read next after last */
|
||||
my_errno=HA_ERR_KEY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
if (!pos)
|
||||
{
|
||||
|
|
|
@ -88,7 +88,7 @@ int heap_rrnd_old(register HP_INFO *info, byte *record, ulong pos)
|
|||
}
|
||||
|
||||
/* Find record number pos */
|
||||
_hp_find_record(info,pos);
|
||||
hp_find_record(info, pos);
|
||||
|
||||
end:
|
||||
if (!info->current_ptr[share->reclength])
|
||||
|
|
|
@ -41,8 +41,8 @@ int heap_rsame(register HP_INFO *info, byte *record, int inx)
|
|||
else if (inx != -1)
|
||||
{
|
||||
info->lastinx=inx;
|
||||
_hp_make_key(share->keydef+inx,info->lastkey,record);
|
||||
if (!_hp_search(info,share->keydef+inx,info->lastkey,3))
|
||||
hp_make_key(share->keydef + inx, info->lastkey, record);
|
||||
if (!hp_search(info, share->keydef + inx, info->lastkey, 3))
|
||||
{
|
||||
info->update=0;
|
||||
DBUG_RETURN(my_errno);
|
||||
|
|
|
@ -58,7 +58,7 @@ int heap_scan(register HP_INFO *info, byte *record)
|
|||
DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
|
||||
}
|
||||
}
|
||||
_hp_find_record(info,pos);
|
||||
hp_find_record(info, pos);
|
||||
}
|
||||
if (!info->current_ptr[share->reclength])
|
||||
{
|
||||
|
|
|
@ -36,7 +36,7 @@ int main(int argc, char **argv)
|
|||
char record[128],key[32];
|
||||
const char *filename;
|
||||
HP_KEYDEF keyinfo[10];
|
||||
HP_KEYSEG keyseg[4];
|
||||
HA_KEYSEG keyseg[4];
|
||||
MY_INIT(argv[0]);
|
||||
|
||||
filename= "test1";
|
||||
|
@ -44,17 +44,19 @@ int main(int argc, char **argv)
|
|||
|
||||
keyinfo[0].keysegs=1;
|
||||
keyinfo[0].seg=keyseg;
|
||||
keyinfo[0].algorithm= HA_KEY_ALG_HASH;
|
||||
keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY;
|
||||
keyinfo[0].seg[0].start=1;
|
||||
keyinfo[0].seg[0].length=6;
|
||||
keyinfo[0].seg[0].charset=default_charset_info;
|
||||
keyinfo[0].flag = HA_NOSAME;
|
||||
|
||||
|
||||
deleted=0;
|
||||
bzero((gptr) flags,sizeof(flags));
|
||||
|
||||
printf("- Creating heap-file\n");
|
||||
heap_create(filename);
|
||||
if (!(file=heap_open(filename,2,1,keyinfo,30,(ulong) flag*100000l,10l)))
|
||||
if (heap_create(filename,1,keyinfo,30,(ulong) flag*100000l,10l) ||
|
||||
!(file= heap_open(filename, 2)))
|
||||
goto err;
|
||||
printf("- Writing records:s\n");
|
||||
strmov(record," ..... key ");
|
||||
|
@ -77,7 +79,7 @@ int main(int argc, char **argv)
|
|||
if (heap_close(file))
|
||||
goto err;
|
||||
printf("- Reopening file\n");
|
||||
if (!(file=heap_open(filename,2,1,keyinfo,30,(ulong) flag*100000l,10l)))
|
||||
if (!(file=heap_open(filename, 2)))
|
||||
goto err;
|
||||
|
||||
printf("- Removing records\n");
|
||||
|
@ -85,7 +87,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
if (i == remove_ant) { VOID(heap_close(file)) ; return (0) ; }
|
||||
sprintf(key,"%6d",(j=(int) ((rand() & 32767)/32767.*25)));
|
||||
if ((error = heap_rkey(file,record,0,key)))
|
||||
if ((error = heap_rkey(file,record,0,key,0,6)))
|
||||
{
|
||||
if (verbose || (flags[j] == 1 ||
|
||||
(error && my_errno != HA_ERR_KEY_NOT_FOUND)))
|
||||
|
@ -113,7 +115,7 @@ int main(int argc, char **argv)
|
|||
sprintf(key,"%6d",i);
|
||||
bmove(record+1,key,6);
|
||||
my_errno=0;
|
||||
error=heap_rkey(file,record,0,key);
|
||||
error=heap_rkey(file,record,0,key,0,6);
|
||||
if (verbose ||
|
||||
(error == 0 && flags[i] != 1) ||
|
||||
(error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND)))
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#define SAFEMALLOC
|
||||
#endif
|
||||
|
||||
#include "heapdef.h" /* Because of _hp_find_block */
|
||||
#include "heapdef.h" /* Because of hp_find_block */
|
||||
#include <signal.h>
|
||||
|
||||
#define MAX_RECORDS 100000
|
||||
|
@ -61,7 +61,7 @@ int main(int argc, char *argv[])
|
|||
const char *filename,*filename2;
|
||||
HP_INFO *file,*file2;
|
||||
HP_KEYDEF keyinfo[MAX_KEYS];
|
||||
HP_KEYSEG keyseg[MAX_KEYS*5];
|
||||
HA_KEYSEG keyseg[MAX_KEYS*5];
|
||||
HEAP_PTR position;
|
||||
MY_INIT(argv[0]); /* init my_sys library & pthreads */
|
||||
LINT_INIT(position);
|
||||
|
@ -77,45 +77,53 @@ int main(int argc, char *argv[])
|
|||
keyinfo[0].seg=keyseg;
|
||||
keyinfo[0].keysegs=1;
|
||||
keyinfo[0].flag= 0;
|
||||
keyinfo[0].algorithm= HA_KEY_ALG_HASH;
|
||||
keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY;
|
||||
keyinfo[0].seg[0].start=0;
|
||||
keyinfo[0].seg[0].length=6;
|
||||
keyinfo[0].seg[0].null_bit=0;
|
||||
keyinfo[0].seg[0].charset=default_charset_info;
|
||||
keyinfo[1].seg=keyseg+1;
|
||||
keyinfo[1].keysegs=2;
|
||||
keyinfo[1].flag=0;
|
||||
keyinfo[1].algorithm= HA_KEY_ALG_HASH;
|
||||
keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY;
|
||||
keyinfo[1].seg[0].start=7;
|
||||
keyinfo[1].seg[0].length=6;
|
||||
keyinfo[1].seg[0].null_bit=0;
|
||||
keyinfo[1].seg[0].charset=default_charset_info;
|
||||
keyinfo[1].seg[1].type=HA_KEYTYPE_TEXT;
|
||||
keyinfo[1].seg[1].start=0; /* key in two parts */
|
||||
keyinfo[1].seg[1].length=6;
|
||||
keyinfo[1].seg[1].null_bit=0;
|
||||
keyinfo[1].seg[1].charset=default_charset_info;
|
||||
keyinfo[2].seg=keyseg+3;
|
||||
keyinfo[2].keysegs=1;
|
||||
keyinfo[2].flag=HA_NOSAME;
|
||||
keyinfo[2].algorithm= HA_KEY_ALG_HASH;
|
||||
keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY;
|
||||
keyinfo[2].seg[0].start=12;
|
||||
keyinfo[2].seg[0].length=8;
|
||||
keyinfo[2].seg[0].null_bit=0;
|
||||
keyinfo[2].seg[0].charset=default_charset_info;
|
||||
keyinfo[3].seg=keyseg+4;
|
||||
keyinfo[3].keysegs=1;
|
||||
keyinfo[3].flag=HA_NOSAME;
|
||||
keyinfo[3].seg=keyseg+4;
|
||||
keyinfo[3].algorithm= HA_KEY_ALG_HASH;
|
||||
keyinfo[3].seg[0].type=HA_KEYTYPE_BINARY;
|
||||
keyinfo[3].seg[0].start=37;
|
||||
keyinfo[3].seg[0].length=1;
|
||||
keyinfo[3].seg[0].null_bit=1;
|
||||
keyinfo[3].seg[0].null_pos=38;
|
||||
keyinfo[3].seg[0].charset=default_charset_info;
|
||||
|
||||
bzero((char*) key1,sizeof(key1));
|
||||
bzero((char*) key3,sizeof(key3));
|
||||
|
||||
printf("- Creating heap-file\n");
|
||||
if (heap_create(filename))
|
||||
goto err;
|
||||
if (!(file=heap_open(filename,2,keys,keyinfo,reclength,(ulong) flag*100000L,
|
||||
(ulong) recant/2)))
|
||||
if (heap_create(filename,keys,keyinfo,reclength,(ulong) flag*100000L,
|
||||
(ulong) recant/2) ||
|
||||
!(file= heap_open(filename, 2)))
|
||||
goto err;
|
||||
signal(SIGINT,endprog);
|
||||
|
||||
|
@ -167,14 +175,14 @@ int main(int argc, char *argv[])
|
|||
if (j != 0)
|
||||
{
|
||||
sprintf(key,"%6d",j);
|
||||
if (heap_rkey(file,record,0,key))
|
||||
if (heap_rkey(file,record,0,key,6,0))
|
||||
{
|
||||
printf("can't find key1: \"%s\"\n",key);
|
||||
goto err;
|
||||
}
|
||||
#ifdef NOT_USED
|
||||
if (file->current_ptr == _hp_find_block(&file->s->block,0) ||
|
||||
file->current_ptr == _hp_find_block(&file->s->block,1))
|
||||
if (file->current_ptr == hp_find_block(&file->s->block,0) ||
|
||||
file->current_ptr == hp_find_block(&file->s->block,1))
|
||||
continue; /* Don't remove 2 first records */
|
||||
#endif
|
||||
if (heap_delete(file,record))
|
||||
|
@ -227,7 +235,7 @@ int main(int argc, char *argv[])
|
|||
if (!key1[j])
|
||||
continue;
|
||||
sprintf(key,"%6d",j);
|
||||
if (heap_rkey(file,record,0,key))
|
||||
if (heap_rkey(file,record,0,key,6,0))
|
||||
{
|
||||
printf("can't find key1: \"%s\"\n",key);
|
||||
goto err;
|
||||
|
@ -277,7 +285,7 @@ int main(int argc, char *argv[])
|
|||
printf("- Read first key - next - delete - next -> last\n");
|
||||
DBUG_PRINT("progpos",("first - next - delete - next -> last"));
|
||||
|
||||
if (heap_rkey(file,record,0,key))
|
||||
if (heap_rkey(file,record,0,key,6,0))
|
||||
goto err;
|
||||
if (heap_rnext(file,record3)) goto err;
|
||||
if (heap_delete(file,record3)) goto err;
|
||||
|
@ -306,7 +314,7 @@ int main(int argc, char *argv[])
|
|||
if (!silent)
|
||||
printf("- Read last key - delete - prev - prev - opt_delete - prev -> first\n");
|
||||
|
||||
if (heap_rlast(file,record3)) goto err;
|
||||
if (heap_rlast(file,record3,0)) goto err;
|
||||
if (heap_delete(file,record3)) goto err;
|
||||
key_check-=atoi(record3);
|
||||
key1[atoi(record+keyinfo[0].seg[0].start)]--;
|
||||
|
@ -501,7 +509,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
printf("- Read through all keys with first-next-last-prev\n");
|
||||
ant=0;
|
||||
for (error=heap_rkey(file,record,0,key) ;
|
||||
for (error=heap_rkey(file,record,0,key,6,0);
|
||||
! error ;
|
||||
error=heap_rnext(file,record))
|
||||
ant++;
|
||||
|
@ -513,7 +521,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
ant=0;
|
||||
for (error=heap_rlast(file,record) ;
|
||||
for (error=heap_rlast(file,record,0) ;
|
||||
! error ;
|
||||
error=heap_rprev(file,record))
|
||||
{
|
||||
|
@ -530,7 +538,7 @@ int main(int argc, char *argv[])
|
|||
if (testflag == 4) goto end;
|
||||
|
||||
printf("- Reading through all rows through keys\n");
|
||||
if (!(file2=heap_open(filename,2,0,0,0,0,0)))
|
||||
if (!(file2=heap_open(filename, 2)))
|
||||
goto err;
|
||||
if (heap_scan_init(file))
|
||||
goto err;
|
||||
|
@ -538,7 +546,7 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
if (error == 0)
|
||||
{
|
||||
if (heap_rkey(file2,record2,2,record+keyinfo[2].seg[0].start))
|
||||
if (heap_rkey(file2,record2,2,record+keyinfo[2].seg[0].start,8,0))
|
||||
{
|
||||
printf("can't find key3: \"%.8s\"\n",
|
||||
record+keyinfo[2].seg[0].start);
|
||||
|
@ -549,7 +557,8 @@ int main(int argc, char *argv[])
|
|||
heap_close(file2);
|
||||
|
||||
printf("- Creating output heap-file 2\n");
|
||||
if (!(file2=heap_open(filename2,2,1,keyinfo,reclength,0L,0L)))
|
||||
if (heap_create(filename2,1,keyinfo,reclength,0L,0L) ||
|
||||
!(file2= heap_open(filename2, 2)))
|
||||
goto err;
|
||||
|
||||
printf("- Copying and removing records\n");
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
|
||||
{
|
||||
uint key;
|
||||
HP_KEYDEF *keydef, *end, *p_lastinx;
|
||||
byte *pos;
|
||||
HP_SHARE *share=info->s;
|
||||
DBUG_ENTER("heap_update");
|
||||
|
@ -28,19 +28,20 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
|
|||
test_active(info);
|
||||
pos=info->current_ptr;
|
||||
|
||||
if (info->opt_flag & READ_CHECK_USED && _hp_rectest(info,old))
|
||||
if (info->opt_flag & READ_CHECK_USED && hp_rectest(info,old))
|
||||
DBUG_RETURN(my_errno); /* Record changed */
|
||||
if (--(share->records) < share->blength >> 1) share->blength>>= 1;
|
||||
share->changed=1;
|
||||
|
||||
for (key=0 ; key < share->keys ; key++)
|
||||
p_lastinx = share->keydef + info->lastinx;
|
||||
for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
|
||||
keydef++)
|
||||
{
|
||||
if (_hp_rec_key_cmp(share->keydef+key,old,heap_new))
|
||||
if (hp_rec_key_cmp(keydef, old, heap_new))
|
||||
{
|
||||
if (_hp_delete_key(info,share->keydef+key,old,pos,key ==
|
||||
(uint) info->lastinx) ||
|
||||
_hp_write_key(share,share->keydef+key,heap_new,pos))
|
||||
goto err;
|
||||
if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) ||
|
||||
(*keydef->write_key)(info, keydef, heap_new, pos))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,16 +52,27 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
|
|||
err:
|
||||
if (my_errno == HA_ERR_FOUND_DUPP_KEY)
|
||||
{
|
||||
info->errkey=key;
|
||||
do
|
||||
info->errkey = keydef - share->keydef;
|
||||
if (keydef->algorithm == HA_KEY_ALG_BTREE)
|
||||
{
|
||||
if (_hp_rec_key_cmp(share->keydef+key,old,heap_new))
|
||||
/* we don't need to delete non-inserted key from rb-tree */
|
||||
if ((*keydef->write_key)(info, keydef, old, pos))
|
||||
{
|
||||
if (_hp_delete_key(info,share->keydef+key,heap_new,pos,0) ||
|
||||
_hp_write_key(share,share->keydef+key,old,pos))
|
||||
if (++(share->records) == share->blength) share->blength+= share->blength;
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
keydef--;
|
||||
}
|
||||
while (keydef >= share->keydef)
|
||||
{
|
||||
if (hp_rec_key_cmp(keydef, old, heap_new))
|
||||
{
|
||||
if ((*keydef->delete_key)(info, keydef, heap_new, pos, 0) ||
|
||||
(*keydef->write_key)(info, keydef, old, pos))
|
||||
break;
|
||||
}
|
||||
} while (key-- > 0);
|
||||
keydef--;
|
||||
}
|
||||
}
|
||||
if (++(share->records) == share->blength) share->blength+= share->blength;
|
||||
DBUG_RETURN(my_errno);
|
||||
|
|
|
@ -27,12 +27,12 @@
|
|||
#define HIGHUSED 8
|
||||
|
||||
static byte *next_free_record_pos(HP_SHARE *info);
|
||||
static HASH_INFO *_hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
|
||||
static HASH_INFO *hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
|
||||
ulong records);
|
||||
|
||||
int heap_write(HP_INFO *info, const byte *record)
|
||||
{
|
||||
uint key;
|
||||
HP_KEYDEF *keydef, *end;
|
||||
byte *pos;
|
||||
HP_SHARE *share=info->s;
|
||||
DBUG_ENTER("heap_write");
|
||||
|
@ -47,9 +47,10 @@ int heap_write(HP_INFO *info, const byte *record)
|
|||
DBUG_RETURN(my_errno);
|
||||
share->changed=1;
|
||||
|
||||
for (key=0 ; key < share->keys ; key++)
|
||||
for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
|
||||
keydef++)
|
||||
{
|
||||
if (_hp_write_key(share,share->keydef+key,record,pos))
|
||||
if ((*keydef->write_key)(info, keydef, record, pos))
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -62,13 +63,19 @@ int heap_write(HP_INFO *info, const byte *record)
|
|||
info->update|=HA_STATE_AKTIV;
|
||||
DBUG_RETURN(0);
|
||||
err:
|
||||
DBUG_PRINT("info",("Duplicate key: %d",key));
|
||||
info->errkey= key;
|
||||
do
|
||||
DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef));
|
||||
info->errkey= keydef - share->keydef;
|
||||
if (keydef->algorithm == HA_KEY_ALG_BTREE)
|
||||
{
|
||||
if (_hp_delete_key(info,share->keydef+key,record,pos,0))
|
||||
/* we don't need to delete non-inserted key from rb-tree */
|
||||
keydef--;
|
||||
}
|
||||
while (keydef >= share->keydef)
|
||||
{
|
||||
if ((*keydef->delete_key)(info, keydef, record, pos, 0))
|
||||
break;
|
||||
} while (key-- > 0);
|
||||
keydef--;
|
||||
}
|
||||
|
||||
share->deleted++;
|
||||
*((byte**) pos)=share->del_link;
|
||||
|
@ -77,6 +84,36 @@ err:
|
|||
DBUG_RETURN(my_errno);
|
||||
} /* heap_write */
|
||||
|
||||
/*
|
||||
Write a key to rb_tree-index
|
||||
*/
|
||||
|
||||
int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record,
|
||||
byte *recpos)
|
||||
{
|
||||
heap_rb_param custom_arg;
|
||||
|
||||
info->last_pos= NULL; /* For heap_rnext/heap_rprev */
|
||||
custom_arg.keyseg= keyinfo->seg;
|
||||
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
|
||||
if (keyinfo->flag & HA_NOSAME)
|
||||
{
|
||||
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
|
||||
keyinfo->rb_tree.flag= TREE_NO_DUPS;
|
||||
}
|
||||
else
|
||||
{
|
||||
custom_arg.search_flag= SEARCH_SAME;
|
||||
keyinfo->rb_tree.flag= 0;
|
||||
}
|
||||
if (!tree_insert(&keyinfo->rb_tree, (void*)info->recbuf,
|
||||
custom_arg.key_length, &custom_arg))
|
||||
{
|
||||
my_errno= HA_ERR_FOUND_DUPP_KEY;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find where to place new record */
|
||||
|
||||
|
@ -102,7 +139,7 @@ static byte *next_free_record_pos(HP_SHARE *info)
|
|||
my_errno=HA_ERR_RECORD_FILE_FULL;
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
if (_hp_get_new_block(&info->block,&length))
|
||||
if (hp_get_new_block(&info->block,&length))
|
||||
DBUG_RETURN(NULL);
|
||||
info->data_length+=length;
|
||||
}
|
||||
|
@ -113,12 +150,12 @@ static byte *next_free_record_pos(HP_SHARE *info)
|
|||
block_pos*info->block.recbuffer);
|
||||
}
|
||||
|
||||
|
||||
/* Write a hash-key to the hash-index */
|
||||
|
||||
int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
||||
int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
|
||||
const byte *record, byte *recpos)
|
||||
{
|
||||
HP_SHARE *share = info->s;
|
||||
int flag;
|
||||
ulong halfbuff,hashnr,first_index;
|
||||
byte *ptr_to_rec,*ptr_to_rec2;
|
||||
|
@ -129,18 +166,18 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||
LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2);
|
||||
|
||||
flag=0;
|
||||
if (!(empty= _hp_find_free_hash(info,&keyinfo->block,info->records)))
|
||||
if (!(empty= hp_find_free_hash(share,&keyinfo->block,share->records)))
|
||||
DBUG_RETURN(-1); /* No more memory */
|
||||
halfbuff= (long) info->blength >> 1;
|
||||
pos= hp_find_hash(&keyinfo->block,(first_index=info->records-halfbuff));
|
||||
halfbuff= (long) share->blength >> 1;
|
||||
pos= hp_find_hash(&keyinfo->block,(first_index=share->records-halfbuff));
|
||||
|
||||
if (pos != empty) /* If some records */
|
||||
{
|
||||
do
|
||||
{
|
||||
hashnr=_hp_rec_hashnr(keyinfo,pos->ptr_to_rec);
|
||||
hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
|
||||
if (flag == 0) /* First loop; Check if ok */
|
||||
if (_hp_mask(hashnr,info->blength,info->records) != first_index)
|
||||
if (hp_mask(hashnr, share->blength, share->records) != first_index)
|
||||
break;
|
||||
if (!(hashnr & halfbuff))
|
||||
{ /* Key will not move */
|
||||
|
@ -212,8 +249,8 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||
}
|
||||
/* Check if we are at the empty position */
|
||||
|
||||
pos=hp_find_hash(&keyinfo->block,_hp_mask(_hp_rec_hashnr(keyinfo,record),
|
||||
info->blength,info->records+1));
|
||||
pos=hp_find_hash(&keyinfo->block, hp_mask(hp_rec_hashnr(keyinfo, record),
|
||||
share->blength, share->records + 1));
|
||||
if (pos == empty)
|
||||
{
|
||||
pos->ptr_to_rec=recpos;
|
||||
|
@ -224,8 +261,8 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||
/* Check if more records in same hash-nr family */
|
||||
empty[0]=pos[0];
|
||||
gpos=hp_find_hash(&keyinfo->block,
|
||||
_hp_mask(_hp_rec_hashnr(keyinfo,pos->ptr_to_rec),
|
||||
info->blength,info->records+1));
|
||||
hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec),
|
||||
share->blength, share->records + 1));
|
||||
if (pos == gpos)
|
||||
{
|
||||
pos->ptr_to_rec=recpos;
|
||||
|
@ -235,7 +272,7 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||
{
|
||||
pos->ptr_to_rec=recpos;
|
||||
pos->next_key=0;
|
||||
_hp_movelink(pos,gpos,empty);
|
||||
hp_movelink(pos, gpos, empty);
|
||||
}
|
||||
|
||||
/* Check if duplicated keys */
|
||||
|
@ -246,7 +283,7 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||
pos=empty;
|
||||
do
|
||||
{
|
||||
if (! _hp_rec_key_cmp(keyinfo,record,pos->ptr_to_rec))
|
||||
if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
|
||||
{
|
||||
DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
|
||||
}
|
||||
|
@ -258,7 +295,7 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||
|
||||
/* Returns ptr to block, and allocates block if neaded */
|
||||
|
||||
static HASH_INFO *_hp_find_free_hash(HP_SHARE *info,
|
||||
static HASH_INFO *hp_find_free_hash(HP_SHARE *info,
|
||||
HP_BLOCK *block, ulong records)
|
||||
{
|
||||
uint block_pos;
|
||||
|
@ -268,7 +305,7 @@ static HASH_INFO *_hp_find_free_hash(HP_SHARE *info,
|
|||
return hp_find_hash(block,records);
|
||||
if (!(block_pos=(records % block->records_in_block)))
|
||||
{
|
||||
if (_hp_get_new_block(block,&length))
|
||||
if (hp_get_new_block(block,&length))
|
||||
return(NULL);
|
||||
info->index_length+=length;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,8 @@ noinst_HEADERS = config-win.h config-os2.h \
|
|||
my_dir.h mysys_err.h my_base.h \
|
||||
my_nosys.h my_alarm.h queues.h rijndael.h sha1.h \
|
||||
my_aes.h my_tree.h hash.h thr_alarm.h \
|
||||
thr_lock.h t_ctype.h violite.h md5.h mysql_version.h.in
|
||||
thr_lock.h t_ctype.h violite.h md5.h \
|
||||
mysql_version.h.in my_handler.h
|
||||
|
||||
# mysql_version.h are generated
|
||||
SUPERCLEANFILES = mysql_version.h my_config.h
|
||||
|
|
|
@ -61,3 +61,14 @@ extern const char *client_errors[]; /* Error messages */
|
|||
#define CR_PROBE_SLAVE_HOSTS 2023
|
||||
#define CR_PROBE_SLAVE_CONNECT 2024
|
||||
#define CR_PROBE_MASTER_CONNECT 2025
|
||||
|
||||
/* new 4.1 error codes */
|
||||
#define CR_INVALID_CONN_HANDLE 2026
|
||||
#define CR_NULL_POINTER 2027
|
||||
#define CR_NO_PREPARE_STMT 2028
|
||||
#define CR_NOT_ALL_PARAMS_BOUND 2029
|
||||
#define CR_DATA_TRUNCATED 2030
|
||||
#define CR_NO_PARAMETERS_EXISTS 2031
|
||||
#define CR_INVALID_PARAMETER_NO 2032
|
||||
#define CR_INVALID_BUFFER_USE 2033
|
||||
#define CR_UNSUPPORTED_PARAM_TYPE 2034
|
||||
|
|
|
@ -40,13 +40,15 @@ typedef struct st_hash {
|
|||
DYNAMIC_ARRAY array; /* Place for hash_keys */
|
||||
hash_get_key get_key;
|
||||
void (*free)(void *);
|
||||
uint (*calc_hashnr)(const byte *key,uint length);
|
||||
uint (*calc_hashnr)(CHARSET_INFO *cs, const byte *key,uint length);
|
||||
CHARSET_INFO *charset;
|
||||
} HASH;
|
||||
|
||||
#define hash_init(A,B,C,D,E,F,G) _hash_init(A,B,C,D,E,F,G CALLER_INFO)
|
||||
my_bool _hash_init(HASH *hash,uint default_array_elements, uint key_offset,
|
||||
uint key_length, hash_get_key get_key,
|
||||
void (*free_element)(void*), uint flags CALLER_INFO_PROTO);
|
||||
#define hash_init(A,B,C,D,E,F,G,H) _hash_init(A,B,C,D,E,F,G, H CALLER_INFO)
|
||||
my_bool _hash_init(HASH *hash, CHARSET_INFO *charset,
|
||||
uint default_array_elements, uint key_offset,
|
||||
uint key_length, hash_get_key get_key,
|
||||
void (*free_element)(void*), uint flags CALLER_INFO_PROTO);
|
||||
void hash_free(HASH *tree);
|
||||
byte *hash_element(HASH *hash,uint idx);
|
||||
gptr hash_search(HASH *info,const byte *key,uint length);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
/* This file should be included when using heap_database_funktions */
|
||||
/* This file should be included when using heap_database_functions */
|
||||
/* Author: Michael Widenius */
|
||||
|
||||
#ifndef _heap_h
|
||||
|
@ -31,6 +31,9 @@ extern "C" {
|
|||
#include <thr_lock.h>
|
||||
#endif
|
||||
|
||||
#include "my_handler.h"
|
||||
#include "my_tree.h"
|
||||
|
||||
/* defines used by heap-funktions */
|
||||
|
||||
#define HP_MAX_LEVELS 4 /* 128^5 records is enough */
|
||||
|
@ -73,22 +76,22 @@ typedef struct st_heap_block /* The data is saved in blocks */
|
|||
ulong last_allocated; /* Blocks allocated, used by keys */
|
||||
} HP_BLOCK;
|
||||
|
||||
typedef struct st_hp_keyseg /* Key-portion */
|
||||
{
|
||||
uint start; /* Start of key in record (from 0) */
|
||||
uint length; /* Keylength */
|
||||
uint type;
|
||||
uint null_bit; /* bit set in row+null_pos */
|
||||
uint null_pos;
|
||||
} HP_KEYSEG;
|
||||
struct st_heap_info; /* For referense */
|
||||
|
||||
typedef struct st_hp_keydef /* Key definition with open */
|
||||
{
|
||||
uint flag; /* HA_NOSAME | HA_NULL_PART_KEY */
|
||||
uint keysegs; /* Number of key-segment */
|
||||
uint length; /* Length of key (automatic) */
|
||||
HP_KEYSEG *seg;
|
||||
uint8 algorithm; /* HASH / BTREE */
|
||||
HA_KEYSEG *seg;
|
||||
HP_BLOCK block; /* Where keys are saved */
|
||||
TREE rb_tree;
|
||||
int (*write_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo,
|
||||
const byte *record, byte *recpos);
|
||||
int (*delete_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo,
|
||||
const byte *record, byte *recpos, int flag);
|
||||
uint (*get_key_length)(struct st_hp_keydef *keydef, const byte *key);
|
||||
} HP_KEYDEF;
|
||||
|
||||
typedef struct st_heap_share
|
||||
|
@ -126,6 +129,11 @@ typedef struct st_heap_info
|
|||
int mode; /* Mode of file (READONLY..) */
|
||||
uint opt_flag,update;
|
||||
byte *lastkey; /* Last used key with rkey */
|
||||
byte *recbuf; /* Record buffer for rb-tree keys */
|
||||
enum ha_rkey_function last_find_flag;
|
||||
TREE_ELEMENT *parents[MAX_TREE_HEIGHT+1];
|
||||
TREE_ELEMENT **last_pos;
|
||||
uint lastkey_len;
|
||||
#ifdef THREAD
|
||||
THR_LOCK_DATA lock;
|
||||
#endif
|
||||
|
@ -134,9 +142,7 @@ typedef struct st_heap_info
|
|||
|
||||
/* Prototypes for heap-functions */
|
||||
|
||||
extern HP_INFO* heap_open(const char *name,int mode,uint keys,
|
||||
HP_KEYDEF *keydef,uint reclength,
|
||||
ulong max_records,ulong min_reloc);
|
||||
extern HP_INFO *heap_open(const char *name, int mode);
|
||||
extern int heap_close(HP_INFO *info);
|
||||
extern int heap_write(HP_INFO *info,const byte *buff);
|
||||
extern int heap_update(HP_INFO *info,const byte *old,const byte *newdata);
|
||||
|
@ -145,7 +151,8 @@ extern int heap_scan_init(HP_INFO *info);
|
|||
extern int heap_scan(register HP_INFO *info, byte *record);
|
||||
extern int heap_delete(HP_INFO *info,const byte *buff);
|
||||
extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag);
|
||||
extern int heap_create(const char *name);
|
||||
extern int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
|
||||
uint reclength, ulong max_records, ulong min_records);
|
||||
extern int heap_delete_table(const char *name);
|
||||
extern int heap_extra(HP_INFO *info,enum ha_extra_function function);
|
||||
extern int heap_rename(const char *old_name,const char *new_name);
|
||||
|
@ -153,10 +160,17 @@ extern int heap_panic(enum ha_panic_function flag);
|
|||
extern int heap_rsame(HP_INFO *info,byte *record,int inx);
|
||||
extern int heap_rnext(HP_INFO *info,byte *record);
|
||||
extern int heap_rprev(HP_INFO *info,byte *record);
|
||||
extern int heap_rfirst(HP_INFO *info,byte *record);
|
||||
extern int heap_rlast(HP_INFO *info,byte *record);
|
||||
extern int heap_rfirst(HP_INFO *info,byte *record,int inx);
|
||||
extern int heap_rlast(HP_INFO *info,byte *record,int inx);
|
||||
extern void heap_clear(HP_INFO *info);
|
||||
extern int heap_rkey(HP_INFO *info,byte *record,int inx,const byte *key);
|
||||
|
||||
ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, const byte *start_key,
|
||||
uint start_key_len,
|
||||
enum ha_rkey_function start_search_flag,
|
||||
const byte *end_key, uint end_key_len,
|
||||
enum ha_rkey_function end_search_flag);
|
||||
int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
extern gptr heap_find(HP_INFO *info,int inx,const byte *key);
|
||||
extern int heap_check_heap(HP_INFO *info, my_bool print_status);
|
||||
extern byte *heap_position(HP_INFO *info);
|
||||
|
|
|
@ -26,68 +26,311 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define CHARSET_DIR "charsets/"
|
||||
|
||||
#define my_wc_t ulong
|
||||
|
||||
typedef struct unicase_info_st {
|
||||
uint16 toupper;
|
||||
uint16 tolower;
|
||||
uint16 sort;
|
||||
} MY_UNICASE_INFO;
|
||||
|
||||
#define MY_CS_ILSEQ 0
|
||||
#define MY_CS_ILUNI 0
|
||||
#define MY_CS_TOOSMALL -1
|
||||
#define MY_CS_TOOFEW(n) (-1-(n))
|
||||
|
||||
/* My charsets_list flags */
|
||||
#define MY_NO_SETS 0
|
||||
#define MY_CS_COMPILED 1 /* compiled-in sets */
|
||||
#define MY_CS_CONFIG 2 /* sets that have a *.conf file */
|
||||
#define MY_CS_INDEX 4 /* sets listed in the Index file */
|
||||
#define MY_CS_LOADED 8 /* sets that are currently loaded */
|
||||
|
||||
|
||||
typedef struct my_uni_idx_st {
|
||||
uint16 from;
|
||||
uint16 to;
|
||||
uchar *tab;
|
||||
} MY_UNI_IDX;
|
||||
|
||||
|
||||
typedef struct charset_info_st
|
||||
{
|
||||
uint number;
|
||||
const char *name;
|
||||
uchar *ctype;
|
||||
uchar *to_lower;
|
||||
uchar *to_upper;
|
||||
uchar *sort_order;
|
||||
|
||||
uint strxfrm_multiply;
|
||||
int (*strcoll)(const uchar *, const uchar *);
|
||||
int (*strxfrm)(uchar *, const uchar *, int);
|
||||
int (*strnncoll)(const uchar *, int, const uchar *, int);
|
||||
int (*strnxfrm)(uchar *, const uchar *, int, int);
|
||||
my_bool (*like_range)(const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);
|
||||
|
||||
uint mbmaxlen;
|
||||
int (*ismbchar)(const char *, const char *);
|
||||
my_bool (*ismbhead)(uint);
|
||||
int (*mbcharlen)(uint);
|
||||
uint number;
|
||||
uint state;
|
||||
const char *name;
|
||||
const char *comment;
|
||||
uchar *ctype;
|
||||
uchar *to_lower;
|
||||
uchar *to_upper;
|
||||
uchar *sort_order;
|
||||
uint16 *tab_to_uni;
|
||||
MY_UNI_IDX *tab_from_uni;
|
||||
|
||||
/* Collation routines */
|
||||
uint strxfrm_multiply;
|
||||
int (*strnncoll)(struct charset_info_st *,
|
||||
const uchar *, uint, const uchar *, uint);
|
||||
int (*strnxfrm)(struct charset_info_st *,
|
||||
uchar *, uint, const uchar *, uint);
|
||||
my_bool (*like_range)(struct charset_info_st *,
|
||||
const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);
|
||||
|
||||
/* Multibyte routines */
|
||||
uint mbmaxlen;
|
||||
int (*ismbchar)(struct charset_info_st *, const char *, const char *);
|
||||
my_bool (*ismbhead)(struct charset_info_st *, uint);
|
||||
int (*mbcharlen)(struct charset_info_st *, uint);
|
||||
|
||||
/* Unicode convertion */
|
||||
int (*mb_wc)(struct charset_info_st *cs,my_wc_t *wc,
|
||||
const unsigned char *s,const unsigned char *e);
|
||||
int (*wc_mb)(struct charset_info_st *cs,my_wc_t wc,
|
||||
unsigned char *s,unsigned char *e);
|
||||
|
||||
/* Functions for case convertion */
|
||||
void (*caseup_str)(struct charset_info_st *, char *);
|
||||
void (*casedn_str)(struct charset_info_st *, char *);
|
||||
void (*caseup)(struct charset_info_st *, char *, uint);
|
||||
void (*casedn)(struct charset_info_st *, char *, uint);
|
||||
|
||||
/* Functions for case comparison */
|
||||
int (*strcasecmp)(struct charset_info_st *, const char *, const char *);
|
||||
int (*strncasecmp)(struct charset_info_st *, const char *, const char *,
|
||||
uint);
|
||||
|
||||
/* Hash calculation */
|
||||
uint (*hash_caseup)(struct charset_info_st *cs, const byte *key, uint len);
|
||||
void (*hash_sort)(struct charset_info_st *cs, const uchar *key, uint len,
|
||||
ulong *nr1, ulong *nr2);
|
||||
|
||||
char max_sort_char; /* For LIKE optimization */
|
||||
} CHARSET_INFO;
|
||||
|
||||
/* strings/ctype.c */
|
||||
extern CHARSET_INFO *default_charset_info;
|
||||
extern CHARSET_INFO *system_charset_info;
|
||||
extern CHARSET_INFO *find_compiled_charset(uint cs_number);
|
||||
extern CHARSET_INFO *find_compiled_charset_by_name(const char *name);
|
||||
extern CHARSET_INFO compiled_charsets[];
|
||||
extern CHARSET_INFO all_charsets[256];
|
||||
extern uint compiled_charset_number(const char *name);
|
||||
extern const char *compiled_charset_name(uint charset_number);
|
||||
|
||||
#define MY_CHARSET_UNDEFINED 0
|
||||
#define MY_CHARSET_CURRENT (default_charset_info->number)
|
||||
|
||||
/* Don't include std ctype.h when this is included */
|
||||
#define _CTYPE_H
|
||||
#define _CTYPE_H_
|
||||
#define _CTYPE_INCLUDED
|
||||
#define __CTYPE_INCLUDED
|
||||
#define _CTYPE_USING /* Don't put names in global namespace. */
|
||||
/* declarations for simple charsets */
|
||||
extern int my_strnxfrm_simple(CHARSET_INFO *, char *, uint, const char *, uint);
|
||||
extern int my_strnncoll_simple(CHARSET_INFO *, const char *, uint, const char *, uint);
|
||||
|
||||
/* Functions for 8bit */
|
||||
extern void my_caseup_str_8bit(CHARSET_INFO *, char *);
|
||||
extern void my_casedn_str_8bit(CHARSET_INFO *, char *);
|
||||
extern void my_caseup_8bit(CHARSET_INFO *, char *, uint);
|
||||
extern void my_casedn_8bit(CHARSET_INFO *, char *, uint);
|
||||
|
||||
extern int my_strcasecmp_8bit(CHARSET_INFO * cs, const char *, const char *);
|
||||
extern int my_strncasecmp_8bit(CHARSET_INFO * cs, const char *, const char *, uint);
|
||||
|
||||
int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc, const uchar *s,const uchar *e);
|
||||
int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e);
|
||||
|
||||
|
||||
#ifdef USE_MB
|
||||
/* Functions for multibyte charsets */
|
||||
extern void my_caseup_str_mb(CHARSET_INFO *, char *);
|
||||
extern void my_casedn_str_mb(CHARSET_INFO *, char *);
|
||||
extern void my_caseup_mb(CHARSET_INFO *, char *, uint);
|
||||
extern void my_casedn_mb(CHARSET_INFO *, char *, uint);
|
||||
extern int my_strcasecmp_mb(CHARSET_INFO * cs,const char *, const char *);
|
||||
extern int my_strncasecmp_mb(CHARSET_INFO * cs,const char *, const char *t, uint);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHARSET_big5
|
||||
/* declarations for the big5 character set */
|
||||
extern uchar ctype_big5[], to_lower_big5[], to_upper_big5[], sort_order_big5[];
|
||||
extern int my_strnncoll_big5(CHARSET_INFO *,const uchar *, uint, const uchar *, uint);
|
||||
extern int my_strnxfrm_big5(CHARSET_INFO *,uchar *, uint, const uchar *, uint);
|
||||
extern my_bool my_like_range_big5(CHARSET_INFO *,const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);
|
||||
extern int ismbchar_big5(CHARSET_INFO *, const char *, const char *);
|
||||
extern my_bool ismbhead_big5(CHARSET_INFO *, uint);
|
||||
extern int mbcharlen_big5(CHARSET_INFO *, uint);
|
||||
int my_mb_wc_big5(CHARSET_INFO *cs,my_wc_t *wc, const uchar *s,const uchar *e);
|
||||
int my_wc_mb_big5(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHARSET_czech
|
||||
/* declarations for the czech character set */
|
||||
extern uchar ctype_czech[], to_lower_czech[], to_upper_czech[], sort_order_czech[];
|
||||
extern int my_strnncoll_czech(CHARSET_INFO *, const uchar *, uint, const uchar *, uint);
|
||||
extern int my_strnxfrm_czech(CHARSET_INFO *, uchar *, uint, const uchar *, uint);
|
||||
extern my_bool my_like_range_czech(CHARSET_INFO *,
|
||||
const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_CHARSET_win1250ch
|
||||
/* declarations for the win1250ch character set */
|
||||
extern uchar ctype_win1250ch[];
|
||||
extern uchar to_lower_win1250ch[];
|
||||
extern uchar to_upper_win1250ch[];
|
||||
extern uchar sort_order_win1250ch[];
|
||||
extern int my_strnncoll_win1250ch(CHARSET_INFO *, const uchar *, uint, const uchar *, uint);
|
||||
extern int my_strnxfrm_win1250ch(CHARSET_INFO *, uchar *, uint, const uchar *, uint);
|
||||
extern my_bool my_like_range_win1250ch(CHARSET_INFO *,
|
||||
const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_CHARSET_euc_kr
|
||||
/* declarations for the euc_kr character set */
|
||||
extern uchar ctype_euc_kr[], to_lower_euc_kr[], to_upper_euc_kr[], sort_order_euc_kr[];
|
||||
extern int ismbchar_euc_kr(CHARSET_INFO *, const char *, const char *);
|
||||
extern my_bool ismbhead_euc_kr(CHARSET_INFO *, uint);
|
||||
extern int mbcharlen_euc_kr(CHARSET_INFO *, uint);
|
||||
int my_mb_wc_euc_kr(CHARSET_INFO *cs,my_wc_t *wc, const uchar *s,const uchar *e);
|
||||
int my_wc_mb_euc_kr(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHARSET_gb2312
|
||||
/* declarations for the gb2312 character set */
|
||||
extern uchar ctype_gb2312[], to_lower_gb2312[], to_upper_gb2312[], sort_order_gb2312[];
|
||||
extern int ismbchar_gb2312(CHARSET_INFO *, const char *, const char *);
|
||||
extern my_bool ismbhead_gb2312(CHARSET_INFO *, uint);
|
||||
extern int mbcharlen_gb2312(CHARSET_INFO *, uint);
|
||||
int my_mb_wc_gb2312(CHARSET_INFO *cs,my_wc_t *wc, const uchar *s,const uchar *e);
|
||||
int my_wc_mb_gb2312(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHARSET_gbk
|
||||
/* declarations for the gbk character set */
|
||||
extern uchar ctype_gbk[], to_lower_gbk[], to_upper_gbk[], sort_order_gbk[];
|
||||
extern int my_strnncoll_gbk(CHARSET_INFO *, const uchar *, uint, const uchar *, uint);
|
||||
extern int my_strnxfrm_gbk(CHARSET_INFO *, uchar *, uint, const uchar *, uint);
|
||||
extern my_bool my_like_range_gbk(CHARSET_INFO *, const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);
|
||||
extern int ismbchar_gbk(CHARSET_INFO *, const char *, const char *);
|
||||
extern my_bool ismbhead_gbk(CHARSET_INFO *, uint);
|
||||
extern int mbcharlen_gbk(CHARSET_INFO *, uint);
|
||||
int my_mb_wc_gbk(CHARSET_INFO *cs,my_wc_t *wc, const uchar *s,const uchar *e);
|
||||
int my_wc_mb_gbk(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHARSET_latin1_de
|
||||
/* declarations for the latin1_de character set */
|
||||
extern uchar ctype_latin1_de[], to_lower_latin1_de[], to_upper_latin1_de[], sort_order_latin1_de[];
|
||||
extern int my_strnncoll_latin1_de(CHARSET_INFO *, const uchar *, uint, const uchar *, uint);
|
||||
extern int my_strnxfrm_latin1_de(CHARSET_INFO *, uchar *, uint, const uchar *, uint);
|
||||
extern my_bool my_like_range_latin1_de(CHARSET_INFO *, const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHARSET_sjis
|
||||
/* declarations for the sjis character set */
|
||||
extern uchar ctype_sjis[], to_lower_sjis[], to_upper_sjis[], sort_order_sjis[];
|
||||
extern int my_strnncoll_sjis(CHARSET_INFO *, const uchar *, uint, const uchar *, uint);
|
||||
extern int my_strnxfrm_sjis(CHARSET_INFO *, uchar *, uint, const uchar *, uint);
|
||||
extern my_bool my_like_range_sjis(CHARSET_INFO *, const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);
|
||||
extern int ismbchar_sjis(CHARSET_INFO *, const char *, const char *);
|
||||
extern my_bool ismbhead_sjis(CHARSET_INFO *, uint);
|
||||
extern int mbcharlen_sjis(CHARSET_INFO *, uint);
|
||||
int my_mb_wc_sjis(CHARSET_INFO *cs,my_wc_t *wc, const uchar *s,const uchar *e);
|
||||
int my_wc_mb_sjis(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHARSET_tis620
|
||||
/* declarations for the tis620 character set */
|
||||
extern uchar ctype_tis620[], to_lower_tis620[], to_upper_tis620[], sort_order_tis620[];
|
||||
extern int my_strnncoll_tis620(CHARSET_INFO *, const uchar *, uint, const uchar *, uint);
|
||||
extern int my_strnxfrm_tis620(CHARSET_INFO *, uchar *, uint, const uchar *, uint);
|
||||
extern my_bool my_like_range_tis620(CHARSET_INFO *, const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHARSET_ujis
|
||||
/* declarations for the ujis character set */
|
||||
extern uchar ctype_ujis[], to_lower_ujis[], to_upper_ujis[], sort_order_ujis[];
|
||||
extern int ismbchar_ujis(CHARSET_INFO *, const char *, const char *);
|
||||
extern my_bool ismbhead_ujis(CHARSET_INFO *, uint);
|
||||
extern int mbcharlen_ujis(CHARSET_INFO *, uint);
|
||||
int my_mb_wc_euc_jp(CHARSET_INFO *cs,my_wc_t *wc, const uchar *s,const uchar *e);
|
||||
int my_wc_mb_euc_jp(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHARSET_utf8
|
||||
|
||||
extern uchar ctype_utf8[];
|
||||
extern uchar to_lower_utf8[];
|
||||
extern uchar to_upper_utf8[];
|
||||
|
||||
int my_strnncoll_utf8(CHARSET_INFO *cs,
|
||||
const uchar *s, uint s_len, const uchar *t, uint t_len);
|
||||
|
||||
int my_strnxfrm_utf8(CHARSET_INFO *cs,
|
||||
uchar *dest, uint destlen, const uchar *src, uint srclen);
|
||||
|
||||
int my_ismbchar_utf8(CHARSET_INFO *cs, const char *b, const char *e);
|
||||
my_bool my_ismbhead_utf8(CHARSET_INFO * cs, uint ch);
|
||||
int my_mbcharlen_utf8(CHARSET_INFO *cs, uint c);
|
||||
|
||||
void my_caseup_str_utf8(CHARSET_INFO * cs, char * s);
|
||||
void my_casedn_str_utf8(CHARSET_INFO *cs, char * s);
|
||||
void my_caseup_utf8(CHARSET_INFO *cs, char *s, uint len);
|
||||
void my_casedn_utf8(CHARSET_INFO *cs, char *s, uint len);
|
||||
|
||||
int my_strcasecmp_utf8(CHARSET_INFO *cs, const char *s, const char *t);
|
||||
int my_strncasecmp_utf8(CHARSET_INFO *cs, const char *s,const char *t,uint l);
|
||||
|
||||
int my_utf8_uni (CHARSET_INFO *cs, my_wc_t *p, const uchar *s, const uchar *e);
|
||||
int my_uni_utf8 (CHARSET_INFO *cs, my_wc_t wc, uchar *b, uchar *e);
|
||||
|
||||
uint my_hash_caseup_utf8(struct charset_info_st *cs, const byte *key, uint len);
|
||||
void my_hash_sort_utf8(struct charset_info_st *cs, const uchar *key, uint len, ulong *nr1, ulong *nr2);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_CHARSET_ucs2
|
||||
|
||||
extern uchar ctype_ucs2[];
|
||||
extern uchar to_lower_ucs2[];
|
||||
extern uchar to_upper_ucs2[];
|
||||
|
||||
int my_strnncoll_ucs2(CHARSET_INFO *cs,
|
||||
const uchar *s, uint s_len, const uchar *t, uint t_len);
|
||||
|
||||
int my_strnxfrm_ucs2(CHARSET_INFO *cs,
|
||||
uchar *dest, uint destlen, const uchar *src, uint srclen);
|
||||
|
||||
int my_ismbchar_ucs2(CHARSET_INFO *cs, const char *b, const char *e);
|
||||
my_bool my_ismbhead_ucs2(CHARSET_INFO * cs, uint ch);
|
||||
int my_mbcharlen_ucs2(CHARSET_INFO *cs, uint c);
|
||||
|
||||
void my_caseup_str_ucs2(CHARSET_INFO * cs, char * s);
|
||||
void my_casedn_str_ucs2(CHARSET_INFO *cs, char * s);
|
||||
void my_caseup_ucs2(CHARSET_INFO *cs, char *s, uint len);
|
||||
void my_casedn_ucs2(CHARSET_INFO *cs, char *s, uint len);
|
||||
|
||||
int my_strcasecmp_ucs2(CHARSET_INFO *cs, const char *s, const char *t);
|
||||
int my_strncasecmp_ucs2(CHARSET_INFO *cs, const char *s,const char *t,uint l);
|
||||
|
||||
int my_ucs2_uni (CHARSET_INFO *cs, my_wc_t *p, const uchar *s, const uchar *e);
|
||||
int my_uni_ucs2 (CHARSET_INFO *cs, my_wc_t wc, uchar *b, uchar *e);
|
||||
|
||||
uint my_hash_caseup_ucs2(struct charset_info_st *cs, const byte *key, uint len);
|
||||
void my_hash_sort_ucs2(struct charset_info_st *cs, const uchar *key, uint len, ulong *nr1, ulong *nr2);
|
||||
|
||||
#endif
|
||||
|
||||
/* Fix things, if ctype.h would have been included before */
|
||||
#undef toupper
|
||||
#undef _toupper
|
||||
#undef _tolower
|
||||
#undef toupper
|
||||
#undef tolower
|
||||
#undef isalpha
|
||||
#undef isupper
|
||||
#undef islower
|
||||
#undef isdigit
|
||||
#undef isxdigit
|
||||
#undef isalnum
|
||||
#undef isspace
|
||||
#undef ispunct
|
||||
#undef isprint
|
||||
#undef isgraph
|
||||
#undef iscntrl
|
||||
#undef isascii
|
||||
#undef toascii
|
||||
|
||||
#define _U 01 /* Upper case */
|
||||
#define _L 02 /* Lower case */
|
||||
|
@ -98,34 +341,13 @@ extern const char *compiled_charset_name(uint charset_number);
|
|||
#define _B 0100 /* Blank */
|
||||
#define _X 0200 /* heXadecimal digit */
|
||||
|
||||
#define my_ctype (default_charset_info->ctype)
|
||||
#define my_to_upper (default_charset_info->to_upper)
|
||||
#define my_to_lower (default_charset_info->to_lower)
|
||||
#define my_sort_order (default_charset_info->sort_order)
|
||||
|
||||
#define _toupper(c) (char) my_to_upper[(uchar) (c)]
|
||||
#define _tolower(c) (char) my_to_lower[(uchar) (c)]
|
||||
#define toupper(c) (char) my_to_upper[(uchar) (c)]
|
||||
#define tolower(c) (char) my_to_lower[(uchar) (c)]
|
||||
|
||||
#define isalpha(c) ((my_ctype+1)[(uchar) (c)] & (_U | _L))
|
||||
#define isupper(c) ((my_ctype+1)[(uchar) (c)] & _U)
|
||||
#define islower(c) ((my_ctype+1)[(uchar) (c)] & _L)
|
||||
#define isdigit(c) ((my_ctype+1)[(uchar) (c)] & _NMR)
|
||||
#define isxdigit(c) ((my_ctype+1)[(uchar) (c)] & _X)
|
||||
#define isalnum(c) ((my_ctype+1)[(uchar) (c)] & (_U | _L | _NMR))
|
||||
#define isspace(c) ((my_ctype+1)[(uchar) (c)] & _SPC)
|
||||
#define ispunct(c) ((my_ctype+1)[(uchar) (c)] & _PNT)
|
||||
#define isprint(c) ((my_ctype+1)[(uchar) (c)] & (_PNT | _U | _L | _NMR | _B))
|
||||
#define isgraph(c) ((my_ctype+1)[(uchar) (c)] & (_PNT | _U | _L | _NMR))
|
||||
#define iscntrl(c) ((my_ctype+1)[(uchar) (c)] & _CTR)
|
||||
#define isascii(c) (!((c) & ~0177))
|
||||
#define toascii(c) ((c) & 0177)
|
||||
|
||||
#ifdef ctype
|
||||
#undef ctype
|
||||
#endif /* ctype */
|
||||
|
||||
#define my_isascii(c) (!((c) & ~0177))
|
||||
#define my_toascii(c) ((c) & 0177)
|
||||
#define my_tocntrl(c) ((c) & 31)
|
||||
#define my_toprint(c) ((c) | 64)
|
||||
#define my_toupper(s,c) (char) ((s)->to_upper[(uchar) (c)])
|
||||
#define my_tolower(s,c) (char) ((s)->to_lower[(uchar) (c)])
|
||||
#define my_isalpha(s, c) (((s)->ctype+1)[(uchar) (c)] & (_U | _L))
|
||||
#define my_isupper(s, c) (((s)->ctype+1)[(uchar) (c)] & _U)
|
||||
#define my_islower(s, c) (((s)->ctype+1)[(uchar) (c)] & _L)
|
||||
|
@ -138,26 +360,28 @@ extern const char *compiled_charset_name(uint charset_number);
|
|||
#define my_isgraph(s, c) (((s)->ctype+1)[(uchar) (c)] & (_PNT | _U | _L | _NMR))
|
||||
#define my_iscntrl(s, c) (((s)->ctype+1)[(uchar) (c)] & _CTR)
|
||||
|
||||
#define use_strcoll(s) ((s)->strcoll != NULL)
|
||||
#define MY_STRXFRM_MULTIPLY (default_charset_info->strxfrm_multiply)
|
||||
#define my_strnxfrm(s, a, b, c, d) ((s)->strnxfrm((a), (b), (c), (d)))
|
||||
#define my_strnncoll(s, a, b, c, d) ((s)->strnncoll((a), (b), (c), (d)))
|
||||
#define my_strxfrm(s, a, b, c, d) ((s)->strnxfrm((a), (b), (c)))
|
||||
#define my_strcoll(s, a, b) ((s)->strcoll((a), (b)))
|
||||
/* Some macros that should be cleaned up a little */
|
||||
#define my_isvar(s,c) (my_isalnum(s,c) || (c) == '_')
|
||||
#define my_isvar_start(s,c) (my_isalpha(s,c) || (c) == '_')
|
||||
|
||||
#define use_strcoll(s) ((s)->strnncoll != NULL)
|
||||
#define my_strnxfrm(s, a, b, c, d) ((s)->strnxfrm((s), (a), (b), (c), (d)))
|
||||
#define my_strnncoll(s, a, b, c, d) ((s)->strnncoll((s), (a), (b), (c), (d)))
|
||||
#define my_like_range(s, a, b, c, d, e, f, g, h) \
|
||||
((s)->like_range((a), (b), (c), (d), (e), (f), (g), (h)))
|
||||
((s)->like_range((s), (a), (b), (c), (d), (e), (f), (g), (h)))
|
||||
|
||||
#define use_mb(s) ((s)->ismbchar != NULL)
|
||||
#define MBMAXLEN (default_charset_info->mbmaxlen)
|
||||
#define my_ismbchar(s, a, b) ((s)->ismbchar((a), (b)))
|
||||
#define my_ismbhead(s, a) ((s)->ismbhead((a)))
|
||||
#define my_mbcharlen(s, a) ((s)->mbcharlen((a)))
|
||||
#define my_ismbchar(s, a, b) ((s)->ismbchar((s), (a), (b)))
|
||||
#define my_ismbhead(s, a) ((s)->ismbhead((s), (a)))
|
||||
#define my_mbcharlen(s, a) ((s)->mbcharlen((s),(a)))
|
||||
|
||||
#define my_caseup(s, a, l) ((s)->caseup((s), (a), (l)))
|
||||
#define my_casedn(s, a, l) ((s)->casedn((s), (a), (l)))
|
||||
#define my_caseup_str(s, a) ((s)->caseup_str((s), (a)))
|
||||
#define my_casedn_str(s, a) ((s)->casedn_str((s), (a)))
|
||||
#define my_strcasecmp(s, a, b) ((s)->strcasecmp((s), (a), (b)))
|
||||
#define my_strncasecmp(s, a, b, l) ((s)->strncasecmp((s), (a), (b), (l)))
|
||||
|
||||
/* Some macros that should be cleaned up a little */
|
||||
#define isvar(c) (isalnum(c) || (c) == '_')
|
||||
#define isvar_start(c) (isalpha(c) || (c) == '_')
|
||||
#define tocntrl(c) ((c) & 31)
|
||||
#define toprint(c) ((c) | 64)
|
||||
|
||||
/* XXX: still need to take care of this one */
|
||||
#ifdef MY_CHARSET_TIS620
|
||||
|
|
|
@ -150,9 +150,9 @@ enum ha_base_keytype {
|
|||
#define HA_PACK_KEY 2 /* Pack string key to previous key */
|
||||
#define HA_AUTO_KEY 16
|
||||
#define HA_BINARY_PACK_KEY 32 /* Packing of all keys to prev key */
|
||||
#define HA_FULLTEXT 128 /* SerG: for full-text search */
|
||||
#define HA_FULLTEXT 128 /* For full-text search */
|
||||
#define HA_UNIQUE_CHECK 256 /* Check the key for uniqueness */
|
||||
#define HA_SPATIAL 1024 /* Alex Barkov: for spatial search */
|
||||
#define HA_SPATIAL 1024 /* For spatial search */
|
||||
#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */
|
||||
|
||||
|
||||
|
|
59
include/my_handler.h
Normal file
59
include/my_handler.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA */
|
||||
|
||||
#ifndef _my_handler_h
|
||||
#define _my_handler_h
|
||||
|
||||
#include "my_global.h"
|
||||
#include "my_base.h"
|
||||
#include "m_ctype.h"
|
||||
#include "myisampack.h"
|
||||
|
||||
typedef struct st_HA_KEYSEG /* Key-portion */
|
||||
{
|
||||
uint8 type; /* Type of key (for sort) */
|
||||
uint8 language;
|
||||
uint8 null_bit; /* bitmask to test for NULL */
|
||||
uint8 bit_start,bit_end; /* if bit field */
|
||||
uint16 flag;
|
||||
uint16 length; /* Keylength */
|
||||
uint32 start; /* Start of key in record */
|
||||
uint32 null_pos; /* position to NULL indicator */
|
||||
CHARSET_INFO *charset;
|
||||
} HA_KEYSEG;
|
||||
|
||||
#define get_key_length(length,key) \
|
||||
{ if ((uchar) *(key) != 255) \
|
||||
length= (uint) (uchar) *((key)++); \
|
||||
else \
|
||||
{ length=mi_uint2korr((key)+1); (key)+=3; } \
|
||||
}
|
||||
|
||||
#define get_key_pack_length(length,length_pack,key) \
|
||||
{ if ((uchar) *(key) != 255) \
|
||||
{ length= (uint) (uchar) *((key)++); length_pack=1; }\
|
||||
else \
|
||||
{ length=mi_uint2korr((key)+1); (key)+=3; length_pack=3; } \
|
||||
}
|
||||
|
||||
extern int mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
|
||||
my_bool);
|
||||
extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
||||
register uchar *b, uint key_length, uint nextflag,
|
||||
uint *diff_pos);
|
||||
|
||||
#endif /* _my_handler_h */
|
|
@ -105,13 +105,6 @@ extern int NEAR my_errno; /* Last error in mysys */
|
|||
#define MY_SEEK_CUR 1
|
||||
#define MY_SEEK_END 2
|
||||
|
||||
/* My charsets_list flags */
|
||||
#define MY_NO_SETS 0
|
||||
#define MY_COMPILED_SETS 1 /* show compiled-in sets */
|
||||
#define MY_CONFIG_SETS 2 /* sets that have a *.conf file */
|
||||
#define MY_INDEX_SETS 4 /* all sets listed in the Index file */
|
||||
#define MY_LOADED_SETS 8 /* the sets that are currently loaded */
|
||||
|
||||
/* Some constants */
|
||||
#define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */
|
||||
#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */
|
||||
|
@ -590,11 +583,7 @@ extern void allow_break(void);
|
|||
#endif
|
||||
|
||||
extern void my_remember_signal(int signal_number,sig_handler (*func)(int));
|
||||
extern void caseup(my_string str,uint length);
|
||||
extern void casedn(my_string str,uint length);
|
||||
extern void caseup_str(my_string str);
|
||||
extern void casedn_str(my_string str);
|
||||
extern void case_sort(my_string str,uint length);
|
||||
extern void case_sort(CHARSET_INFO *cs, my_string str,uint length);
|
||||
extern uint dirname_part(my_string to,const char *name);
|
||||
extern uint dirname_length(const char *name);
|
||||
#define base_name(A) (A+dirname_length(A))
|
||||
|
@ -619,18 +608,14 @@ extern my_string my_path(my_string to,const char *progname,
|
|||
extern my_string my_load_path(my_string to, const char *path,
|
||||
const char *own_path_prefix);
|
||||
extern int wild_compare(const char *str,const char *wildstr);
|
||||
extern my_string my_strcasestr(const char *src,const char *suffix);
|
||||
extern int my_strcasecmp(const char *s,const char *t);
|
||||
extern int my_strsortcmp(const char *s,const char *t);
|
||||
extern int my_casecmp(const char *s,const char *t,uint length);
|
||||
extern int my_sortcmp(const char *s,const char *t,uint length);
|
||||
extern int my_sortncmp(const char *s,uint s_len, const char *t,uint t_len);
|
||||
extern int my_sortcmp(CHARSET_INFO *cs, const char *s,const char *t,uint length);
|
||||
extern int my_sortncmp(CHARSET_INFO *cs, const char *s,uint s_len, const char *t,uint t_len);
|
||||
extern WF_PACK *wf_comp(my_string str);
|
||||
extern int wf_test(struct wild_file_pack *wf_pack,const char *name);
|
||||
extern void wf_end(struct wild_file_pack *buffer);
|
||||
extern size_s strip_sp(my_string str);
|
||||
extern void get_date(my_string to,int timeflag,time_t use_time);
|
||||
extern void soundex(my_string out_pntr, my_string in_pntr,pbool remove_garbage);
|
||||
extern void soundex(CHARSET_INFO *, my_string out_pntr, my_string in_pntr,pbool remove_garbage);
|
||||
extern int init_record_cache(RECORD_CACHE *info,uint cachesize,File file,
|
||||
uint reclength,enum cache_type type,
|
||||
pbool use_async_io);
|
||||
|
|
|
@ -20,13 +20,17 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_TREE_HIGHT 40 /* = max 1048576 leafs in tree */
|
||||
#include "my_base.h" /* get 'enum ha_rkey_function' */
|
||||
|
||||
#define MAX_TREE_HEIGHT 40 /* = max 1048576 leafs in tree */
|
||||
#define ELEMENT_KEY(tree,element)\
|
||||
(tree->offset_to_key ? (void*)((byte*) element+tree->offset_to_key) :\
|
||||
*((void**) (element+1)))
|
||||
|
||||
#define tree_set_pointer(element,ptr) *((byte **) (element+1))=((byte*) (ptr))
|
||||
|
||||
#define TREE_NO_DUPS 1
|
||||
|
||||
typedef enum { left_root_right, right_root_left } TREE_WALK;
|
||||
typedef uint32 element_count;
|
||||
typedef int (*tree_walk_action)(void *,element_count,void *);
|
||||
|
@ -48,15 +52,18 @@ typedef struct st_tree_element {
|
|||
} TREE_ELEMENT;
|
||||
#endif /* MSDOS */
|
||||
|
||||
#define ELEMENT_CHILD(element, offs) (*(TREE_ELEMENT**)((char*)element + offs))
|
||||
|
||||
typedef struct st_tree {
|
||||
TREE_ELEMENT *root,null_element;
|
||||
TREE_ELEMENT **parents[MAX_TREE_HIGHT];
|
||||
TREE_ELEMENT **parents[MAX_TREE_HEIGHT];
|
||||
uint offset_to_key,elements_in_tree,size_of_element,memory_limit,allocated;
|
||||
qsort_cmp2 compare;
|
||||
void* custom_arg;
|
||||
void *custom_arg;
|
||||
MEM_ROOT mem_root;
|
||||
my_bool with_delete;
|
||||
tree_element_free free;
|
||||
uint flag;
|
||||
} TREE;
|
||||
|
||||
/* Functions on whole tree */
|
||||
|
@ -70,12 +77,22 @@ void reset_tree(TREE*);
|
|||
#define is_tree_inited(tree) ((tree)->root != 0)
|
||||
|
||||
/* Functions on leafs */
|
||||
TREE_ELEMENT *tree_insert(TREE *tree,void *key,uint key_size);
|
||||
void *tree_search(TREE *tree,void *key);
|
||||
TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size,
|
||||
void *custom_arg);
|
||||
void *tree_search(TREE *tree, void *key, void *custom_arg);
|
||||
int tree_walk(TREE *tree,tree_walk_action action,
|
||||
void *argument, TREE_WALK visit);
|
||||
int tree_delete(TREE *tree,void *key);
|
||||
int tree_delete(TREE *tree, void *key, void *custom_arg);
|
||||
|
||||
void *tree_search_key(TREE *tree, const void *key,
|
||||
TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos,
|
||||
enum ha_rkey_function flag, void *custom_arg);
|
||||
void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents,
|
||||
TREE_ELEMENT ***last_pos, int child_offs);
|
||||
void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs,
|
||||
int r_offs);
|
||||
uint tree_record_pos(TREE *tree, const void *key,
|
||||
enum ha_rkey_function search_flag, void *custom_arg);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,7 @@ extern "C" {
|
|||
#ifndef _m_ctype_h
|
||||
#include <m_ctype.h>
|
||||
#endif
|
||||
#include "my_handler.h"
|
||||
|
||||
/* defines used by myisam-funktions */
|
||||
|
||||
|
@ -105,20 +106,6 @@ typedef struct st_mi_create_info
|
|||
struct st_myisam_info; /* For referense */
|
||||
typedef struct st_myisam_info MI_INFO;
|
||||
|
||||
typedef struct st_mi_keyseg /* Key-portion */
|
||||
{
|
||||
uint8 type; /* Type of key (for sort) */
|
||||
uint8 language;
|
||||
uint8 null_bit; /* bitmask to test for NULL */
|
||||
uint8 bit_start,bit_end; /* if bit field */
|
||||
uint16 flag;
|
||||
uint16 length; /* Keylength */
|
||||
uint32 start; /* Start of key in record */
|
||||
uint32 null_pos; /* position to NULL indicator */
|
||||
CHARSET_INFO *charset;
|
||||
} MI_KEYSEG;
|
||||
|
||||
|
||||
struct st_mi_s_param;
|
||||
|
||||
typedef struct st_mi_keydef /* Key definition with open & info */
|
||||
|
@ -135,7 +122,7 @@ typedef struct st_mi_keydef /* Key definition with open & info */
|
|||
uint16 block_size; /* block_size (auto) */
|
||||
uint32 version; /* For concurrent read/write */
|
||||
|
||||
MI_KEYSEG *seg,*end;
|
||||
HA_KEYSEG *seg,*end;
|
||||
int (*bin_search)(struct st_myisam_info *info,struct st_mi_keydef *keyinfo,
|
||||
uchar *page,uchar *key,
|
||||
uint key_len,uint comp_flag,uchar * *ret_pos,
|
||||
|
@ -147,6 +134,8 @@ typedef struct st_mi_keydef /* Key definition with open & info */
|
|||
struct st_mi_s_param *s_temp);
|
||||
void (*store_key)(struct st_mi_keydef *keyinfo, uchar *key_pos,
|
||||
struct st_mi_s_param *s_temp);
|
||||
int (*ck_insert)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen);
|
||||
int (*ck_delete)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen);
|
||||
} MI_KEYDEF;
|
||||
|
||||
|
||||
|
@ -157,7 +146,7 @@ typedef struct st_unique_def /* Segment definition of unique */
|
|||
uint16 keysegs; /* Number of key-segment */
|
||||
uchar key; /* Mapped to which key */
|
||||
uint8 null_are_equal;
|
||||
MI_KEYSEG *seg,*end;
|
||||
HA_KEYSEG *seg,*end;
|
||||
} MI_UNIQUEDEF;
|
||||
|
||||
typedef struct st_mi_decode_tree /* Decode huff-table */
|
||||
|
@ -321,6 +310,7 @@ typedef struct st_sort_key_blocks /* Used when sorting */
|
|||
int inited;
|
||||
} SORT_KEY_BLOCKS;
|
||||
|
||||
|
||||
typedef struct st_mi_check_param
|
||||
{
|
||||
ulonglong auto_increment_value;
|
||||
|
|
141
include/mysql.h
141
include/mysql.h
|
@ -68,16 +68,17 @@ extern char *mysql_unix_port;
|
|||
#define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR)
|
||||
|
||||
typedef struct st_mysql_field {
|
||||
char *name; /* Name of column */
|
||||
char *table; /* Table of column if column was a field */
|
||||
char *org_table; /* Org table name if table was an alias */
|
||||
char *db; /* Database for table */
|
||||
char *def; /* Default value (set by mysql_list_fields) */
|
||||
unsigned long length; /* Width of column */
|
||||
unsigned long max_length; /* Max width of selected set */
|
||||
unsigned int flags; /* Div flags */
|
||||
unsigned int decimals; /* Number of decimals in field */
|
||||
enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
|
||||
char *name; /* Name of column */
|
||||
char *org_name; /* Original column name, if an alias */
|
||||
char *table; /* Table of column if column was a field */
|
||||
char *org_table; /* Org table name, if table was an alias */
|
||||
char *db; /* Database for table */
|
||||
char *def; /* Default value (set by mysql_list_fields) */
|
||||
unsigned long length; /* Width of column */
|
||||
unsigned long max_length; /* Max width of selected set */
|
||||
unsigned int flags; /* Div flags */
|
||||
unsigned int decimals; /* Number of decimals in field */
|
||||
enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
|
||||
} MYSQL_FIELD;
|
||||
|
||||
typedef char **MYSQL_ROW; /* return data as array of strings */
|
||||
|
@ -156,7 +157,8 @@ enum mysql_rpl_type { MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE,
|
|||
MYSQL_RPL_ADMIN };
|
||||
|
||||
|
||||
typedef struct st_mysql {
|
||||
typedef struct st_mysql
|
||||
{
|
||||
NET net; /* Communication parameters */
|
||||
gptr connector_fd; /* ConnectorFd for SSL */
|
||||
char *host,*user,*passwd,*unix_socket,*server_version,*host_info,
|
||||
|
@ -174,6 +176,7 @@ typedef struct st_mysql {
|
|||
unsigned int field_count;
|
||||
unsigned int server_status;
|
||||
unsigned int server_language;
|
||||
unsigned int warning_count;
|
||||
struct st_mysql_options options;
|
||||
enum mysql_status status;
|
||||
my_bool free_me; /* If free in mysql_close */
|
||||
|
@ -272,12 +275,13 @@ my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql);
|
|||
my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql);
|
||||
unsigned int STDCALL mysql_errno(MYSQL *mysql);
|
||||
const char * STDCALL mysql_error(MYSQL *mysql);
|
||||
uint STDCALL mysql_warning_count(MYSQL *mysql);
|
||||
const char * STDCALL mysql_info(MYSQL *mysql);
|
||||
unsigned long STDCALL mysql_thread_id(MYSQL *mysql);
|
||||
const char * STDCALL mysql_character_set_name(MYSQL *mysql);
|
||||
|
||||
MYSQL * STDCALL mysql_init(MYSQL *mysql);
|
||||
int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
|
||||
my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
|
||||
const char *cert, const char *ca,
|
||||
const char *capath, const char *cipher);
|
||||
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
|
||||
|
@ -294,19 +298,19 @@ int STDCALL mysql_select_db(MYSQL *mysql, const char *db);
|
|||
int STDCALL mysql_query(MYSQL *mysql, const char *q);
|
||||
int STDCALL mysql_send_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
int STDCALL mysql_read_query_result(MYSQL *mysql);
|
||||
my_bool STDCALL mysql_read_query_result(MYSQL *mysql);
|
||||
int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
/* perform query on master */
|
||||
int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
/* perform query on slave */
|
||||
int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
|
||||
/*
|
||||
enable/disable parsing of all queries to decide if they go on master or
|
||||
|
@ -321,12 +325,12 @@ int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql);
|
|||
void STDCALL mysql_enable_reads_from_master(MYSQL* mysql);
|
||||
void STDCALL mysql_disable_reads_from_master(MYSQL* mysql);
|
||||
/* get the value of the master read flag */
|
||||
int STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
|
||||
my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
|
||||
|
||||
enum mysql_rpl_type STDCALL mysql_rpl_query_type(const char* q, int len);
|
||||
|
||||
/* discover the master and its slaves */
|
||||
int STDCALL mysql_rpl_probe(MYSQL* mysql);
|
||||
my_bool STDCALL mysql_rpl_probe(MYSQL* mysql);
|
||||
|
||||
/* set the master, close/free the old one, if it is not a pivot */
|
||||
int STDCALL mysql_set_master(MYSQL* mysql, const char* host,
|
||||
|
@ -356,6 +360,7 @@ MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table,
|
|||
MYSQL_RES * STDCALL mysql_list_processes(MYSQL *mysql);
|
||||
MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql);
|
||||
MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql);
|
||||
MYSQL_RES * STDCALL mysql_warnings(MYSQL *mysql);
|
||||
int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option,
|
||||
const char *arg);
|
||||
void STDCALL mysql_free_result(MYSQL_RES *result);
|
||||
|
@ -398,6 +403,91 @@ int STDCALL mysql_manager_command(MYSQL_MANAGER* con,
|
|||
int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con,
|
||||
char* res_buf,
|
||||
int res_buf_size);
|
||||
|
||||
|
||||
/*
|
||||
The following definitions are added for the enhanced
|
||||
client-server protocol
|
||||
*/
|
||||
|
||||
/* statement state */
|
||||
enum MY_STMT_STATE { MY_ST_UNKNOWN, MY_ST_PREPARE, MY_ST_EXECUTE };
|
||||
|
||||
/* bind structure */
|
||||
typedef struct st_mysql_bind
|
||||
{
|
||||
long *length; /* output length pointer */
|
||||
gptr buffer; /* buffer */
|
||||
unsigned long buffer_length; /* buffer length */
|
||||
enum enum_field_types buffer_type; /* buffer type */
|
||||
enum enum_field_types field_type; /* field type */
|
||||
my_bool is_null; /* NULL indicator */
|
||||
my_bool is_long_data; /* long data indicator */
|
||||
|
||||
/* The following are for internal use. Set by mysql_bind_param */
|
||||
long bind_length; /* Default length of data */
|
||||
my_bool long_ended; /* All data supplied for long */
|
||||
uint param_number; /* For null count and error messages */
|
||||
void (*store_param_func)(NET *net, struct st_mysql_bind *param);
|
||||
char *(*fetch_result)(struct st_mysql_bind *, const char *row);
|
||||
} MYSQL_BIND;
|
||||
|
||||
|
||||
/* statement handler */
|
||||
typedef struct st_mysql_stmt
|
||||
{
|
||||
MYSQL *mysql; /* connection handle */
|
||||
MYSQL_BIND *params; /* input parameters */
|
||||
MYSQL_RES *result; /* resultset */
|
||||
MYSQL_BIND *bind; /* row binding */
|
||||
MYSQL_FIELD *fields; /* prepare meta info */
|
||||
char *query; /* query buffer */
|
||||
MEM_ROOT mem_root; /* root allocations */
|
||||
MYSQL_RES tmp_result; /* Used by mysql_prepare_result */
|
||||
unsigned long param_count; /* parameters count */
|
||||
unsigned long field_count; /* fields count */
|
||||
unsigned long long_length; /* long buffer alloced length */
|
||||
ulong stmt_id; /* Id for prepared statement */
|
||||
uint last_errno; /* error code */
|
||||
enum MY_STMT_STATE state; /* statement state */
|
||||
char last_error[MYSQL_ERRMSG_SIZE]; /* error message */
|
||||
my_bool long_alloced; /* flag to indicate long alloced */
|
||||
my_bool types_supplied; /* to indicate types supply */
|
||||
} MYSQL_STMT;
|
||||
|
||||
|
||||
MYSQL_STMT * STDCALL mysql_prepare(MYSQL * mysql, const char *query,
|
||||
unsigned long length);
|
||||
int STDCALL mysql_execute(MYSQL_STMT * stmt);
|
||||
unsigned long STDCALL mysql_param_count(MYSQL_STMT * stmt);
|
||||
my_bool STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bind);
|
||||
my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bind);
|
||||
my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt);
|
||||
uint STDCALL mysql_stmt_errno(MYSQL_STMT * stmt);
|
||||
const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt);
|
||||
my_bool STDCALL mysql_commit(MYSQL * mysql);
|
||||
my_bool STDCALL mysql_rollback(MYSQL * mysql);
|
||||
my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
|
||||
int STDCALL mysql_fetch(MYSQL_STMT *stmt);
|
||||
my_bool STDCALL mysql_send_long_data(MYSQL_STMT *stmt,
|
||||
uint param_number,
|
||||
const char *data,
|
||||
unsigned long length,
|
||||
my_bool last_data);
|
||||
int STDCALL mysql_multi_query(MYSQL *mysql,const char *query,
|
||||
unsigned long len);
|
||||
MYSQL_RES *STDCALL mysql_next_result(MYSQL *mysql);
|
||||
MYSQL_RES *STDCALL mysql_prepare_result(MYSQL_STMT *stmt);
|
||||
|
||||
|
||||
/* new status messages */
|
||||
#define MYSQL_SUCCESS 0
|
||||
#define MYSQL_WARNING 1
|
||||
#define MYSQL_STATUS_ERROR 2
|
||||
#define MYSQL_NO_DATA 100
|
||||
#define MYSQL_NEED_DATA 99
|
||||
#define MYSQL_LONG_DATA_END 0xFF
|
||||
|
||||
#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
|
||||
|
||||
#ifdef USE_OLD_FUNCTIONS
|
||||
|
@ -414,8 +504,9 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
|
|||
They are not for general usage
|
||||
*/
|
||||
|
||||
int simple_command(MYSQL *mysql,enum enum_server_command command,
|
||||
const char *arg, unsigned long length, my_bool skipp_check);
|
||||
my_bool
|
||||
simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
ulong length, my_bool skip_check);
|
||||
unsigned long net_safe_read(MYSQL* mysql);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -34,14 +34,15 @@
|
|||
#define MYSQL_SERVICENAME "MySql"
|
||||
#endif /* __WIN__ */
|
||||
|
||||
enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
|
||||
COM_FIELD_LIST,COM_CREATE_DB,COM_DROP_DB,COM_REFRESH,
|
||||
COM_SHUTDOWN,COM_STATISTICS,
|
||||
COM_PROCESS_INFO,COM_CONNECT,COM_PROCESS_KILL,
|
||||
COM_DEBUG,COM_PING,COM_TIME,COM_DELAYED_INSERT,
|
||||
COM_CHANGE_USER, COM_BINLOG_DUMP,
|
||||
COM_TABLE_DUMP, COM_CONNECT_OUT,
|
||||
COM_REGISTER_SLAVE};
|
||||
enum enum_server_command
|
||||
{
|
||||
COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST,
|
||||
COM_CREATE_DB, COM_DROP_DB, COM_REFRESH, COM_SHUTDOWN, COM_STATISTICS,
|
||||
COM_PROCESS_INFO, COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING,
|
||||
COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
|
||||
COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
|
||||
COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT
|
||||
};
|
||||
|
||||
#define NOT_NULL_FLAG 1 /* Field can't be NULL */
|
||||
#define PRI_KEY_FLAG 2 /* Field is part of a primary key */
|
||||
|
@ -95,9 +96,11 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
|
|||
#define CLIENT_SSL 2048 /* Switch to SSL after handshake */
|
||||
#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
|
||||
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
|
||||
#define CLIENT_PROTOCOL_41 16384 /* New 4.1 protocol */
|
||||
|
||||
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
|
||||
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
|
||||
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
|
||||
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
|
||||
#define SERVER_STATUS_MORE_RESULTS 4 /* More results on server */
|
||||
|
||||
#define MYSQL_ERRMSG_SIZE 200
|
||||
#define NET_READ_TIMEOUT 30 /* Timeout on read */
|
||||
|
@ -136,27 +139,64 @@ typedef struct st_net {
|
|||
|
||||
#define packet_error (~(unsigned long) 0)
|
||||
|
||||
enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
|
||||
FIELD_TYPE_SHORT, FIELD_TYPE_LONG,
|
||||
FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE,
|
||||
FIELD_TYPE_NULL, FIELD_TYPE_TIMESTAMP,
|
||||
FIELD_TYPE_LONGLONG,FIELD_TYPE_INT24,
|
||||
FIELD_TYPE_DATE, FIELD_TYPE_TIME,
|
||||
FIELD_TYPE_DATETIME, FIELD_TYPE_YEAR,
|
||||
FIELD_TYPE_NEWDATE,
|
||||
FIELD_TYPE_ENUM=247,
|
||||
FIELD_TYPE_SET=248,
|
||||
FIELD_TYPE_TINY_BLOB=249,
|
||||
FIELD_TYPE_MEDIUM_BLOB=250,
|
||||
FIELD_TYPE_LONG_BLOB=251,
|
||||
FIELD_TYPE_BLOB=252,
|
||||
FIELD_TYPE_VAR_STRING=253,
|
||||
FIELD_TYPE_STRING=254,
|
||||
FIELD_TYPE_GEOMETRY=255
|
||||
enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
|
||||
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
|
||||
MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
|
||||
MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP,
|
||||
MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
|
||||
MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
|
||||
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
|
||||
MYSQL_TYPE_NEWDATE,
|
||||
MYSQL_TYPE_ENUM=247,
|
||||
MYSQL_TYPE_SET=248,
|
||||
MYSQL_TYPE_TINY_BLOB=249,
|
||||
MYSQL_TYPE_MEDIUM_BLOB=250,
|
||||
MYSQL_TYPE_LONG_BLOB=251,
|
||||
MYSQL_TYPE_BLOB=252,
|
||||
MYSQL_TYPE_VAR_STRING=253,
|
||||
MYSQL_TYPE_STRING=254,
|
||||
MYSQL_TYPE_GEOMETRY=255
|
||||
|
||||
};
|
||||
|
||||
#define FIELD_TYPE_CHAR FIELD_TYPE_TINY /* For compability */
|
||||
#define FIELD_TYPE_INTERVAL FIELD_TYPE_ENUM /* For compability */
|
||||
/* For backward compatibility */
|
||||
#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL
|
||||
#define FIELD_TYPE_TINY MYSQL_TYPE_TINY
|
||||
#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT
|
||||
#define FIELD_TYPE_LONG MYSQL_TYPE_LONG
|
||||
#define FIELD_TYPE_FLOAT MYSQL_TYPE_FLOAT
|
||||
#define FIELD_TYPE_DOUBLE MYSQL_TYPE_DOUBLE
|
||||
#define FIELD_TYPE_NULL MYSQL_TYPE_NULL
|
||||
#define FIELD_TYPE_TIMESTAMP MYSQL_TYPE_TIMESTAMP
|
||||
#define FIELD_TYPE_LONGLONG MYSQL_TYPE_LONGLONG
|
||||
#define FIELD_TYPE_INT24 MYSQL_TYPE_INT24
|
||||
#define FIELD_TYPE_DATE MYSQL_TYPE_DATE
|
||||
#define FIELD_TYPE_TIME MYSQL_TYPE_TIME
|
||||
#define FIELD_TYPE_DATETIME MYSQL_TYPE_DATETIME
|
||||
#define FIELD_TYPE_YEAR MYSQL_TYPE_YEAR
|
||||
#define FIELD_TYPE_NEWDATE MYSQL_TYPE_NEWDATE
|
||||
#define FIELD_TYPE_ENUM MYSQL_TYPE_ENUM
|
||||
#define FIELD_TYPE_SET MYSQL_TYPE_SET
|
||||
#define FIELD_TYPE_TINY_BLOB MYSQL_TYPE_TINY_BLOB
|
||||
#define FIELD_TYPE_MEDIUM_BLOB MYSQL_TYPE_MEDIUM_BLOB
|
||||
#define FIELD_TYPE_LONG_BLOB MYSQL_TYPE_LONG_BLOB
|
||||
#define FIELD_TYPE_BLOB MYSQL_TYPE_BLOB
|
||||
#define FIELD_TYPE_VAR_STRING MYSQL_TYPE_VAR_STRING
|
||||
#define FIELD_TYPE_STRING MYSQL_TYPE_STRING
|
||||
#define FIELD_TYPE_CHAR MYSQL_TYPE_TINY
|
||||
#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM
|
||||
#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY
|
||||
|
||||
#if TO_BE_INCLUDED_LATER
|
||||
/* For bind applications, to indicate unsigned buffers */
|
||||
#define MYSQL_TYPE_UTINY -10
|
||||
#define MYSQL_TYPE_USHORT -9
|
||||
#define MYSQL_TYPE_ULONG -8
|
||||
#define MYSQL_TYPE_UFLOAT -7
|
||||
#define MYSQL_TYPE_UDOUBLE -6
|
||||
#define MYSQL_TYPE_ULONGLONG -5
|
||||
#define MYSQL_TYPE_UINT24 -4
|
||||
#endif
|
||||
|
||||
#define net_new_transaction(net) ((net)->pkt_nr=0)
|
||||
|
||||
|
@ -164,21 +204,26 @@ enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
int my_net_init(NET *net, Vio* vio);
|
||||
my_bool my_net_init(NET *net, Vio* vio);
|
||||
void my_net_local_init(NET *net);
|
||||
void net_end(NET *net);
|
||||
void net_clear(NET *net);
|
||||
int net_flush(NET *net);
|
||||
int my_net_write(NET *net,const char *packet,unsigned long len);
|
||||
int net_write_command(NET *net,unsigned char command,const char *packet,
|
||||
unsigned long len);
|
||||
my_bool net_realloc(NET *net, unsigned long length);
|
||||
my_bool net_flush(NET *net);
|
||||
my_bool my_net_write(NET *net,const char *packet,unsigned long len);
|
||||
my_bool net_write_command(NET *net,unsigned char command,
|
||||
const char *header, unsigned long head_len,
|
||||
const char *packet, unsigned long len);
|
||||
int net_real_write(NET *net,const char *packet,unsigned long len);
|
||||
unsigned long my_net_read(NET *net);
|
||||
|
||||
/* The following function is not meant for normal usage */
|
||||
/*
|
||||
The following function is not meant for normal usage
|
||||
Currently it's used internally by manager.c
|
||||
*/
|
||||
struct sockaddr;
|
||||
int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen,
|
||||
unsigned int timeout);
|
||||
my_bool my_connect(my_socket s, const struct sockaddr *name,
|
||||
unsigned int namelen, unsigned int timeout);
|
||||
|
||||
struct rand_struct {
|
||||
unsigned long seed1,seed2,max_value;
|
||||
|
@ -252,5 +297,6 @@ void my_thread_end(void);
|
|||
#endif
|
||||
|
||||
#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */
|
||||
#define MYSQL_LONG_DATA_HEADER 8
|
||||
|
||||
#endif
|
||||
|
|
|
@ -253,4 +253,9 @@
|
|||
#define ER_CANT_USE_OPTION_HERE 1234
|
||||
#define ER_NOT_SUPPORTED_YET 1235
|
||||
#define ER_MASTER_FATAL_ERROR_READING_BINLOG 1236
|
||||
#define ER_ERROR_MESSAGES 237
|
||||
#define ER_WRONG_FK_DEF 1237
|
||||
#define ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1238
|
||||
#define ER_SUBSELECT_NO_1_COL 1239
|
||||
#define ER_SUBSELECT_NO_1_ROW 1240
|
||||
#define ER_UNKNOWN_STMT_HANDLER 1241
|
||||
#define ER_ERROR_MESSAGES 242
|
||||
|
|
|
@ -58,7 +58,7 @@ uint _nisam_make_key(register N_INFO *info, uint keynr, uchar *key, const char *
|
|||
#endif
|
||||
{
|
||||
if (type == HA_KEYTYPE_TEXT)
|
||||
case_sort((byte*) key,length);
|
||||
case_sort(default_charset_info,(byte*) key,length);
|
||||
}
|
||||
key+=length;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ uint _nisam_make_key(register N_INFO *info, uint keynr, uchar *key, const char *
|
|||
#endif
|
||||
{
|
||||
if (type == HA_KEYTYPE_TEXT)
|
||||
case_sort((byte*) key,(uint) keyseg->base.length);
|
||||
case_sort(default_charset_info,(byte*) key,(uint) keyseg->base.length);
|
||||
}
|
||||
#ifdef NAN_TEST
|
||||
else if (type == HA_KEYTYPE_FLOAT)
|
||||
|
@ -154,7 +154,7 @@ uint _nisam_pack_key(register N_INFO *info, uint keynr, uchar *key, uchar *old,
|
|||
#endif
|
||||
{
|
||||
if (type == HA_KEYTYPE_TEXT)
|
||||
case_sort((byte*) key,length);
|
||||
case_sort(default_charset_info,(byte*) key,length);
|
||||
}
|
||||
key+= length;
|
||||
}
|
||||
|
|
|
@ -515,11 +515,13 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
|
|||
if (*a++ != *b++)
|
||||
{
|
||||
a--; b--;
|
||||
if (isdigit((char) *a) && isdigit((char) *b))
|
||||
if (my_isdigit(default_charset_info, (char) *a) &&
|
||||
my_isdigit(default_charset_info, (char) *b))
|
||||
return ((int) *a - (int) *b);
|
||||
if (*a == '-' || isdigit((char) *b))
|
||||
if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
|
||||
return (-1);
|
||||
if (*b == '-' || *b++ == ' ' || isdigit((char) *a))
|
||||
if (*b == '-' || *b++ == ' ' ||
|
||||
my_isdigit(default_charset_info,(char) *a))
|
||||
return (1);
|
||||
if (*a++ == ' ')
|
||||
return (-1);
|
||||
|
@ -539,11 +541,13 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
|
|||
if (*a++ != *b++)
|
||||
{
|
||||
a--; b--;
|
||||
if (isdigit((char) *a) && isdigit((char) *b))
|
||||
if (my_isdigit(default_charset_info,(char) *a) &&
|
||||
my_isdigit(default_charset_info,(char) *b))
|
||||
return ((int) *a - (int) *b);
|
||||
if (*a == '-' || isdigit((char) *b))
|
||||
if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
|
||||
return (-1);
|
||||
if (*b == '-' || *b++ == ' ' || isdigit((char) *a))
|
||||
if (*b == '-' || *b++ == ' ' ||
|
||||
my_isdigit(default_charset_info,(char) *a))
|
||||
return (1);
|
||||
if (*a++ == ' ')
|
||||
return -1;
|
||||
|
|
|
@ -342,7 +342,7 @@ static int examine_log(my_string file_name, char **table_names)
|
|||
file_info.process=0;
|
||||
result=uint2korr(head+7);
|
||||
if ((curr_file_info=(struct isamlog_file_info*)
|
||||
tree_search(&tree,&file_info)))
|
||||
tree_search(&tree, &file_info, tree.custom_arg)))
|
||||
{
|
||||
curr_file_info->accessed=access_time;
|
||||
if (update && curr_file_info->used && curr_file_info->closed)
|
||||
|
@ -444,7 +444,7 @@ static int examine_log(my_string file_name, char **table_names)
|
|||
files_open++;
|
||||
file_info.closed=0;
|
||||
}
|
||||
VOID(tree_insert(&tree,(gptr) &file_info,0));
|
||||
VOID(tree_insert(&tree, (gptr) &file_info, 0, tree.custom_arg));
|
||||
if (file_info.used)
|
||||
{
|
||||
if (verbose && !record_pos_file)
|
||||
|
@ -463,7 +463,7 @@ static int examine_log(my_string file_name, char **table_names)
|
|||
{
|
||||
if (!curr_file_info->closed)
|
||||
files_open--;
|
||||
VOID(tree_delete(&tree,(gptr) curr_file_info));
|
||||
VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
|
||||
}
|
||||
break;
|
||||
case LOG_EXTRA:
|
||||
|
|
|
@ -687,7 +687,8 @@ static HUFF_COUNTS *init_huff_count(N_INFO *info,my_off_t records)
|
|||
(type == FIELD_NORMAL ||
|
||||
type == FIELD_SKIP_ZERO))
|
||||
count[i].max_zero_fill= count[i].field_length;
|
||||
init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,NULL,NULL);
|
||||
init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,
|
||||
NULL, NULL);
|
||||
if (records)
|
||||
count[i].tree_pos=count[i].tree_buff =
|
||||
my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
|
||||
|
@ -765,7 +766,8 @@ static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
|
|||
if (count->tree_buff)
|
||||
{
|
||||
global_count=count;
|
||||
if (!(element=tree_insert(&count->int_tree,pos,0)) ||
|
||||
if (!(element=tree_insert(&count->int_tree, pos, 0,
|
||||
count->int_tree.custom_arg)) ||
|
||||
((element->count == 1 &&
|
||||
count->tree_buff + tree_buff_length <
|
||||
count->tree_pos + count->field_length) ||
|
||||
|
@ -1736,7 +1738,8 @@ static int compress_isam_file(MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
|
|||
break;
|
||||
case FIELD_INTERVALL:
|
||||
global_count=count;
|
||||
pos=(byte*) tree_search(&count->int_tree,start_pos);
|
||||
pos=(byte*) tree_search(&count->int_tree, start_pos,
|
||||
count->int_tree.custom_arg);
|
||||
intervall=(uint) (pos - count->tree_buff)/field_length;
|
||||
write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
|
||||
start_pos=end_pos;
|
||||
|
|
|
@ -49,10 +49,6 @@ link_sources:
|
|||
rm -f $(srcdir)/$$f; \
|
||||
@LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \
|
||||
done; \
|
||||
for f in $(mystringsgen); do \
|
||||
rm -f $(srcdir)/$$f; \
|
||||
@LN_CP_F@ ../strings/$$f $(srcdir)/$$f; \
|
||||
done; \
|
||||
for f in $$qs; do \
|
||||
rm -f $(srcdir)/$$f; \
|
||||
@LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \
|
||||
|
|
|
@ -27,9 +27,6 @@ pkglib_LTLIBRARIES = $(target)
|
|||
|
||||
noinst_PROGRAMS = conf_to_src
|
||||
|
||||
# We need .lo, not .o files for everything.
|
||||
CHARSET_OBJS=@CHARSET_OBJS@
|
||||
LTCHARSET_OBJS= ${CHARSET_OBJS:.o=.lo}
|
||||
|
||||
target_sources = libmysql.c password.c manager.c \
|
||||
get_password.c errmsg.c
|
||||
|
@ -41,9 +38,13 @@ mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \
|
|||
strcend.lo bcmp.lo \
|
||||
bchange.lo bmove.lo bmove_upp.lo longlong2str.lo \
|
||||
strtoull.lo strtoll.lo llstr.lo \
|
||||
ctype.lo $(LTCHARSET_OBJS)
|
||||
ctype.lo ctype-simple.lo ctype-mb.lo \
|
||||
ctype-big5.lo ctype-czech.lo ctype-euc_kr.lo \
|
||||
ctype-win1250ch.lo ctype-utf8.lo \
|
||||
ctype-gb2312.lo ctype-gbk.lo ctype-latin1_de.lo \
|
||||
ctype-sjis.lo ctype-tis620.lo ctype-ujis.lo
|
||||
|
||||
mystringsextra= strto.c
|
||||
mystringsgen= ctype_autoconf.c
|
||||
dbugobjects = dbug.lo # IT IS IN SAFEMALLOC.C sanity.lo
|
||||
mysysheaders = mysys_priv.h my_static.h
|
||||
mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
|
||||
|
@ -77,19 +78,15 @@ DEFS = -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
|
|||
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" $(target_defs)
|
||||
|
||||
# The automatic dependencies miss this
|
||||
bmove_upp.lo: $(LTCHARSET_OBJS)
|
||||
ctype.lo: ctype_extra_sources.c
|
||||
#bmove_upp.lo: $(LTCHARSET_OBJS)
|
||||
|
||||
clean-local:
|
||||
rm -f `echo $(mystringsobjects) | sed "s;\.lo;.c;g"` \
|
||||
`echo $(dbugobjects) | sed "s;\.lo;.c;g"` \
|
||||
`echo $(mysysobjects) | sed "s;\.lo;.c;g"` \
|
||||
$(mystringsextra) $(mystringsgen) $(mysysheaders) \
|
||||
ctype_extra_sources.c net.c ../linked_client_sources
|
||||
$(mystringsextra) $(mysysheaders) \
|
||||
../linked_client_sources net.c
|
||||
|
||||
ctype_extra_sources.c: conf_to_src
|
||||
./conf_to_src $(top_srcdir) @CHARSETS_NEED_SOURCE@ > \
|
||||
$(srcdir)/ctype_extra_sources.c
|
||||
conf_to_src_SOURCES = conf_to_src.c
|
||||
conf_to_src_LDADD=
|
||||
#force static linking of conf_to_src - essential when linking against
|
||||
|
|
|
@ -49,7 +49,16 @@ const char *client_errors[]=
|
|||
"Error on SHOW SLAVE STATUS:",
|
||||
"Error on SHOW SLAVE HOSTS:",
|
||||
"Error connecting to slave:",
|
||||
"Error connecting to master:"
|
||||
"Error connecting to master:",
|
||||
"Invalid connection handle",
|
||||
"Invalid use of null pointer",
|
||||
"Statement not prepared",
|
||||
"Not all parameters data supplied",
|
||||
"Data truncated",
|
||||
"No parameters exists in the statement",
|
||||
"Invalid parameter number",
|
||||
"Can't send long data for non string or binary data types (parameter: %d)",
|
||||
"Using not supported parameter type: %d (parameter: %d)"
|
||||
};
|
||||
|
||||
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
|
||||
|
@ -82,7 +91,16 @@ const char *client_errors[]=
|
|||
"Error on SHOW SLAVE STATUS:",
|
||||
"Error on SHOW SLAVE HOSTS:",
|
||||
"Error connecting to slave:",
|
||||
"Error connecting to master:"
|
||||
"Error connecting to master:",
|
||||
"Invalid connection handle",
|
||||
"Invalid use of null pointer",
|
||||
"Statement not prepared",
|
||||
"Not all parameters data supplied",
|
||||
"Data truncated",
|
||||
"No parameters exists in the statement",
|
||||
"Invalid parameter number",
|
||||
"Can't send long data for non string or binary data types (parameter: %d)",
|
||||
"Using not supported parameter type: %d (parameter: %d)"
|
||||
};
|
||||
|
||||
#else /* ENGLISH */
|
||||
|
@ -113,7 +131,16 @@ const char *client_errors[]=
|
|||
"Error on SHOW SLAVE STATUS:",
|
||||
"Error on SHOW SLAVE HOSTS:",
|
||||
"Error connecting to slave:",
|
||||
"Error connecting to master:"
|
||||
"Error connecting to master:",
|
||||
"Invalid connection handle",
|
||||
"Invalid use of null pointer",
|
||||
"Statement not prepared",
|
||||
"Not all parameters data supplied",
|
||||
"Data truncated",
|
||||
"No parameters exists in the statement",
|
||||
"Invalid parameter number",
|
||||
"Can't send long data for non string or binary data types (parameter: %d)",
|
||||
"Using not supported parameter type: %d (parameter: %d)"
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
1213
libmysql/libmysql.c
1213
libmysql/libmysql.c
File diff suppressed because it is too large
Load diff
|
@ -101,8 +101,8 @@ EXPORTS
|
|||
mysql_rpl_probe
|
||||
mysql_set_master
|
||||
mysql_add_slave
|
||||
|
||||
|
||||
mysql_warning_count
|
||||
mysql_warnings
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
|
|||
}
|
||||
sock_addr.sin_port = (ushort) htons((ushort) port);
|
||||
if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr),
|
||||
0) <0)
|
||||
0))
|
||||
{
|
||||
con->last_errno=errno;
|
||||
sprintf(con->last_error ,"Could not connect to %-.64s", host);
|
||||
|
|
|
@ -43,17 +43,20 @@ sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \
|
|||
hostname.cc init.cc \
|
||||
item.cc item_buff.cc item_cmpfunc.cc item_create.cc \
|
||||
item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \
|
||||
item_uniq.cc key.cc lock.cc log.cc log_event.cc mf_iocache.cc\
|
||||
item_uniq.cc item_subselect.cc \
|
||||
key.cc lock.cc log.cc log_event.cc mf_iocache.cc\
|
||||
mini_client.cc net_pkg.cc net_serv.cc opt_ft.cc opt_range.cc \
|
||||
opt_sum.cc procedure.cc records.cc sql_acl.cc \
|
||||
repl_failsafe.cc slave.cc sql_load.cc sql_olap.cc \
|
||||
sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
|
||||
sql_crypt.cc sql_db.cc sql_delete.cc sql_insert.cc sql_lex.cc \
|
||||
sql_list.cc sql_manager.cc sql_map.cc set_var.cc sql_parse.cc \
|
||||
sql_rename.cc sql_repl.cc sql_select.cc sql_do.cc sql_show.cc \
|
||||
sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
|
||||
sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc \
|
||||
sql_prepare.cc sql_derived.cc sql_rename.cc sql_repl.cc \
|
||||
sql_select.cc sql_do.cc sql_show.cc set_var.cc \
|
||||
sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \
|
||||
sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \
|
||||
unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc
|
||||
unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc \
|
||||
spatial.cc gstream.cc
|
||||
|
||||
EXTRA_DIST = lib_vio.c
|
||||
|
||||
|
|
|
@ -154,14 +154,12 @@ check_connections1(THD *thd)
|
|||
end+=SCRAMBLE_LENGTH +1;
|
||||
int2store(end,client_flags);
|
||||
end[2]=MY_CHARSET_CURRENT;
|
||||
|
||||
#define MIN_HANDSHAKE_SIZE 6
|
||||
|
||||
int2store(end+3,thd->server_status);
|
||||
bzero(end+5,13);
|
||||
end+=18;
|
||||
if (net_write_command(net,protocol_version, buff,
|
||||
(uint) (end-buff)))
|
||||
if (net_write_command(net,protocol_version,
|
||||
NullS, 0,
|
||||
buff, (uint) (end-buff)))
|
||||
{
|
||||
inc_host_errors(&thd->remote.sin_addr);
|
||||
return(ER_HANDSHAKE_ERROR);
|
||||
|
@ -169,6 +167,8 @@ check_connections1(THD *thd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define MIN_HANDSHAKE_SIZE 6
|
||||
|
||||
static int
|
||||
check_connections2(THD * thd)
|
||||
{
|
||||
|
@ -214,13 +214,12 @@ check_connections2(THD * thd)
|
|||
static bool check_user(THD *thd,enum_server_command command, const char *user,
|
||||
const char *passwd, const char *db, bool check_count)
|
||||
{
|
||||
NET *net= &thd->net;
|
||||
USER_RESOURCES ur;
|
||||
thd->db=0;
|
||||
|
||||
if (!(thd->user = my_strdup(user, MYF(0))))
|
||||
{
|
||||
send_error(net,ER_OUT_OF_RESOURCES);
|
||||
send_error(thd,ER_OUT_OF_RESOURCES);
|
||||
return 1;
|
||||
}
|
||||
thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
|
||||
|
@ -236,7 +235,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
|
|||
thd->master_access, thd->db ? thd->db : "*none*"));
|
||||
if (thd->master_access & NO_ACCESS)
|
||||
{
|
||||
net_printf(net, ER_ACCESS_DENIED_ERROR,
|
||||
net_printf(thd, ER_ACCESS_DENIED_ERROR,
|
||||
thd->user,
|
||||
thd->host_or_ip,
|
||||
passwd[0] ? ER(ER_YES) : ER(ER_NO));
|
||||
|
@ -254,7 +253,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
|
|||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||
if (tmp)
|
||||
{ // Too many connections
|
||||
send_error(net, ER_CON_COUNT_ERROR);
|
||||
send_error(thd, ER_CON_COUNT_ERROR);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +268,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
|
|||
if (db && db[0])
|
||||
return test(mysql_change_db(thd,db));
|
||||
else
|
||||
send_ok(net); // Ready to handle questions
|
||||
send_ok(thd); // Ready to handle questions
|
||||
return 0; // ok
|
||||
}
|
||||
|
||||
|
@ -370,7 +369,6 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
|
|||
|
||||
(void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
|
||||
(void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
|
||||
(void) pthread_mutex_init(&LOCK_grant,MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_open,MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW);
|
||||
|
@ -388,6 +386,7 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
|
|||
(void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
|
||||
(void) my_rwlock_init(&LOCK_grant, NULL);
|
||||
(void) pthread_cond_init(&COND_thread_count,NULL);
|
||||
(void) pthread_cond_init(&COND_refresh,NULL);
|
||||
(void) pthread_cond_init(&COND_thread_cache,NULL);
|
||||
|
@ -400,7 +399,7 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
|
|||
mysql_server_end();
|
||||
return 1;
|
||||
}
|
||||
charsets_list = list_charsets(MYF(MY_COMPILED_SETS|MY_CONFIG_SETS));
|
||||
charsets_list = list_charsets(MYF(MY_CS_COMPILED|MY_CS_CONFIG));
|
||||
|
||||
/* Parameter for threads created for connections */
|
||||
(void) pthread_attr_init(&connection_attrib);
|
||||
|
@ -499,7 +498,7 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
|
|||
After this we can't quit by a simple unireg_abort
|
||||
*/
|
||||
error_handler_hook = my_message_sql;
|
||||
if (pthread_key_create(&THR_THD,NULL) || pthread_key_create(&THR_NET,NULL) ||
|
||||
if (pthread_key_create(&THR_THD,NULL) ||
|
||||
pthread_key_create(&THR_MALLOC,NULL))
|
||||
{
|
||||
sql_print_error("Can't create thread-keys");
|
||||
|
|
|
@ -50,7 +50,7 @@ static my_bool mysql_client_init=0;
|
|||
uint mysql_port=0;
|
||||
my_string mysql_unix_port=0;
|
||||
|
||||
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS)
|
||||
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | CLIENT_PROTOCOL_41)
|
||||
|
||||
#if defined(MSDOS) || defined(__WIN__)
|
||||
#define ERRNO WSAGetLastError()
|
||||
|
@ -212,12 +212,12 @@ static void free_rows(MYSQL_DATA *cur)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
my_bool
|
||||
simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
ulong length, my_bool skipp_check)
|
||||
{
|
||||
NET *net= &mysql->net;
|
||||
int result= -1;
|
||||
my_bool result= 1;
|
||||
|
||||
/* Check that we are calling the client functions in right order */
|
||||
if (mysql->status != MYSQL_STATUS_READY)
|
||||
|
@ -239,7 +239,7 @@ simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
|||
result = lib_dispatch_command(command, net, arg,length);
|
||||
if (!skipp_check)
|
||||
result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ?
|
||||
-1 : 0);
|
||||
1 : 0);
|
||||
end:
|
||||
return result;
|
||||
}
|
||||
|
@ -412,7 +412,7 @@ mysql_free_result(MYSQL_RES *result)
|
|||
uint pkt_len;
|
||||
if ((pkt_len=(uint) net_safe_read(result->handle)) == packet_error)
|
||||
break;
|
||||
if (pkt_len == 1 && result->handle->net.read_pos[0] == 254)
|
||||
if (pkt_len <= 8 && result->handle->net.read_pos[0] == 254)
|
||||
break; /* End of data */
|
||||
}
|
||||
result->handle->status=MYSQL_STATUS_READY;
|
||||
|
@ -632,7 +632,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
|||
result->rows=0;
|
||||
result->fields=fields;
|
||||
|
||||
while (*(cp=net->read_pos) != 254 || pkt_len != 1)
|
||||
while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
|
||||
{
|
||||
result->rows++;
|
||||
if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
|
||||
|
@ -676,6 +676,8 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
|||
}
|
||||
}
|
||||
*prev_ptr=0; /* last pointer is null */
|
||||
mysql->warning_count= uint2korr(cp+1);
|
||||
DBUG_PRINT("info",("warning_count: %ld", mysql->warning_count));
|
||||
DBUG_PRINT("exit",("Got %d rows",result->rows));
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
@ -696,8 +698,11 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
|
|||
|
||||
if ((pkt_len=net_safe_read(mysql)) == packet_error)
|
||||
return -1;
|
||||
if (pkt_len == 1 && mysql->net.read_pos[0] == 254)
|
||||
if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
|
||||
{
|
||||
mysql->warning_count= uint2korr(mysql->net.read_pos+1);
|
||||
return 1; /* End of data */
|
||||
}
|
||||
prev_pos= 0; /* allowed to write at packet[-1] */
|
||||
pos=mysql->net.read_pos;
|
||||
for (field=0 ; field < fields ; field++)
|
||||
|
@ -1124,7 +1129,7 @@ mysql_send_query(MYSQL* mysql, const char* query, ulong length)
|
|||
}
|
||||
|
||||
|
||||
int STDCALL
|
||||
my_bool STDCALL
|
||||
mysql_read_query_result(MYSQL *mysql)
|
||||
{
|
||||
uchar *pos;
|
||||
|
@ -1134,7 +1139,7 @@ mysql_read_query_result(MYSQL *mysql)
|
|||
DBUG_ENTER("mysql_read_query_result");
|
||||
|
||||
if ((length=net_safe_read(mysql)) == packet_error)
|
||||
DBUG_RETURN(-1);
|
||||
DBUG_RETURN(1);
|
||||
free_old_query(mysql); /* Free old result */
|
||||
get_info:
|
||||
pos=(uchar*) mysql->net.read_pos;
|
||||
|
@ -1142,10 +1147,8 @@ get_info:
|
|||
{
|
||||
mysql->affected_rows= net_field_length_ll(&pos);
|
||||
mysql->insert_id= net_field_length_ll(&pos);
|
||||
if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
|
||||
{
|
||||
mysql->server_status=uint2korr(pos); pos+=2;
|
||||
}
|
||||
mysql->server_status=uint2korr(pos); pos+=2;
|
||||
mysql->warning_count=uint2korr(pos); pos+=2;
|
||||
if (pos < mysql->net.read_pos+length && net_field_length(&pos))
|
||||
mysql->info=(char*) pos;
|
||||
DBUG_RETURN(0);
|
||||
|
@ -1154,7 +1157,7 @@ get_info:
|
|||
{
|
||||
int error=send_file_to_server(mysql,(char*) pos);
|
||||
if ((length=net_safe_read(mysql)) == packet_error || error)
|
||||
DBUG_RETURN(-1);
|
||||
DBUG_RETURN(1);
|
||||
goto get_info; /* Get info packet */
|
||||
}
|
||||
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
|
||||
|
@ -1162,19 +1165,20 @@ get_info:
|
|||
|
||||
mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
|
||||
if (!(fields=read_rows(mysql,(MYSQL_FIELD*) 0,5)))
|
||||
DBUG_RETURN(-1);
|
||||
DBUG_RETURN(1);
|
||||
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
|
||||
(uint) field_count,0,
|
||||
(my_bool) test(mysql->server_capabilities &
|
||||
CLIENT_LONG_FLAG))))
|
||||
DBUG_RETURN(-1);
|
||||
DBUG_RETURN(1);
|
||||
mysql->status=MYSQL_STATUS_GET_RESULT;
|
||||
mysql->field_count=field_count;
|
||||
mysql->warning_count= 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* A modified version of connect(). connect2() allows you to specify
|
||||
* A modified version of connect(). my_connect() allows you to specify
|
||||
* a timeout value, in seconds, that we should wait until we
|
||||
* derermine we can't connect to a particular host. If timeout is 0,
|
||||
* my_connect() will behave exactly like connect().
|
||||
|
@ -1182,11 +1186,11 @@ get_info:
|
|||
* Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
|
||||
*****************************************************************************/
|
||||
|
||||
int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
|
||||
uint timeout)
|
||||
my_bool my_connect(my_socket s, const struct sockaddr *name, uint namelen,
|
||||
uint timeout)
|
||||
{
|
||||
#if defined(__WIN__) || defined(OS2)
|
||||
return connect(s, (struct sockaddr*) name, namelen);
|
||||
return connect(s, (struct sockaddr*) name, namelen) != 0;
|
||||
#else
|
||||
int flags, res, s_err;
|
||||
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
|
||||
|
@ -1199,7 +1203,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
|
|||
*/
|
||||
|
||||
if (timeout == 0)
|
||||
return connect(s, (struct sockaddr*) name, namelen);
|
||||
return connect(s, (struct sockaddr*) name, namelen) != 0;
|
||||
|
||||
flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */
|
||||
#ifdef O_NONBLOCK
|
||||
|
@ -1212,7 +1216,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
|
|||
if ((res != 0) && (s_err != EINPROGRESS))
|
||||
{
|
||||
errno = s_err; /* Restore it */
|
||||
return(-1);
|
||||
return(1);
|
||||
}
|
||||
if (res == 0) /* Connected quickly! */
|
||||
return(0);
|
||||
|
@ -1252,7 +1256,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
|
|||
now_time=time(NULL);
|
||||
timeout-= (uint) (now_time - start_time);
|
||||
if (errno != EINTR || (int) timeout <= 0)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* select() returned something more interesting than zero, let's
|
||||
|
@ -1262,12 +1266,12 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
|
|||
|
||||
s_err=0;
|
||||
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
|
||||
return(-1);
|
||||
return(1);
|
||||
|
||||
if (s_err)
|
||||
{ /* getsockopt could succeed */
|
||||
errno = s_err;
|
||||
return(-1); /* but return an error... */
|
||||
return(1); /* but return an error... */
|
||||
}
|
||||
return(0); /* It's all good! */
|
||||
#endif
|
||||
|
@ -1881,6 +1885,11 @@ const char * STDCALL mysql_error(MYSQL *mysql)
|
|||
return (mysql)->net.last_error;
|
||||
}
|
||||
|
||||
uint STDCALL mysql_warning_count(MYSQL *mysql)
|
||||
{
|
||||
return mysql->warning_count;
|
||||
}
|
||||
|
||||
const char *STDCALL mysql_info(MYSQL *mysql)
|
||||
{
|
||||
return (mysql)->info;
|
||||
|
@ -1906,6 +1915,18 @@ uint STDCALL mysql_thread_safe(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
MYSQL_RES *STDCALL mysql_warnings(MYSQL *mysql)
|
||||
{
|
||||
uint warning_count;
|
||||
DBUG_ENTER("mysql_warnings");
|
||||
/* Save warning count as mysql_real_query may change this */
|
||||
warning_count= mysql->warning_count;
|
||||
if (mysql_real_query(mysql, "SHOW WARNINGS", 13))
|
||||
DBUG_RETURN(0);
|
||||
mysql->warning_count= warning_count;
|
||||
DBUG_RETURN(mysql_store_result(mysql));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
** Some support functions
|
||||
****************************************************************************/
|
||||
|
|
|
@ -7,6 +7,8 @@ ft_test1
|
|||
mi_test1
|
||||
mi_test2
|
||||
mi_test3
|
||||
rt_test
|
||||
sp_test
|
||||
myisamchk
|
||||
myisamlog
|
||||
myisampack
|
||||
|
|
|
@ -25,14 +25,16 @@ bin_PROGRAMS = myisamchk myisamlog myisampack
|
|||
myisamchk_DEPENDENCIES= $(LIBRARIES)
|
||||
myisamlog_DEPENDENCIES= $(LIBRARIES)
|
||||
myisampack_DEPENDENCIES=$(LIBRARIES)
|
||||
noinst_PROGRAMS = mi_test1 mi_test2 mi_test3 ft_dump #ft_test1 ft_eval
|
||||
noinst_HEADERS = myisamdef.h fulltext.h ftdefs.h ft_test1.h ft_eval.h
|
||||
noinst_PROGRAMS = mi_test1 mi_test2 mi_test3 rt_test sp_test ft_dump #ft_test1 ft_eval
|
||||
noinst_HEADERS = myisamdef.h rt_index.h rt_key.h rt_mbr.h sp_defs.h fulltext.h ftdefs.h ft_test1.h ft_eval.h
|
||||
mi_test1_DEPENDENCIES= $(LIBRARIES)
|
||||
mi_test2_DEPENDENCIES= $(LIBRARIES)
|
||||
mi_test3_DEPENDENCIES= $(LIBRARIES)
|
||||
#ft_test1_DEPENDENCIES= $(LIBRARIES)
|
||||
#ft_eval_DEPENDENCIES= $(LIBRARIES)
|
||||
ft_dump_DEPENDENCIES= $(LIBRARIES)
|
||||
rt_test_DEPENDENCIES= $(LIBRARIES)
|
||||
sp_test_DEPENDENCIES= $(LIBRARIES)
|
||||
libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
|
||||
mi_rnext.c mi_rnext_same.c \
|
||||
mi_search.c mi_page.c mi_key.c mi_locking.c \
|
||||
|
@ -46,8 +48,9 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
|
|||
mi_changed.c mi_static.c mi_delete_all.c \
|
||||
mi_delete_table.c mi_rename.c mi_check.c \
|
||||
ft_parser.c ft_stopwords.c ft_static.c \
|
||||
ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c
|
||||
CLEANFILES = test?.MY? FT?.MY? isam.log mi_test_all
|
||||
ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c \
|
||||
rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c
|
||||
CLEANFILES = test?.MY? FT?.MY? isam.log mi_test_all rt_test.MY? sp_test.MY?
|
||||
DEFS = -DMAP_TO_USE_RAID
|
||||
# Omit dependency for ../mit-pthreads/include/sys that only exits if
|
||||
# mit-pthreads are used
|
||||
|
|
|
@ -119,7 +119,7 @@ static int FTB_WORD_cmp(my_off_t *v, FTB_WORD *a, FTB_WORD *b)
|
|||
static int FTB_WORD_cmp_list(CHARSET_INFO *cs, FTB_WORD **a, FTB_WORD **b)
|
||||
{
|
||||
/* ORDER BY word DESC, ndepth DESC */
|
||||
int i=_mi_compare_text(cs, (*b)->word+1,(*b)->len-1,
|
||||
int i= mi_compare_text(cs, (*b)->word+1,(*b)->len-1,
|
||||
(*a)->word+1,(*a)->len-1,0);
|
||||
if (!i)
|
||||
i=CMP_NUM((*b)->ndepth,(*a)->ndepth);
|
||||
|
@ -242,8 +242,8 @@ static void _ftb_init_index_search(FT_INFO *ftb)
|
|||
{
|
||||
if (!is_tree_inited(& ftb->no_dupes))
|
||||
{
|
||||
init_tree(& ftb->no_dupes,0,0,sizeof(my_off_t),
|
||||
_ftb_no_dupes_cmp,0,0,0);
|
||||
init_tree(&ftb->no_dupes,0,0,sizeof(my_off_t),
|
||||
_ftb_no_dupes_cmp, 0, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ static void _ftb_init_index_search(FT_INFO *ftb)
|
|||
SEARCH_FIND | SEARCH_BIGGER, keyroot);
|
||||
if (!r)
|
||||
{
|
||||
r=_mi_compare_text(ftb->charset,
|
||||
r= mi_compare_text(ftb->charset,
|
||||
info->lastkey + (ftbw->flags&FTB_FLAG_TRUNC),
|
||||
ftbw->len - (ftbw->flags&FTB_FLAG_TRUNC),
|
||||
ftbw->word + (ftbw->flags&FTB_FLAG_TRUNC),
|
||||
|
@ -460,7 +460,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record)
|
|||
(curdoc=((FTB_WORD *)queue_top(& ftb->queue))->docid[0]) !=
|
||||
HA_POS_ERROR)
|
||||
{
|
||||
while (curdoc==(ftbw=(FTB_WORD *)queue_top(& ftb->queue))->docid[0])
|
||||
while (curdoc == (ftbw=(FTB_WORD *)queue_top(& ftb->queue))->docid[0])
|
||||
{
|
||||
_ftb_climb_the_tree(ftb, ftbw, 0);
|
||||
|
||||
|
@ -469,7 +469,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record)
|
|||
SEARCH_BIGGER , keyroot);
|
||||
if (!r)
|
||||
{
|
||||
r=_mi_compare_text(ftb->charset,
|
||||
r= mi_compare_text(ftb->charset,
|
||||
info->lastkey + (ftbw->flags&FTB_FLAG_TRUNC),
|
||||
ftbw->len - (ftbw->flags&FTB_FLAG_TRUNC),
|
||||
ftbw->word + (ftbw->flags&FTB_FLAG_TRUNC),
|
||||
|
@ -501,12 +501,14 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record)
|
|||
ftbe->yesses>=(ftbe->ythresh-ftbe->yweaks) && !ftbe->nos)
|
||||
{
|
||||
/* curdoc matched ! */
|
||||
if (is_tree_inited(& ftb->no_dupes) &&
|
||||
tree_insert(& ftb->no_dupes, &curdoc, 0)->count >1)
|
||||
if (is_tree_inited(&ftb->no_dupes) &&
|
||||
tree_insert(&ftb->no_dupes, &curdoc, 0,
|
||||
ftb->no_dupes.custom_arg)->count >1)
|
||||
/* but it managed to get past this line once */
|
||||
continue;
|
||||
|
||||
info->lastpos=curdoc;
|
||||
/* Clear all states, except that the table was updated */
|
||||
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||
|
||||
if (!(*info->read_record)(info,curdoc,record))
|
||||
|
@ -575,9 +577,9 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
|
|||
for (a=0, b=ftb->queue.elements, c=(a+b)/2; b-a>1; c=(a+b)/2)
|
||||
{
|
||||
ftbw=ftb->list[c];
|
||||
if (_mi_compare_text(ftb->charset, word.pos, word.len,
|
||||
(uchar*) ftbw->word+1, ftbw->len-1,
|
||||
(my_bool) (ftbw->flags&FTB_FLAG_TRUNC)) >0)
|
||||
if (mi_compare_text(ftb->charset, word.pos, word.len,
|
||||
(uchar*) ftbw->word+1, ftbw->len-1,
|
||||
(my_bool) (ftbw->flags&FTB_FLAG_TRUNC)) >0)
|
||||
b=c;
|
||||
else
|
||||
a=c;
|
||||
|
@ -585,9 +587,9 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
|
|||
for (; c>=0; c--)
|
||||
{
|
||||
ftbw=ftb->list[c];
|
||||
if (_mi_compare_text(ftb->charset, word.pos,word.len,
|
||||
(uchar*) ftbw->word+1,ftbw->len-1,
|
||||
(my_bool) (ftbw->flags&FTB_FLAG_TRUNC)))
|
||||
if (mi_compare_text(ftb->charset, word.pos,word.len,
|
||||
(uchar*) ftbw->word+1,ftbw->len-1,
|
||||
(my_bool) (ftbw->flags&FTB_FLAG_TRUNC)))
|
||||
break;
|
||||
if (ftbw->docid[1] == docid)
|
||||
continue;
|
||||
|
|
|
@ -131,7 +131,7 @@ int main(int argc,char *argv[])
|
|||
#endif
|
||||
|
||||
snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey+1);
|
||||
casedn_str(buf);
|
||||
my_casedn_str(default_charset_info,buf);
|
||||
total++;
|
||||
lengths[keylen]++;
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ FILE *df,*qf;
|
|||
|
||||
MI_COLUMNDEF recinfo[3];
|
||||
MI_KEYDEF keyinfo[2];
|
||||
MI_KEYSEG keyseg[10];
|
||||
HA_KEYSEG keyseg[10];
|
||||
|
||||
#define SWL_INIT 500
|
||||
#define SWL_PLUS 50
|
||||
|
|
|
@ -98,9 +98,10 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
|
|||
|
||||
while (!r)
|
||||
{
|
||||
if (_mi_compare_text(aio->charset,
|
||||
aio->info->lastkey,keylen,
|
||||
aio->keybuff,keylen,0)) break;
|
||||
if (mi_compare_text(aio->charset,
|
||||
aio->info->lastkey,keylen,
|
||||
aio->keybuff,keylen,0))
|
||||
break;
|
||||
|
||||
#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
|
||||
#ifdef EVAL_RUN
|
||||
|
@ -120,7 +121,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
|
|||
sdoc.doc.dpos=aio->info->lastpos;
|
||||
|
||||
/* saving document matched into dtree */
|
||||
if (!(selem=tree_insert(&aio->dtree, &sdoc, 0)))
|
||||
if (!(selem=tree_insert(&aio->dtree, &sdoc, 0, aio->dtree.custom_arg)))
|
||||
return 1;
|
||||
|
||||
sptr=(FT_SUPERDOC *)ELEMENT_KEY((&aio->dtree), selem);
|
||||
|
|
|
@ -37,8 +37,8 @@ typedef struct st_ft_docstat {
|
|||
|
||||
static int FT_WORD_cmp(CHARSET_INFO* cs, FT_WORD *w1, FT_WORD *w2)
|
||||
{
|
||||
return _mi_compare_text(cs, (uchar*) w1->pos, w1->len,
|
||||
(uchar*) w2->pos, w2->len, 0);
|
||||
return mi_compare_text(cs, (uchar*) w1->pos, w1->len,
|
||||
(uchar*) w2->pos, w2->len, 0);
|
||||
}
|
||||
|
||||
static int walk_and_copy(FT_WORD *word,uint32 count,FT_DOCSTAT *docstat)
|
||||
|
@ -105,13 +105,13 @@ FT_WORD * ft_linearize(TREE *wtree)
|
|||
DBUG_RETURN(wlist);
|
||||
}
|
||||
|
||||
#define true_word_char(X) (isalnum(X) || (X)=='_')
|
||||
#define true_word_char(s,X) (my_isalnum(s,X) || (X)=='_')
|
||||
#ifdef HYPHEN_IS_DELIM
|
||||
#define misc_word_char(X) ((X)=='\'')
|
||||
#else
|
||||
#define misc_word_char(X) ((X)=='\'' || (X)=='-')
|
||||
#endif
|
||||
#define word_char(X) (true_word_char(X) || misc_word_char(X))
|
||||
#define word_char(s,X) (true_word_char(s,X) || misc_word_char(s,X))
|
||||
|
||||
|
||||
/* returns:
|
||||
|
@ -132,7 +132,11 @@ byte ft_get_word(byte **start, byte *end, FT_WORD *word, FTB_PARAM *param)
|
|||
{
|
||||
for (;doc<end;doc++)
|
||||
{
|
||||
if (true_word_char(*doc)) break;
|
||||
/*
|
||||
BAR TODO: discuss with Serge how to remove
|
||||
default_charset_info correctly
|
||||
*/
|
||||
if (true_word_char(default_charset_info,*doc)) break;
|
||||
if (*doc == FTB_RQUOT && param->quot) {
|
||||
param->quot=doc;
|
||||
*start=doc+1;
|
||||
|
@ -162,7 +166,7 @@ byte ft_get_word(byte **start, byte *end, FT_WORD *word, FTB_PARAM *param)
|
|||
|
||||
mwc=0;
|
||||
for (word->pos=doc; doc<end; doc++)
|
||||
if (true_word_char(*doc))
|
||||
if (true_word_char(default_charset_info,*doc))
|
||||
mwc=0;
|
||||
else if (!misc_word_char(*doc) || mwc++)
|
||||
break;
|
||||
|
@ -191,12 +195,12 @@ byte ft_simple_get_word(byte **start, byte *end, FT_WORD *word)
|
|||
{
|
||||
for (;doc<end;doc++)
|
||||
{
|
||||
if (true_word_char(*doc)) break;
|
||||
if (true_word_char(default_charset_info,*doc)) break;
|
||||
}
|
||||
|
||||
mwc=0;
|
||||
for(word->pos=doc; doc<end; doc++)
|
||||
if (true_word_char(*doc))
|
||||
if (true_word_char(default_charset_info,*doc))
|
||||
mwc=0;
|
||||
else if (!misc_word_char(*doc) || mwc++)
|
||||
break;
|
||||
|
@ -226,7 +230,7 @@ int ft_parse(TREE *wtree, byte *doc, int doclen)
|
|||
|
||||
while (ft_simple_get_word(&doc,end,&w))
|
||||
{
|
||||
if (!tree_insert(wtree, &w, 0))
|
||||
if (!tree_insert(wtree, &w, 0, wtree->custom_arg))
|
||||
goto err;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -23,7 +23,7 @@ ulong ft_max_word_len=HA_FT_MAXLEN;
|
|||
ulong ft_max_word_len_for_sort=20;
|
||||
const char *ft_boolean_syntax="+ -><()~*:\"\"&|";
|
||||
|
||||
const MI_KEYSEG ft_keysegs[FT_SEGS]={
|
||||
const HA_KEYSEG ft_keysegs[FT_SEGS]={
|
||||
{
|
||||
HA_KEYTYPE_VARTEXT, /* type */
|
||||
7, /* language (will be overwritten) */
|
||||
|
|
|
@ -28,9 +28,9 @@ static TREE *stopwords3=NULL;
|
|||
static int FT_STOPWORD_cmp(void* cmp_arg __attribute__((unused)),
|
||||
FT_STOPWORD *w1, FT_STOPWORD *w2)
|
||||
{
|
||||
return _mi_compare_text(default_charset_info,
|
||||
(uchar *)w1->pos,w1->len,
|
||||
(uchar *)w2->pos,w2->len,0);
|
||||
return mi_compare_text(default_charset_info,
|
||||
(uchar *)w1->pos,w1->len,
|
||||
(uchar *)w2->pos,w2->len,0);
|
||||
}
|
||||
|
||||
int ft_init_stopwords(const char **sws)
|
||||
|
@ -41,8 +41,8 @@ int ft_init_stopwords(const char **sws)
|
|||
if(!stopwords3)
|
||||
{
|
||||
if(!(stopwords3=(TREE *)my_malloc(sizeof(TREE),MYF(0)))) return -1;
|
||||
init_tree(stopwords3,0,0,sizeof(FT_STOPWORD),(qsort_cmp2)&FT_STOPWORD_cmp,0,
|
||||
NULL, NULL);
|
||||
init_tree(stopwords3,0,0,sizeof(FT_STOPWORD),(qsort_cmp2)&FT_STOPWORD_cmp,
|
||||
0, NULL, NULL);
|
||||
}
|
||||
|
||||
if(!sws) return 0;
|
||||
|
@ -50,7 +50,7 @@ int ft_init_stopwords(const char **sws)
|
|||
for(;*sws;sws++)
|
||||
{
|
||||
if( (sw.len= (uint) strlen(sw.pos=*sws)) < ft_min_word_len) continue;
|
||||
if(!tree_insert(stopwords3, &sw, 0))
|
||||
if(!tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg))
|
||||
{
|
||||
delete_tree(stopwords3); /* purecov: inspected */
|
||||
return -1; /* purecov: inspected */
|
||||
|
@ -64,7 +64,7 @@ int is_stopword(char *word, uint len)
|
|||
FT_STOPWORD sw;
|
||||
sw.pos=word;
|
||||
sw.len=len;
|
||||
return tree_search(stopwords3,&sw) != NULL;
|
||||
return tree_search(stopwords3, &sw, stopwords3->custom_arg) != NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
static MI_COLUMNDEF recinfo[3];
|
||||
static MI_KEYDEF keyinfo[2];
|
||||
static MI_KEYSEG keyseg[10];
|
||||
static HA_KEYSEG keyseg[10];
|
||||
|
||||
static int run_test(const char *filename)
|
||||
{
|
||||
|
|
|
@ -163,8 +163,8 @@ int _mi_ft_cmp(MI_INFO *info, uint keynr, const byte *rec1, const byte *rec2)
|
|||
{
|
||||
if ((ftsi1.pos != ftsi2.pos) &&
|
||||
(!ftsi1.pos || !ftsi2.pos ||
|
||||
_mi_compare_text(cs, (uchar*) ftsi1.pos,ftsi1.len,
|
||||
(uchar*) ftsi2.pos,ftsi2.len,0)))
|
||||
mi_compare_text(cs, (uchar*) ftsi1.pos,ftsi1.len,
|
||||
(uchar*) ftsi2.pos,ftsi2.len,0)))
|
||||
return THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT;
|
||||
}
|
||||
return GEE_THEY_ARE_ABSOLUTELY_IDENTICAL;
|
||||
|
@ -190,7 +190,7 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf,
|
|||
error=0;
|
||||
while(old_word->pos && new_word->pos)
|
||||
{
|
||||
cmp=_mi_compare_text(cs, (uchar*) old_word->pos,old_word->len,
|
||||
cmp= mi_compare_text(cs, (uchar*) old_word->pos,old_word->len,
|
||||
(uchar*) new_word->pos,new_word->len,0);
|
||||
cmp2= cmp ? 0 : (fabs(old_word->weight - new_word->weight) > 1.e-5);
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ byte ft_simple_get_word(byte **, byte *, FT_WORD *);
|
|||
|
||||
typedef struct _st_ft_seg_iterator {
|
||||
uint num, len;
|
||||
MI_KEYSEG *seg;
|
||||
HA_KEYSEG *seg;
|
||||
const byte *rec, *pos;
|
||||
} FT_SEG_ITERATOR;
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#define FT_SEGS 2
|
||||
#endif /* EVAL_RUN */
|
||||
|
||||
extern const MI_KEYSEG ft_keysegs[FT_SEGS];
|
||||
extern const HA_KEYSEG ft_keysegs[FT_SEGS];
|
||||
|
||||
int _mi_ft_cmp(MI_INFO *, uint, const byte *, const byte *);
|
||||
int _mi_ft_add(MI_INFO *, uint, byte *, const byte *, my_off_t);
|
||||
|
|
|
@ -583,8 +583,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
|
|||
goto err;
|
||||
}
|
||||
if ((*keys)++ &&
|
||||
(flag=_mi_key_cmp(keyinfo->seg,info->lastkey,key,key_length,
|
||||
comp_flag, ¬_used)) >=0)
|
||||
(flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length,
|
||||
comp_flag, ¬_used)) >=0)
|
||||
{
|
||||
DBUG_DUMP("old",(byte*) info->lastkey, info->lastkey_length);
|
||||
DBUG_DUMP("new",(byte*) key, key_length);
|
||||
|
@ -601,8 +601,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
|
|||
if (*keys != 1L) /* not first_key */
|
||||
{
|
||||
uint diff;
|
||||
_mi_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,SEARCH_FIND,
|
||||
&diff);
|
||||
ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,SEARCH_FIND,
|
||||
&diff);
|
||||
param->unique_count[diff-1]++;
|
||||
}
|
||||
}
|
||||
|
@ -669,7 +669,7 @@ static ha_checksum calc_checksum(ha_rows count)
|
|||
static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
|
||||
{
|
||||
uint length;
|
||||
MI_KEYSEG *keyseg;
|
||||
HA_KEYSEG *keyseg;
|
||||
DBUG_ENTER("isam_key_length");
|
||||
|
||||
length= info->s->rec_reflength;
|
||||
|
@ -1771,7 +1771,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
|
|||
File new_file;
|
||||
MI_SORT_PARAM sort_param;
|
||||
MYISAM_SHARE *share=info->s;
|
||||
MI_KEYSEG *keyseg;
|
||||
HA_KEYSEG *keyseg;
|
||||
ulong *rec_per_key_part;
|
||||
char llbuff[22];
|
||||
SORT_INFO sort_info;
|
||||
|
@ -2136,7 +2136,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
|
|||
MI_SORT_PARAM *sort_param=0;
|
||||
MYISAM_SHARE *share=info->s;
|
||||
ulong *rec_per_key_part;
|
||||
MI_KEYSEG *keyseg;
|
||||
HA_KEYSEG *keyseg;
|
||||
char llbuff[22];
|
||||
IO_CACHE_SHARE io_share;
|
||||
SORT_INFO sort_info;
|
||||
|
@ -3050,8 +3050,8 @@ static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
|
|||
const void *b)
|
||||
{
|
||||
uint not_used;
|
||||
return (_mi_key_cmp(sort_param->keyinfo->seg,*((uchar**) a),*((uchar**) b),
|
||||
USE_WHOLE_KEY, SEARCH_SAME,¬_used));
|
||||
return (ha_key_cmp(sort_param->keyinfo->seg, *((uchar**) a), *((uchar**) b),
|
||||
USE_WHOLE_KEY, SEARCH_SAME,¬_used));
|
||||
} /* sort_key_cmp */
|
||||
|
||||
|
||||
|
@ -3065,9 +3065,9 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
|
|||
|
||||
if (sort_info->key_block->inited)
|
||||
{
|
||||
cmp=_mi_key_cmp(sort_param->keyinfo->seg, sort_info->key_block->lastkey,
|
||||
(uchar*) a, USE_WHOLE_KEY, SEARCH_FIND | SEARCH_UPDATE,
|
||||
&diff_pos);
|
||||
cmp=ha_key_cmp(sort_param->keyinfo->seg,sort_info->key_block->lastkey,
|
||||
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
|
||||
&diff_pos);
|
||||
sort_param->unique[diff_pos-1]++;
|
||||
}
|
||||
else
|
||||
|
@ -3078,13 +3078,16 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
|
|||
{
|
||||
sort_info->dupp++;
|
||||
sort_info->info->lastpos=get_record_for_key(sort_info->info,
|
||||
sort_param->keyinfo,
|
||||
(uchar*) a);
|
||||
sort_param->keyinfo,
|
||||
(uchar*) a);
|
||||
mi_check_print_warning(param,
|
||||
"Duplicate key for record at %10s against record at %10s",
|
||||
llstr(sort_info->info->lastpos,llbuff),
|
||||
llstr(get_record_for_key(sort_info->info, sort_param->keyinfo,
|
||||
sort_info->key_block->lastkey), llbuff2));
|
||||
"Duplicate key for record at %10s against record at %10s",
|
||||
llstr(sort_info->info->lastpos,llbuff),
|
||||
llstr(get_record_for_key(sort_info->info,
|
||||
sort_param->keyinfo,
|
||||
sort_info->key_block->
|
||||
lastkey),
|
||||
llbuff2));
|
||||
param->testflag|=T_RETRY_WITHOUT_QUICK;
|
||||
if (sort_info->param->testflag & T_VERBOSE)
|
||||
_mi_print_key(stdout,sort_param->keyinfo->seg,(uchar*) a, USE_WHOLE_KEY);
|
||||
|
@ -3340,7 +3343,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
|
|||
MI_INFO info;
|
||||
MYISAM_SHARE share;
|
||||
MI_KEYDEF *keyinfo,*key,*key_end;
|
||||
MI_KEYSEG *keysegs,*keyseg;
|
||||
HA_KEYSEG *keysegs,*keyseg;
|
||||
MI_COLUMNDEF *recdef,*rec,*end;
|
||||
MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
|
||||
MI_STATUS_INFO status_info;
|
||||
|
@ -3362,7 +3365,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
|
|||
(size_t) (sizeof(MI_KEYDEF)*share.base.keys));
|
||||
|
||||
key_parts= share.base.all_key_parts;
|
||||
if (!(keysegs=(MI_KEYSEG*) my_alloca(sizeof(MI_KEYSEG)*
|
||||
if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
|
||||
(key_parts+share.base.keys))))
|
||||
{
|
||||
my_afree((gptr) keyinfo);
|
||||
|
@ -3398,7 +3401,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
|
|||
|
||||
/* Change the new key to point at the saved key segments */
|
||||
memcpy((byte*) keysegs,(byte*) share.keyparts,
|
||||
(size_t) (sizeof(MI_KEYSEG)*(key_parts+share.base.keys+
|
||||
(size_t) (sizeof(HA_KEYSEG)*(key_parts+share.base.keys+
|
||||
share.state.header.uniques)));
|
||||
keyseg=keysegs;
|
||||
for (key=keyinfo,key_end=keyinfo+share.base.keys; key != key_end ; key++)
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
/* Create a MyISAM table */
|
||||
|
||||
#include "fulltext.h"
|
||||
#include "sp_defs.h"
|
||||
|
||||
#if defined(MSDOS) || defined(__WIN__)
|
||||
#ifdef __WIN__
|
||||
#include <fcntl.h>
|
||||
|
@ -51,7 +53,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
|
|||
MYISAM_SHARE share;
|
||||
MI_KEYDEF *keydef,tmp_keydef;
|
||||
MI_UNIQUEDEF *uniquedef;
|
||||
MI_KEYSEG *keyseg,tmp_keyseg;
|
||||
HA_KEYSEG *keyseg,tmp_keyseg;
|
||||
MI_COLUMNDEF *rec;
|
||||
ulong *rec_per_key_part;
|
||||
my_off_t key_root[MI_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
|
||||
|
@ -233,11 +235,42 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
|
|||
|
||||
for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++)
|
||||
{
|
||||
share.state.key_root[i]= HA_OFFSET_ERROR;
|
||||
|
||||
share.state.key_root[i]= HA_OFFSET_ERROR;
|
||||
min_key_length_skipp=length=0;
|
||||
key_length=pointer;
|
||||
if (keydef->flag & HA_SPATIAL)
|
||||
{
|
||||
/* BAR TODO to support 3D and more dimensions in the future */
|
||||
uint sp_segs=SPDIMS*2;
|
||||
keydef->flag=HA_SPATIAL;
|
||||
|
||||
if (flags & HA_DONT_TOUCH_DATA)
|
||||
{
|
||||
/*
|
||||
called by myisamchk - i.e. table structure was taken from
|
||||
MYI file and SPATIAL key *do has* additional sp_segs keysegs.
|
||||
We'd better delete them now
|
||||
*/
|
||||
keydef->keysegs-=sp_segs;
|
||||
}
|
||||
|
||||
for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
|
||||
j++, keyseg++)
|
||||
{
|
||||
if (keyseg->type != HA_KEYTYPE_BINARY &&
|
||||
keyseg->type != HA_KEYTYPE_VARBINARY)
|
||||
{
|
||||
my_errno=HA_WRONG_CREATE_OPTION;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
keydef->keysegs+=sp_segs;
|
||||
key_length+=SPLEN*sp_segs;
|
||||
length++; /* At least one length byte */
|
||||
min_key_length_skipp+=SPLEN*2*SPDIMS;
|
||||
}
|
||||
else
|
||||
if (keydef->flag & HA_FULLTEXT) /* SerG */
|
||||
{
|
||||
keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
|
||||
|
@ -411,7 +444,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
|
|||
info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+
|
||||
keys * MI_KEYDEF_SIZE+
|
||||
uniques * MI_UNIQUEDEF_SIZE +
|
||||
(key_segs + unique_key_parts)*MI_KEYSEG_SIZE+
|
||||
(key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
|
||||
columns*MI_COLUMNDEF_SIZE);
|
||||
|
||||
bmove(share.state.header.file_version,(byte*) myisam_file_magic,4);
|
||||
|
@ -558,19 +591,35 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
|
|||
for (i=0 ; i < share.base.keys - uniques; i++)
|
||||
{
|
||||
uint ft_segs=(keydefs[i].flag & HA_FULLTEXT) ? FT_SEGS : 0;
|
||||
uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0;
|
||||
|
||||
if (mi_keydef_write(file, &keydefs[i]))
|
||||
goto err;
|
||||
for (j=0 ; j < keydefs[i].keysegs-ft_segs ; j++)
|
||||
for (j=0 ; j < keydefs[i].keysegs-ft_segs-sp_segs ; j++)
|
||||
if (mi_keyseg_write(file, &keydefs[i].seg[j]))
|
||||
goto err;
|
||||
goto err;
|
||||
for (j=0 ; j < ft_segs ; j++)
|
||||
{
|
||||
MI_KEYSEG seg=ft_keysegs[j];
|
||||
HA_KEYSEG seg=ft_keysegs[j];
|
||||
seg.language= keydefs[i].seg[0].language;
|
||||
if (mi_keyseg_write(file, &seg))
|
||||
goto err;
|
||||
}
|
||||
for (j=0 ; j < sp_segs ; j++)
|
||||
{
|
||||
HA_KEYSEG sseg;
|
||||
sseg.type=SPTYPE;
|
||||
sseg.language= 7;
|
||||
sseg.null_bit=0;
|
||||
sseg.bit_start=0;
|
||||
sseg.bit_end=0;
|
||||
sseg.length=SPLEN;
|
||||
sseg.null_pos=0;
|
||||
sseg.start=j*SPLEN;
|
||||
sseg.flag= HA_SWAP_KEY;
|
||||
if (mi_keyseg_write(file, &sseg))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* Create extra keys for unique definitions */
|
||||
offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
/* Print a key in user understandable format */
|
||||
|
||||
void _mi_print_key(FILE *stream, register MI_KEYSEG *keyseg,
|
||||
void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg,
|
||||
const uchar *key, uint length)
|
||||
{
|
||||
int flag;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
/* Remove a row from a MyISAM table */
|
||||
|
||||
#include "fulltext.h"
|
||||
#include "rt_index.h"
|
||||
|
||||
#ifdef __WIN__
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
@ -79,9 +81,9 @@ int mi_delete(MI_INFO *info,const byte *record)
|
|||
}
|
||||
else
|
||||
{
|
||||
uint key_length=_mi_make_key(info,i,old_key,record,info->lastpos);
|
||||
if (_mi_ck_delete(info,i,old_key,key_length))
|
||||
goto err;
|
||||
if (info->s->keyinfo[i].ck_delete(info,i,old_key,
|
||||
_mi_make_key(info,i,old_key,record,info->lastpos)))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "myisamdef.h"
|
||||
#include "m_ctype.h"
|
||||
#include "sp_defs.h"
|
||||
#ifdef HAVE_IEEEFP_H
|
||||
#include <ieeefp.h>
|
||||
#endif
|
||||
|
@ -36,9 +37,17 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
|
|||
{
|
||||
byte *pos,*end;
|
||||
uchar *start;
|
||||
reg1 MI_KEYSEG *keyseg;
|
||||
reg1 HA_KEYSEG *keyseg;
|
||||
DBUG_ENTER("_mi_make_key");
|
||||
|
||||
if(info->s->keyinfo[keynr].flag & HA_SPATIAL)
|
||||
{
|
||||
/*
|
||||
TODO: nulls processing
|
||||
*/
|
||||
return sp_make_key(info,keynr,key,record,filepos);
|
||||
}
|
||||
|
||||
start=key;
|
||||
for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
|
||||
{
|
||||
|
@ -144,7 +153,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
|
|||
{
|
||||
uint length;
|
||||
uchar *pos,*end,*start_key=key;
|
||||
reg1 MI_KEYSEG *keyseg;
|
||||
reg1 HA_KEYSEG *keyseg;
|
||||
enum ha_base_keytype type;
|
||||
DBUG_ENTER("_mi_pack_key");
|
||||
|
||||
|
@ -243,7 +252,7 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
|
|||
{
|
||||
reg2 byte *key;
|
||||
byte *pos,*key_end;
|
||||
reg1 MI_KEYSEG *keyseg;
|
||||
reg1 HA_KEYSEG *keyseg;
|
||||
byte *blob_ptr;
|
||||
DBUG_ENTER("_mi_put_key_in_record");
|
||||
|
||||
|
@ -377,7 +386,7 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
|
|||
void update_auto_increment(MI_INFO *info,const byte *record)
|
||||
{
|
||||
ulonglong value;
|
||||
MI_KEYSEG *keyseg=info->s->keyinfo[info->s->base.auto_key-1].seg;
|
||||
HA_KEYSEG *keyseg=info->s->keyinfo[info->s->base.auto_key-1].seg;
|
||||
const uchar *key=(uchar*) record+keyseg->start;
|
||||
|
||||
switch (keyseg->type) {
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
/* open a isam-database */
|
||||
|
||||
#include "fulltext.h"
|
||||
#include "sp_defs.h"
|
||||
#include "rt_index.h"
|
||||
#include <m_ctype.h>
|
||||
|
||||
#if defined(MSDOS) || defined(__WIN__)
|
||||
|
@ -65,7 +67,7 @@ static MI_INFO *test_if_reopen(char *filename)
|
|||
|
||||
MI_INFO *mi_open(const char *name, int mode, uint open_flags)
|
||||
{
|
||||
int lock_error,kfile,open_mode,save_errno;
|
||||
int lock_error,kfile,open_mode,save_errno,have_rtree=0;
|
||||
uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
|
||||
key_parts,unique_key_parts,tmp_length,uniques;
|
||||
char name_buff[FN_REFLEN], org_name [FN_REFLEN], index_name[FN_REFLEN],
|
||||
|
@ -254,7 +256,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
|
|||
&share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF),
|
||||
&share->keyparts,
|
||||
(key_parts+unique_key_parts+keys+uniques) *
|
||||
sizeof(MI_KEYSEG),
|
||||
sizeof(HA_KEYSEG),
|
||||
&share->rec,
|
||||
(share->base.fields+1)*sizeof(MI_COLUMNDEF),
|
||||
&share->blobs,sizeof(MI_BLOB)*share->base.blobs,
|
||||
|
@ -284,7 +286,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
|
|||
|
||||
share->blocksize=min(IO_SIZE,myisam_block_size);
|
||||
{
|
||||
MI_KEYSEG *pos=share->keyparts;
|
||||
HA_KEYSEG *pos=share->keyparts;
|
||||
for (i=0 ; i < keys ; i++)
|
||||
{
|
||||
disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
|
||||
|
@ -293,6 +295,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
|
|||
for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
|
||||
{
|
||||
disk_pos=mi_keyseg_read(disk_pos, pos);
|
||||
|
||||
if (pos->type == HA_KEYTYPE_TEXT || pos->type == HA_KEYTYPE_VARTEXT)
|
||||
{
|
||||
if (!pos->language)
|
||||
|
@ -304,7 +307,12 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (share->keyinfo[i].flag & HA_FULLTEXT)
|
||||
if (share->keyinfo[i].flag & HA_SPATIAL)
|
||||
{
|
||||
uint sp_segs=SPDIMS*2;
|
||||
share->keyinfo[i].seg=pos-sp_segs;
|
||||
share->keyinfo[i].keysegs--;
|
||||
} else if (share->keyinfo[i].flag & HA_FULLTEXT)
|
||||
{
|
||||
share->keyinfo[i].seg=pos-FT_SEGS;
|
||||
share->fulltext_index=1;
|
||||
|
@ -342,7 +350,11 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
|
|||
}
|
||||
}
|
||||
for (i=0 ; i < keys ; i++)
|
||||
{
|
||||
if (share->keyinfo[i].key_alg == HA_KEY_ALG_RTREE)
|
||||
have_rtree=1;
|
||||
setup_key_functions(share->keyinfo+i);
|
||||
}
|
||||
|
||||
for (i=j=offset=0 ; i < share->base.fields ; i++)
|
||||
{
|
||||
|
@ -421,7 +433,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
|
|||
((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
|
||||
HA_OPTION_COMPRESS_RECORD |
|
||||
HA_OPTION_TEMP_COMPRESS_RECORD)) ||
|
||||
(open_flags & HA_OPEN_TMP_TABLE)) ? 0 : 1;
|
||||
(open_flags & HA_OPEN_TMP_TABLE) ||
|
||||
have_rtree) ? 0 : 1;
|
||||
if (share->concurrent_insert)
|
||||
{
|
||||
share->lock.get_status=mi_get_status;
|
||||
|
@ -451,6 +464,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
|
|||
&info.blobs,sizeof(MI_BLOB)*share->base.blobs,
|
||||
&info.buff,(share->base.max_key_block_length*2+
|
||||
share->base.max_key_length),
|
||||
&info.rtree_recursion_state,have_rtree ? 1024 : 0,
|
||||
&info.lastkey,share->base.max_key_length*3+1,
|
||||
&info.filename,strlen(org_name)+1,
|
||||
NullS))
|
||||
|
@ -649,6 +663,16 @@ void mi_setup_functions(register MYISAM_SHARE *share)
|
|||
|
||||
static void setup_key_functions(register MI_KEYDEF *keyinfo)
|
||||
{
|
||||
if (keyinfo->key_alg == HA_KEY_ALG_RTREE)
|
||||
{
|
||||
keyinfo->ck_insert = rtree_insert;
|
||||
keyinfo->ck_delete = rtree_delete;
|
||||
}
|
||||
else
|
||||
{
|
||||
keyinfo->ck_insert = _mi_ck_write;
|
||||
keyinfo->ck_delete = _mi_ck_delete;
|
||||
}
|
||||
if (keyinfo->flag & HA_BINARY_PACK_KEY)
|
||||
{ /* Simple prefix compression */
|
||||
keyinfo->bin_search=_mi_seq_search;
|
||||
|
@ -914,7 +938,7 @@ uint mi_keydef_write(File file, MI_KEYDEF *keydef)
|
|||
uchar *ptr=buff;
|
||||
|
||||
*ptr++ = (uchar) keydef->keysegs;
|
||||
*ptr++ = 0; /* not used */
|
||||
*ptr++ = keydef->key_alg; /* Rtree or Btree */
|
||||
mi_int2store(ptr,keydef->flag); ptr +=2;
|
||||
mi_int2store(ptr,keydef->block_length); ptr +=2;
|
||||
mi_int2store(ptr,keydef->keylength); ptr +=2;
|
||||
|
@ -926,7 +950,8 @@ uint mi_keydef_write(File file, MI_KEYDEF *keydef)
|
|||
char *mi_keydef_read(char *ptr, MI_KEYDEF *keydef)
|
||||
{
|
||||
keydef->keysegs = (uint) *ptr++;
|
||||
ptr++;
|
||||
keydef->key_alg = *ptr++; /* Rtree or Btree */
|
||||
|
||||
keydef->flag = mi_uint2korr(ptr); ptr +=2;
|
||||
keydef->block_length = mi_uint2korr(ptr); ptr +=2;
|
||||
keydef->keylength = mi_uint2korr(ptr); ptr +=2;
|
||||
|
@ -942,9 +967,9 @@ char *mi_keydef_read(char *ptr, MI_KEYDEF *keydef)
|
|||
** mi_keyseg
|
||||
***************************************************************************/
|
||||
|
||||
int mi_keyseg_write(File file, const MI_KEYSEG *keyseg)
|
||||
int mi_keyseg_write(File file, const HA_KEYSEG *keyseg)
|
||||
{
|
||||
uchar buff[MI_KEYSEG_SIZE];
|
||||
uchar buff[HA_KEYSEG_SIZE];
|
||||
uchar *ptr=buff;
|
||||
|
||||
*ptr++ =keyseg->type;
|
||||
|
@ -962,7 +987,7 @@ int mi_keyseg_write(File file, const MI_KEYSEG *keyseg)
|
|||
}
|
||||
|
||||
|
||||
char *mi_keyseg_read(char *ptr, MI_KEYSEG *keyseg)
|
||||
char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg)
|
||||
{
|
||||
keyseg->type = *ptr++;
|
||||
keyseg->language = *ptr++;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*/
|
||||
|
||||
#include "myisamdef.h"
|
||||
#include "rt_index.h"
|
||||
|
||||
static ha_rows _mi_record_pos(MI_INFO *info,const byte *key,uint key_len,
|
||||
enum ha_rkey_function search_flag);
|
||||
|
@ -39,7 +40,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, const byte *start_key,
|
|||
const byte *end_key, uint end_key_len,
|
||||
enum ha_rkey_function end_search_flag)
|
||||
{
|
||||
ha_rows start_pos,end_pos;
|
||||
ha_rows start_pos,end_pos,res;
|
||||
DBUG_ENTER("mi_records_in_range");
|
||||
|
||||
if ((inx = _mi_check_index(info,inx)) < 0)
|
||||
|
@ -50,20 +51,39 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, const byte *start_key,
|
|||
info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED);
|
||||
if (info->s->concurrent_insert)
|
||||
rw_rdlock(&info->s->key_root_lock[inx]);
|
||||
start_pos= (start_key ?
|
||||
|
||||
switch(info->s->keyinfo[inx].key_alg){
|
||||
case HA_KEY_ALG_RTREE:
|
||||
{
|
||||
uchar * key_buff;
|
||||
if (start_key_len == 0)
|
||||
start_key_len=USE_WHOLE_KEY;
|
||||
key_buff=info->lastkey+info->s->base.max_key_length;
|
||||
start_key_len=_mi_pack_key(info,inx,key_buff,(uchar*) start_key,start_key_len);
|
||||
res=rtree_estimate(info, inx, key_buff, start_key_len, myisam_read_vec[start_search_flag]);
|
||||
res=res?res:1;
|
||||
break;
|
||||
}
|
||||
case HA_KEY_ALG_BTREE:
|
||||
default:
|
||||
start_pos= (start_key ?
|
||||
_mi_record_pos(info,start_key,start_key_len,start_search_flag) :
|
||||
(ha_rows) 0);
|
||||
end_pos= (end_key ?
|
||||
end_pos= (end_key ?
|
||||
_mi_record_pos(info,end_key,end_key_len,end_search_flag) :
|
||||
info->state->records+ (ha_rows) 1);
|
||||
res=end_pos < start_pos ? (ha_rows) 0 :
|
||||
(end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos);
|
||||
if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
|
||||
res=HA_POS_ERROR;
|
||||
}
|
||||
|
||||
if (info->s->concurrent_insert)
|
||||
rw_unlock(&info->s->key_root_lock[inx]);
|
||||
fast_mi_writeinfo(info);
|
||||
if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
|
||||
DBUG_RETURN(HA_POS_ERROR);
|
||||
DBUG_PRINT("info",("records: %ld",(ulong) (end_pos-start_pos)));
|
||||
DBUG_RETURN(end_pos < start_pos ? (ha_rows) 0 :
|
||||
(end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos));
|
||||
|
||||
DBUG_PRINT("info",("records: %ld",(ulong) (res)));
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
/* Read record based on a key */
|
||||
|
||||
#include "myisamdef.h"
|
||||
|
||||
#include "rt_index.h"
|
||||
|
||||
/* Read a record using key */
|
||||
/* Ordinary search_flag is 0 ; Give error if no record with key */
|
||||
|
@ -36,6 +36,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
|||
DBUG_RETURN(my_errno);
|
||||
|
||||
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||
info->last_key_func=search_flag;
|
||||
|
||||
if (!info->use_packed_key)
|
||||
{
|
||||
|
@ -65,22 +66,33 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
|||
if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
|
||||
use_key_length=USE_WHOLE_KEY;
|
||||
|
||||
if (!_mi_search(info,info->s->keyinfo+inx,key_buff,use_key_length,
|
||||
myisam_read_vec[search_flag],info->s->state.key_root[inx]))
|
||||
{
|
||||
while (info->lastpos >= info->state->data_file_length)
|
||||
switch(info->s->keyinfo[inx].key_alg){
|
||||
case HA_KEY_ALG_RTREE:
|
||||
if(rtree_find_first(info,inx,key_buff,use_key_length,nextflag)<0)
|
||||
{
|
||||
/*
|
||||
Skip rows that are inserted by other threads since we got a lock
|
||||
Note that this can only happen if we are not searching after an
|
||||
exact key, because the keys are sorted according to position
|
||||
*/
|
||||
my_errno=HA_ERR_CRASHED;
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case HA_KEY_ALG_BTREE:
|
||||
default:
|
||||
if (!_mi_search(info,info->s->keyinfo+inx,key_buff,use_key_length,
|
||||
myisam_read_vec[search_flag],info->s->state.key_root[inx]))
|
||||
{
|
||||
while (info->lastpos >= info->state->data_file_length)
|
||||
{
|
||||
/*
|
||||
Skip rows that are inserted by other threads since we got a lock
|
||||
Note that this can only happen if we are not searching after an
|
||||
exact key, because the keys are sorted according to position
|
||||
*/
|
||||
|
||||
if (_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
|
||||
if (_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
|
||||
info->lastkey_length,
|
||||
myisam_readnext_vec[search_flag],
|
||||
info->s->state.key_root[inx]))
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (share->concurrent_insert)
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include "myisamdef.h"
|
||||
|
||||
#include "rt_index.h"
|
||||
|
||||
/*
|
||||
Read next row with the same key as previous read
|
||||
One may have done a write, update or delete of the previous row.
|
||||
|
@ -42,27 +44,55 @@ int mi_rnext(MI_INFO *info, byte *buf, int inx)
|
|||
changed=_mi_test_if_changed(info);
|
||||
if (!flag)
|
||||
{
|
||||
error=_mi_search_first(info,info->s->keyinfo+inx,
|
||||
info->s->state.key_root[inx]);
|
||||
switch(info->s->keyinfo[inx].key_alg){
|
||||
case HA_KEY_ALG_RTREE:
|
||||
error=rtree_get_first(info,inx,info->lastkey_length);
|
||||
break;
|
||||
case HA_KEY_ALG_BTREE:
|
||||
default:
|
||||
error=_mi_search_first(info,info->s->keyinfo+inx,
|
||||
info->s->state.key_root[inx]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!changed)
|
||||
error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
|
||||
else
|
||||
{
|
||||
switch(info->s->keyinfo[inx].key_alg)
|
||||
{
|
||||
case HA_KEY_ALG_RTREE:
|
||||
/*
|
||||
Note that rtree doesn't support that the table
|
||||
may be changed since last call, so we do need
|
||||
to skip rows inserted by other threads like in btree
|
||||
*/
|
||||
error=rtree_get_next(info,inx,info->lastkey_length);
|
||||
break;
|
||||
|
||||
case HA_KEY_ALG_BTREE:
|
||||
default:
|
||||
if (!changed)
|
||||
{
|
||||
error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
|
||||
info->lastkey_length,flag,
|
||||
info->s->state.key_root[inx]);
|
||||
else
|
||||
error=_mi_search(info,info->s->keyinfo+inx,info->lastkey,
|
||||
}
|
||||
else
|
||||
{
|
||||
error=_mi_search(info,info->s->keyinfo+inx,info->lastkey,
|
||||
USE_WHOLE_KEY,flag, info->s->state.key_root[inx]);
|
||||
|
||||
if (!error)
|
||||
{
|
||||
while (info->lastpos >= info->state->data_file_length)
|
||||
{
|
||||
/* Skip rows that are inserted by other threads since we got a lock */
|
||||
if ((error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
|
||||
}
|
||||
if (!error)
|
||||
{
|
||||
while (info->lastpos >= info->state->data_file_length)
|
||||
{
|
||||
/* Skip rows that are inserted by other threads since we got a lock */
|
||||
if ((error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
|
||||
info->lastkey_length,
|
||||
SEARCH_BIGGER,
|
||||
info->s->state.key_root[inx])))
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "myisamdef.h"
|
||||
#include "rt_index.h"
|
||||
|
||||
/*
|
||||
Read next row with the same key as previous read, but abort if
|
||||
|
@ -38,26 +39,39 @@ int mi_rnext_same(MI_INFO *info, byte *buf)
|
|||
if (fast_mi_readinfo(info))
|
||||
DBUG_RETURN(my_errno);
|
||||
|
||||
memcpy(info->lastkey2,info->lastkey,info->last_rkey_length);
|
||||
if (info->s->concurrent_insert)
|
||||
rw_rdlock(&info->s->key_root_lock[inx]);
|
||||
for (;;)
|
||||
|
||||
switch(keyinfo->key_alg)
|
||||
{
|
||||
if ((error=_mi_search_next(info,keyinfo,info->lastkey,
|
||||
case HA_KEY_ALG_RTREE:
|
||||
if((error=rtree_find_next(info,inx,myisam_read_vec[info->last_key_func])))
|
||||
{
|
||||
/* FIXME: What to do?*/
|
||||
}
|
||||
break;
|
||||
case HA_KEY_ALG_BTREE:
|
||||
default:
|
||||
|
||||
memcpy(info->lastkey2,info->lastkey,info->last_rkey_length);
|
||||
for (;;)
|
||||
{
|
||||
if ((error=_mi_search_next(info,keyinfo,info->lastkey,
|
||||
info->lastkey_length,flag,
|
||||
info->s->state.key_root[inx])))
|
||||
break;
|
||||
if (_mi_key_cmp(keyinfo->seg,info->lastkey2,info->lastkey,
|
||||
break;
|
||||
if (ha_key_cmp(keyinfo->seg,info->lastkey2,info->lastkey,
|
||||
info->last_rkey_length, SEARCH_FIND, ¬_used))
|
||||
{
|
||||
error=1;
|
||||
my_errno=HA_ERR_END_OF_FILE;
|
||||
info->lastpos= HA_OFFSET_ERROR;
|
||||
break;
|
||||
}
|
||||
/* Skip rows that are inserted by other threads since we got a lock */
|
||||
if (info->lastpos < info->state->data_file_length)
|
||||
break;
|
||||
{
|
||||
error=1;
|
||||
my_errno=HA_ERR_END_OF_FILE;
|
||||
info->lastpos= HA_OFFSET_ERROR;
|
||||
break;
|
||||
}
|
||||
/* Skip rows that are inserted by other threads since we got a lock */
|
||||
if (info->lastpos < info->state->data_file_length)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (info->s->concurrent_insert)
|
||||
rw_unlock(&info->s->key_root_lock[inx]);
|
||||
|
|
|
@ -133,7 +133,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
|
|||
&info->lastkey_length))
|
||||
goto err;
|
||||
if ((nextflag & SEARCH_LAST) &&
|
||||
_mi_key_cmp(keyinfo->seg, info->lastkey, key, key_len, SEARCH_FIND,
|
||||
ha_key_cmp(keyinfo->seg, info->lastkey, key, key_len, SEARCH_FIND,
|
||||
¬_used))
|
||||
{
|
||||
my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
|
||||
|
@ -191,7 +191,7 @@ int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
|
|||
while (start != end)
|
||||
{
|
||||
mid= (start+end)/2;
|
||||
if ((flag=_mi_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len,
|
||||
if ((flag=ha_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len,
|
||||
comp_flag,¬_used))
|
||||
>= 0)
|
||||
end=mid;
|
||||
|
@ -199,7 +199,7 @@ int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
|
|||
start=mid+1;
|
||||
}
|
||||
if (mid != start)
|
||||
flag=_mi_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len,
|
||||
flag=ha_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len,
|
||||
comp_flag,¬_used);
|
||||
if (flag < 0)
|
||||
start++; /* point at next, bigger key */
|
||||
|
@ -239,7 +239,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
|
|||
length,page,end));
|
||||
DBUG_RETURN(MI_FOUND_WRONG_KEY);
|
||||
}
|
||||
if ((flag=_mi_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag,
|
||||
if ((flag=ha_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag,
|
||||
¬_used)) >= 0)
|
||||
break;
|
||||
#ifdef EXTRA_DEBUG
|
||||
|
@ -262,7 +262,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
|
|||
{
|
||||
/* my_flag is raw comparison result to be changed according to
|
||||
SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
|
||||
flag is the value returned by _mi_key_cmp and as treated as final */
|
||||
flag is the value returned by ha_key_cmp and as treated as final */
|
||||
int flag=0, my_flag=-1;
|
||||
uint nod_flag, length, len, matched, cmplen, kseg_len;
|
||||
uint prefix_len,suffix_len;
|
||||
|
@ -351,7 +351,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
|
|||
DBUG_PRINT("loop",("page: '%.*s%.*s'",prefix_len,t_buff+seg_len_pack,suffix_len,vseg));
|
||||
{
|
||||
uchar *from=vseg+suffix_len;
|
||||
MI_KEYSEG *keyseg;
|
||||
HA_KEYSEG *keyseg;
|
||||
uint l;
|
||||
|
||||
for (keyseg=keyinfo->seg+1 ; keyseg->type ; keyseg++ )
|
||||
|
@ -423,7 +423,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
|
|||
else if (key_len_left>0)
|
||||
{
|
||||
uint not_used;
|
||||
if ((flag = _mi_key_cmp(keyinfo->seg+1,vseg,
|
||||
if ((flag = ha_key_cmp(keyinfo->seg+1,vseg,
|
||||
k,key_len_left,nextflag,¬_used)) >= 0)
|
||||
break;
|
||||
}
|
||||
|
@ -651,389 +651,6 @@ void _mi_dpointer(MI_INFO *info, uchar *buff, my_off_t pos)
|
|||
} /* _mi_dpointer */
|
||||
|
||||
|
||||
int _mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
|
||||
uchar *b, uint b_length, my_bool part_key)
|
||||
{
|
||||
int flag;
|
||||
|
||||
#ifdef USE_STRCOLL
|
||||
if (use_strcoll(charset_info))
|
||||
{
|
||||
if (part_key && b_length < a_length)
|
||||
a_length=b_length;
|
||||
return my_strnncoll(charset_info, a, a_length, b, b_length);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
uint length= min(a_length,b_length);
|
||||
uchar *end= a+ length;
|
||||
uchar *sort_order=charset_info->sort_order;
|
||||
while (a < end)
|
||||
if ((flag= (int) sort_order[*a++] - (int) sort_order[*b++]))
|
||||
return flag;
|
||||
}
|
||||
if (part_key && b_length < a_length)
|
||||
return 0;
|
||||
return (int) (a_length-b_length);
|
||||
}
|
||||
|
||||
|
||||
static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
|
||||
my_bool part_key)
|
||||
{
|
||||
uint length= min(a_length,b_length);
|
||||
uchar *end= a+ length;
|
||||
int flag;
|
||||
|
||||
while (a < end)
|
||||
if ((flag= (int) *a++ - (int) *b++))
|
||||
return flag;
|
||||
if (part_key && b_length < a_length)
|
||||
return 0;
|
||||
return (int) (a_length-b_length);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Compare two keys
|
||||
** Returns <0, 0, >0 acording to which is bigger
|
||||
** Key_length specifies length of key to use. Number-keys can't
|
||||
** be splited
|
||||
** If flag <> SEARCH_FIND compare also position
|
||||
*/
|
||||
|
||||
#define FCMP(A,B) ((int) (A) - (int) (B))
|
||||
|
||||
int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
|
||||
register uchar *b, uint key_length, uint nextflag,
|
||||
uint *diff_pos)
|
||||
{
|
||||
int flag;
|
||||
int16 s_1,s_2;
|
||||
int32 l_1,l_2;
|
||||
uint32 u_1,u_2;
|
||||
float f_1,f_2;
|
||||
double d_1,d_2;
|
||||
uint next_key_length;
|
||||
|
||||
*diff_pos=0;
|
||||
for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
|
||||
{
|
||||
uchar *end;
|
||||
uint piks=! (keyseg->flag & HA_NO_SORT);
|
||||
(*diff_pos)++;
|
||||
|
||||
/* Handle NULL part */
|
||||
if (keyseg->null_bit)
|
||||
{
|
||||
key_length--;
|
||||
if (*a != *b && piks)
|
||||
{
|
||||
flag = (int) *a - (int) *b;
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
}
|
||||
b++;
|
||||
if (!*a++) /* If key was NULL */
|
||||
{
|
||||
if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
|
||||
nextflag=SEARCH_SAME; /* Allow duplicate keys */
|
||||
next_key_length=key_length;
|
||||
continue; /* To next key part */
|
||||
}
|
||||
}
|
||||
end= a+ min(keyseg->length,key_length);
|
||||
next_key_length=key_length-keyseg->length;
|
||||
|
||||
switch ((enum ha_base_keytype) keyseg->type) {
|
||||
case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
|
||||
if (keyseg->flag & HA_SPACE_PACK)
|
||||
{
|
||||
int a_length,b_length,pack_length;
|
||||
get_key_length(a_length,a);
|
||||
get_key_pack_length(b_length,pack_length,b);
|
||||
next_key_length=key_length-b_length-pack_length;
|
||||
|
||||
if (piks &&
|
||||
(flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a+=a_length;
|
||||
b+=b_length;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint length=(uint) (end-a), a_length=length, b_length=length;
|
||||
if (!(nextflag & SEARCH_PREFIX))
|
||||
{
|
||||
while (a_length && a[a_length-1] == ' ')
|
||||
a_length--;
|
||||
while (b_length && b[b_length-1] == ' ')
|
||||
b_length--;
|
||||
}
|
||||
if (piks &&
|
||||
(flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a=end;
|
||||
b+=length;
|
||||
}
|
||||
break;
|
||||
case HA_KEYTYPE_BINARY:
|
||||
if (keyseg->flag & HA_SPACE_PACK)
|
||||
{
|
||||
int a_length,b_length,pack_length;
|
||||
get_key_length(a_length,a);
|
||||
get_key_pack_length(b_length,pack_length,b);
|
||||
next_key_length=key_length-b_length-pack_length;
|
||||
|
||||
if (piks &&
|
||||
(flag=compare_bin(a,a_length,b,b_length,
|
||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a+=a_length;
|
||||
b+=b_length;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint length=keyseg->length;
|
||||
if (piks &&
|
||||
(flag=compare_bin(a,length,b,length,
|
||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a+=length;
|
||||
b+=length;
|
||||
}
|
||||
break;
|
||||
case HA_KEYTYPE_VARTEXT:
|
||||
{
|
||||
int a_length,b_length,pack_length;
|
||||
get_key_length(a_length,a);
|
||||
get_key_pack_length(b_length,pack_length,b);
|
||||
next_key_length=key_length-b_length-pack_length;
|
||||
|
||||
if (piks &&
|
||||
(flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a+=a_length;
|
||||
b+=b_length;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HA_KEYTYPE_VARBINARY:
|
||||
{
|
||||
int a_length,b_length,pack_length;
|
||||
get_key_length(a_length,a);
|
||||
get_key_pack_length(b_length,pack_length,b);
|
||||
next_key_length=key_length-b_length-pack_length;
|
||||
|
||||
if (piks &&
|
||||
(flag=compare_bin(a,a_length,b,b_length,
|
||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a+=a_length;
|
||||
b+=b_length;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HA_KEYTYPE_INT8:
|
||||
{
|
||||
int i_1= (int) *((signed char*) a);
|
||||
int i_2= (int) *((signed char*) b);
|
||||
if (piks && (flag = CMP_NUM(i_1,i_2)))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a= end;
|
||||
b++;
|
||||
break;
|
||||
}
|
||||
case HA_KEYTYPE_SHORT_INT:
|
||||
s_1= mi_sint2korr(a);
|
||||
s_2= mi_sint2korr(b);
|
||||
if (piks && (flag = CMP_NUM(s_1,s_2)))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a= end;
|
||||
b+= 2; /* sizeof(short int); */
|
||||
break;
|
||||
case HA_KEYTYPE_USHORT_INT:
|
||||
{
|
||||
uint16 us_1,us_2;
|
||||
us_1= mi_sint2korr(a);
|
||||
us_2= mi_sint2korr(b);
|
||||
if (piks && (flag = CMP_NUM(us_1,us_2)))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a= end;
|
||||
b+=2; /* sizeof(short int); */
|
||||
break;
|
||||
}
|
||||
case HA_KEYTYPE_LONG_INT:
|
||||
l_1= mi_sint4korr(a);
|
||||
l_2= mi_sint4korr(b);
|
||||
if (piks && (flag = CMP_NUM(l_1,l_2)))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a= end;
|
||||
b+= 4; /* sizeof(long int); */
|
||||
break;
|
||||
case HA_KEYTYPE_ULONG_INT:
|
||||
u_1= mi_sint4korr(a);
|
||||
u_2= mi_sint4korr(b);
|
||||
if (piks && (flag = CMP_NUM(u_1,u_2)))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a= end;
|
||||
b+= 4; /* sizeof(long int); */
|
||||
break;
|
||||
case HA_KEYTYPE_INT24:
|
||||
l_1=mi_sint3korr(a);
|
||||
l_2=mi_sint3korr(b);
|
||||
if (piks && (flag = CMP_NUM(l_1,l_2)))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a= end;
|
||||
b+= 3;
|
||||
break;
|
||||
case HA_KEYTYPE_UINT24:
|
||||
l_1=mi_uint3korr(a);
|
||||
l_2=mi_uint3korr(b);
|
||||
if (piks && (flag = CMP_NUM(l_1,l_2)))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a= end;
|
||||
b+= 3;
|
||||
break;
|
||||
case HA_KEYTYPE_FLOAT:
|
||||
mi_float4get(f_1,a);
|
||||
mi_float4get(f_2,b);
|
||||
if (piks && (flag = CMP_NUM(f_1,f_2)))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a= end;
|
||||
b+= 4; /* sizeof(float); */
|
||||
break;
|
||||
case HA_KEYTYPE_DOUBLE:
|
||||
mi_float8get(d_1,a);
|
||||
mi_float8get(d_2,b);
|
||||
if (piks && (flag = CMP_NUM(d_1,d_2)))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a= end;
|
||||
b+= 8; /* sizeof(double); */
|
||||
break;
|
||||
case HA_KEYTYPE_NUM: /* Numeric key */
|
||||
{
|
||||
int swap_flag= 0;
|
||||
int alength,blength;
|
||||
|
||||
if (keyseg->flag & HA_REVERSE_SORT)
|
||||
{
|
||||
swap(uchar*,a,b);
|
||||
swap_flag=1; /* Remember swap of a & b */
|
||||
end= a+ (int) (end-b);
|
||||
}
|
||||
if (keyseg->flag & HA_SPACE_PACK)
|
||||
{
|
||||
alength= *a++; blength= *b++;
|
||||
end=a+alength;
|
||||
next_key_length=key_length-blength-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
alength= (int) (end-a);
|
||||
blength=keyseg->length;
|
||||
/* remove pre space from keys */
|
||||
for ( ; alength && *a == ' ' ; a++, alength--) ;
|
||||
for ( ; blength && *b == ' ' ; b++, blength--) ;
|
||||
}
|
||||
if (piks)
|
||||
{
|
||||
if (*a == '-')
|
||||
{
|
||||
if (*b != '-')
|
||||
return -1;
|
||||
a++; b++;
|
||||
swap(uchar*,a,b);
|
||||
swap(int,alength,blength);
|
||||
swap_flag=1-swap_flag;
|
||||
alength--; blength--;
|
||||
end=a+alength;
|
||||
}
|
||||
else if (*b == '-')
|
||||
return 1;
|
||||
while (alength && (*a == '+' || *a == '0'))
|
||||
{
|
||||
a++; alength--;
|
||||
}
|
||||
while (blength && (*b == '+' || *b == '0'))
|
||||
{
|
||||
b++; blength--;
|
||||
}
|
||||
if (alength != blength)
|
||||
return (alength < blength) ? -1 : 1;
|
||||
while (a < end)
|
||||
if (*a++ != *b++)
|
||||
return ((int) a[-1] - (int) b[-1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
b+=(end-a);
|
||||
a=end;
|
||||
}
|
||||
|
||||
if (swap_flag) /* Restore pointers */
|
||||
swap(uchar*,a,b);
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_LONG_LONG
|
||||
case HA_KEYTYPE_LONGLONG:
|
||||
{
|
||||
longlong ll_a,ll_b;
|
||||
ll_a= mi_sint8korr(a);
|
||||
ll_b= mi_sint8korr(b);
|
||||
if (piks && (flag = CMP_NUM(ll_a,ll_b)))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a= end;
|
||||
b+= 8;
|
||||
break;
|
||||
}
|
||||
case HA_KEYTYPE_ULONGLONG:
|
||||
{
|
||||
ulonglong ll_a,ll_b;
|
||||
ll_a= mi_uint8korr(a);
|
||||
ll_b= mi_uint8korr(b);
|
||||
if (piks && (flag = CMP_NUM(ll_a,ll_b)))
|
||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||
a= end;
|
||||
b+= 8;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case HA_KEYTYPE_END: /* Ready */
|
||||
goto end; /* diff_pos is incremented */
|
||||
}
|
||||
}
|
||||
(*diff_pos)++;
|
||||
end:
|
||||
if (!(nextflag & SEARCH_FIND))
|
||||
{
|
||||
uint i;
|
||||
if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
|
||||
return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
|
||||
flag=0;
|
||||
for (i=keyseg->length ; i-- > 0 ; )
|
||||
{
|
||||
if (*a++ != *b++)
|
||||
{
|
||||
flag= FCMP(a[-1],b[-1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nextflag & SEARCH_SAME)
|
||||
return (flag); /* read same */
|
||||
if (nextflag & SEARCH_BIGGER)
|
||||
return (flag <= 0 ? -1 : 1); /* read next */
|
||||
return (flag < 0 ? -1 : 1); /* read previous */
|
||||
}
|
||||
return 0;
|
||||
} /* _mi_key_cmp */
|
||||
|
||||
|
||||
/* Get key from key-block */
|
||||
/* page points at previous key; its advanced to point at next key */
|
||||
/* key should contain previous key */
|
||||
|
@ -1057,7 +674,7 @@ uint _mi_get_static_key(register MI_KEYDEF *keyinfo, uint nod_flag,
|
|||
uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
|
||||
register uchar **page_pos, register uchar *key)
|
||||
{
|
||||
reg1 MI_KEYSEG *keyseg;
|
||||
reg1 HA_KEYSEG *keyseg;
|
||||
uchar *start_key,*page=*page_pos;
|
||||
uint length;
|
||||
|
||||
|
@ -1190,7 +807,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
|
|||
uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
|
||||
register uchar **page_pos, register uchar *key)
|
||||
{
|
||||
reg1 MI_KEYSEG *keyseg;
|
||||
reg1 HA_KEYSEG *keyseg;
|
||||
uchar *start_key,*page=*page_pos,*page_end,*from,*from_end;
|
||||
uint length,tmp;
|
||||
|
||||
|
@ -1389,7 +1006,7 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
|
|||
|
||||
uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
|
||||
{
|
||||
reg1 MI_KEYSEG *keyseg;
|
||||
reg1 HA_KEYSEG *keyseg;
|
||||
uchar *start;
|
||||
|
||||
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
|
||||
|
@ -1655,7 +1272,7 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
|
|||
uchar *org_key, uchar *prev_key, uchar *key,
|
||||
MI_KEY_PARAM *s_temp)
|
||||
{
|
||||
reg1 MI_KEYSEG *keyseg;
|
||||
reg1 HA_KEYSEG *keyseg;
|
||||
int length;
|
||||
uint key_length,ref_length,org_key_length=0,
|
||||
length_pack,new_key_length,diff_flag,pack_marker;
|
||||
|
|
|
@ -51,7 +51,8 @@ uint NEAR myisam_read_vec[]=
|
|||
{
|
||||
SEARCH_FIND, SEARCH_FIND | SEARCH_BIGGER, SEARCH_FIND | SEARCH_SMALLER,
|
||||
SEARCH_NO_FIND | SEARCH_BIGGER, SEARCH_NO_FIND | SEARCH_SMALLER,
|
||||
SEARCH_FIND | SEARCH_PREFIX, SEARCH_LAST
|
||||
SEARCH_FIND | SEARCH_PREFIX, SEARCH_LAST,
|
||||
MBR_CONTAIN, MBR_INTERSECT, MBR_WITHIN, MBR_DISJOINT, MBR_EQUAL
|
||||
};
|
||||
|
||||
uint NEAR myisam_readnext_vec[]=
|
||||
|
|
|
@ -36,8 +36,8 @@ static my_bool key_cacheing, null_fields, silent, skip_update, opt_unique,
|
|||
verbose;
|
||||
static MI_COLUMNDEF recinfo[4];
|
||||
static MI_KEYDEF keyinfo[10];
|
||||
static MI_KEYSEG keyseg[10];
|
||||
static MI_KEYSEG uniqueseg[10];
|
||||
static HA_KEYSEG keyseg[10];
|
||||
static HA_KEYSEG uniqueseg[10];
|
||||
|
||||
static int run_test(const char *filename);
|
||||
static void get_options(int argc, char *argv[]);
|
||||
|
@ -92,6 +92,7 @@ int run_test(const char *filename)
|
|||
/* Define a key over the first column */
|
||||
keyinfo[0].seg=keyseg;
|
||||
keyinfo[0].keysegs=1;
|
||||
keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
|
||||
keyinfo[0].seg[0].type= key_type;
|
||||
keyinfo[0].seg[0].flag= pack_seg;
|
||||
keyinfo[0].seg[0].start=1;
|
||||
|
@ -460,19 +461,19 @@ static void update_record(char *record)
|
|||
ptr=blob_key;
|
||||
memcpy_fixed(pos+4,&ptr,sizeof(char*)); /* Store pointer to new key */
|
||||
if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
|
||||
casedn(blob_key,length);
|
||||
my_casedn(default_charset_info,blob_key,length);
|
||||
pos+=recinfo[1].length;
|
||||
}
|
||||
else if (recinfo[1].type == FIELD_VARCHAR)
|
||||
{
|
||||
uint length=uint2korr(pos);
|
||||
casedn(pos+2,length);
|
||||
my_casedn(default_charset_info,pos+2,length);
|
||||
pos+=recinfo[1].length;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
|
||||
casedn(pos,keyinfo[0].seg[0].length);
|
||||
my_casedn(default_charset_info,pos,keyinfo[0].seg[0].length);
|
||||
pos+=recinfo[1].length;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ static uint use_blob=0;
|
|||
static uint16 key1[1001],key3[5000];
|
||||
static char record[300],record2[300],key[100],key2[100],
|
||||
read_record[300],read_record2[300],read_record3[300];
|
||||
static MI_KEYSEG glob_keyseg[MYISAM_KEYS][MAX_PARTS];
|
||||
static HA_KEYSEG glob_keyseg[MYISAM_KEYS][MAX_PARTS];
|
||||
|
||||
/* Test program */
|
||||
|
||||
|
@ -91,6 +91,7 @@ int main(int argc, char *argv[])
|
|||
keyinfo[0].seg[0].flag=(uint8) pack_seg;
|
||||
keyinfo[0].seg[0].null_bit=0;
|
||||
keyinfo[0].seg[0].null_pos=0;
|
||||
keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
|
||||
keyinfo[0].keysegs=1;
|
||||
keyinfo[0].flag = pack_type;
|
||||
keyinfo[1].seg= &glob_keyseg[1][0];
|
||||
|
@ -106,6 +107,7 @@ int main(int argc, char *argv[])
|
|||
keyinfo[1].seg[1].flag=HA_REVERSE_SORT;
|
||||
keyinfo[1].seg[1].null_bit=0;
|
||||
keyinfo[1].seg[1].null_pos=0;
|
||||
keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
|
||||
keyinfo[1].keysegs=2;
|
||||
keyinfo[1].flag =0;
|
||||
keyinfo[2].seg= &glob_keyseg[2][0];
|
||||
|
@ -115,6 +117,7 @@ int main(int argc, char *argv[])
|
|||
keyinfo[2].seg[0].flag=HA_REVERSE_SORT;
|
||||
keyinfo[2].seg[0].null_bit=0;
|
||||
keyinfo[2].seg[0].null_pos=0;
|
||||
keyinfo[2].key_alg=HA_KEY_ALG_BTREE;
|
||||
keyinfo[2].keysegs=1;
|
||||
keyinfo[2].flag =HA_NOSAME;
|
||||
keyinfo[3].seg= &glob_keyseg[3][0];
|
||||
|
@ -125,6 +128,7 @@ int main(int argc, char *argv[])
|
|||
keyinfo[3].seg[0].flag=(uint8) pack_seg;
|
||||
keyinfo[3].seg[0].null_bit=0;
|
||||
keyinfo[3].seg[0].null_pos=0;
|
||||
keyinfo[3].key_alg=HA_KEY_ALG_BTREE;
|
||||
keyinfo[3].keysegs=1;
|
||||
keyinfo[3].flag = pack_type;
|
||||
keyinfo[4].seg= &glob_keyseg[4][0];
|
||||
|
@ -135,6 +139,7 @@ int main(int argc, char *argv[])
|
|||
keyinfo[4].seg[0].flag=0;
|
||||
keyinfo[4].seg[0].null_bit=0;
|
||||
keyinfo[4].seg[0].null_pos=0;
|
||||
keyinfo[4].key_alg=HA_KEY_ALG_BTREE;
|
||||
keyinfo[4].keysegs=1;
|
||||
keyinfo[4].flag = pack_type;
|
||||
keyinfo[5].seg= &glob_keyseg[5][0];
|
||||
|
@ -145,6 +150,7 @@ int main(int argc, char *argv[])
|
|||
keyinfo[5].seg[0].flag=pack_seg;
|
||||
keyinfo[5].seg[0].null_bit=0;
|
||||
keyinfo[5].seg[0].null_pos=0;
|
||||
keyinfo[5].key_alg=HA_KEY_ALG_BTREE;
|
||||
keyinfo[5].keysegs=1;
|
||||
keyinfo[5].flag = pack_type;
|
||||
|
||||
|
@ -1013,7 +1019,7 @@ static void put_blob_in_record(char *blob_pos, char **blob_buffer)
|
|||
|
||||
static void copy_key(MI_INFO *info,uint inx,uchar *rec,uchar *key_buff)
|
||||
{
|
||||
MI_KEYSEG *keyseg;
|
||||
HA_KEYSEG *keyseg;
|
||||
|
||||
for (keyseg=info->s->keyinfo[inx].seg ; keyseg->type ; keyseg++)
|
||||
{
|
||||
|
|
|
@ -59,7 +59,7 @@ int main(int argc,char **argv)
|
|||
uint i=0;
|
||||
MI_KEYDEF keyinfo[10];
|
||||
MI_COLUMNDEF recinfo[10];
|
||||
MI_KEYSEG keyseg[10][2];
|
||||
HA_KEYSEG keyseg[10][2];
|
||||
MY_INIT(argv[0]);
|
||||
get_options(argc,argv);
|
||||
|
||||
|
@ -70,6 +70,7 @@ int main(int argc,char **argv)
|
|||
keyinfo[0].seg[0].length=8;
|
||||
keyinfo[0].seg[0].type=HA_KEYTYPE_TEXT;
|
||||
keyinfo[0].seg[0].flag=HA_SPACE_PACK;
|
||||
keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
|
||||
keyinfo[0].keysegs=1;
|
||||
keyinfo[0].flag = (uint8) HA_PACK_KEY;
|
||||
keyinfo[1].seg= &keyseg[1][0];
|
||||
|
@ -77,6 +78,7 @@ int main(int argc,char **argv)
|
|||
keyinfo[1].seg[0].length=4; /* Long is always 4 in myisam */
|
||||
keyinfo[1].seg[0].type=HA_KEYTYPE_LONG_INT;
|
||||
keyinfo[1].seg[0].flag=0;
|
||||
keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
|
||||
keyinfo[1].keysegs=1;
|
||||
keyinfo[1].flag =HA_NOSAME;
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
|
|||
{
|
||||
const byte *pos, *end;
|
||||
ha_checksum crc=0;
|
||||
MI_KEYSEG *keyseg;
|
||||
HA_KEYSEG *keyseg;
|
||||
|
||||
for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
|
||||
{
|
||||
|
@ -99,11 +99,20 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
|
|||
end= pos+length;
|
||||
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
|
||||
{
|
||||
uchar *sort_order=keyseg->charset->sort_order;
|
||||
while (pos != end)
|
||||
crc=((crc << 8) +
|
||||
(((uchar) sort_order[*(uchar*) pos++]))) +
|
||||
(crc >> (8*sizeof(ha_checksum)-8));
|
||||
if (keyseg->charset->hash_sort)
|
||||
{
|
||||
ulong nr=1, nr2=4;
|
||||
keyseg->charset->hash_sort(keyseg->charset,(const uchar*)pos,length,&nr, &nr2);
|
||||
crc=nr;
|
||||
}
|
||||
else
|
||||
{
|
||||
uchar *sort_order=keyseg->charset->sort_order;
|
||||
while (pos != end)
|
||||
crc=((crc << 8) +
|
||||
(((uchar) sort_order[*(uchar*) pos++]))) +
|
||||
(crc >> (8*sizeof(ha_checksum)-8));
|
||||
}
|
||||
}
|
||||
else
|
||||
while (pos != end)
|
||||
|
@ -122,7 +131,7 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
|
|||
my_bool null_are_equal)
|
||||
{
|
||||
const byte *pos_a, *pos_b, *end;
|
||||
MI_KEYSEG *keyseg;
|
||||
HA_KEYSEG *keyseg;
|
||||
|
||||
for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
|
||||
{
|
||||
|
@ -172,8 +181,8 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
|
|||
}
|
||||
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
|
||||
{
|
||||
if (_mi_compare_text(keyseg->charset, (uchar *)pos_a, length,
|
||||
(uchar *)pos_b, length, 0))
|
||||
if (mi_compare_text(keyseg->charset, (uchar *) pos_a, length,
|
||||
(uchar *) pos_b, length, 0))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
/* Update an old row in a MyISAM table */
|
||||
|
||||
#include "fulltext.h"
|
||||
#include "rt_index.h"
|
||||
|
||||
#ifdef __WIN__
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
@ -61,6 +63,7 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
|
|||
goto err_end; /* Record has changed */
|
||||
}
|
||||
|
||||
|
||||
/* Calculate and check all unique constraints */
|
||||
key_changed=0;
|
||||
for (i=0 ; i < share->state.header.uniques ; i++)
|
||||
|
@ -111,8 +114,8 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
|
|||
key_changed|=HA_STATE_WRITTEN; /* Mark that keyfile changed */
|
||||
changed|=((ulonglong) 1 << i);
|
||||
share->keyinfo[i].version++;
|
||||
if (_mi_ck_delete(info,i,old_key,old_length)) goto err;
|
||||
if (_mi_ck_write(info,i,new_key,new_length)) goto err;
|
||||
if (share->keyinfo[i].ck_delete(info,i,old_key,old_length)) goto err;
|
||||
if (share->keyinfo[i].ck_insert(info,i,new_key,new_length)) goto err;
|
||||
if (share->base.auto_key == i+1)
|
||||
auto_key_changed=1;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
/* Write a row to a MyISAM table */
|
||||
|
||||
#include "fulltext.h"
|
||||
#include "rt_index.h"
|
||||
|
||||
#ifdef __WIN__
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
@ -121,17 +123,17 @@ int mi_write(MI_INFO *info, byte *record)
|
|||
}
|
||||
else
|
||||
{
|
||||
uint key_length=_mi_make_key(info,i,buff,record,filepos);
|
||||
if (_mi_ck_write(info,i,buff,key_length))
|
||||
{
|
||||
if (local_lock_tree)
|
||||
rw_unlock(&share->key_root_lock[i]);
|
||||
DBUG_PRINT("error",("Got error: %d on write",my_errno));
|
||||
goto err;
|
||||
}
|
||||
if (share->keyinfo[i].ck_insert(info,i,buff,
|
||||
_mi_make_key(info,i,buff,record,filepos)))
|
||||
{
|
||||
if (local_lock_tree)
|
||||
rw_unlock(&share->key_root_lock[i]);
|
||||
DBUG_PRINT("error",("Got error: %d on write",my_errno));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (local_lock_tree)
|
||||
rw_unlock(&share->key_root_lock[i]);
|
||||
rw_unlock(&share->key_root_lock[i]);
|
||||
}
|
||||
}
|
||||
if (share->calc_checksum)
|
||||
|
@ -751,7 +753,8 @@ int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key,
|
|||
DBUG_ENTER("_mi_ck_write_tree");
|
||||
|
||||
error= tree_insert(&info->bulk_insert[keynr], key,
|
||||
key_length + info->s->rec_reflength) ? 0 : HA_ERR_OUT_OF_MEM ;
|
||||
key_length + info->s->rec_reflength,
|
||||
info->bulk_insert[keynr].custom_arg) ? 0 : HA_ERR_OUT_OF_MEM ;
|
||||
|
||||
DBUG_RETURN(error);
|
||||
} /* _mi_ck_write_tree */
|
||||
|
@ -762,7 +765,7 @@ int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key,
|
|||
static int keys_compare(bulk_insert_param *param, uchar *key1, uchar *key2)
|
||||
{
|
||||
uint not_used;
|
||||
return _mi_key_cmp(param->info->s->keyinfo[param->keynr].seg,
|
||||
return ha_key_cmp(param->info->s->keyinfo[param->keynr].seg,
|
||||
key1, key2, USE_WHOLE_KEY, SEARCH_SAME,
|
||||
¬_used);
|
||||
}
|
||||
|
|
|
@ -1107,7 +1107,7 @@ static void descript(MI_CHECK *param, register MI_INFO *info, my_string name)
|
|||
{
|
||||
uint key,keyseg_nr,field,start;
|
||||
reg3 MI_KEYDEF *keyinfo;
|
||||
reg2 MI_KEYSEG *keyseg;
|
||||
reg2 HA_KEYSEG *keyseg;
|
||||
reg4 const char *text;
|
||||
char buff[160],length[10],*pos,*end;
|
||||
enum en_fieldtype type;
|
||||
|
|
|
@ -96,7 +96,7 @@ typedef struct st_mi_state_info
|
|||
#define MI_STATE_EXTRA_SIZE ((MI_MAX_KEY+MI_MAX_KEY_BLOCK_SIZE)*MI_STATE_KEY_SIZE + MI_MAX_KEY*MI_MAX_KEY_SEG*MI_STATE_KEYSEG_SIZE)
|
||||
#define MI_KEYDEF_SIZE (2+ 5*2)
|
||||
#define MI_UNIQUEDEF_SIZE (2+1+1)
|
||||
#define MI_KEYSEG_SIZE (6+ 2*2 + 4*2)
|
||||
#define HA_KEYSEG_SIZE (6+ 2*2 + 4*2)
|
||||
#define MI_COLUMNDEF_SIZE (2*3+1)
|
||||
#define MI_BASE_INFO_SIZE (5*8 + 8*4 + 4 + 4*2 + 16)
|
||||
#define MI_INDEX_BLOCK_MARGIN 16 /* Safety margin for .MYI tables */
|
||||
|
@ -156,7 +156,7 @@ typedef struct st_mi_isam_share { /* Shared between opens */
|
|||
MI_BASE_INFO base;
|
||||
MI_KEYDEF *keyinfo; /* Key definitions */
|
||||
MI_UNIQUEDEF *uniqueinfo; /* unique definitions */
|
||||
MI_KEYSEG *keyparts; /* key part info */
|
||||
HA_KEYSEG *keyparts; /* key part info */
|
||||
MI_COLUMNDEF *rec; /* Pointer to field information */
|
||||
MI_PACK pack; /* Data about packed records */
|
||||
MI_BLOB *blobs; /* Pointer to blobs */
|
||||
|
@ -251,6 +251,7 @@ struct st_myisam_info {
|
|||
int lastinx; /* Last used index */
|
||||
uint lastkey_length; /* Length of key in lastkey */
|
||||
uint last_rkey_length; /* Last length in mi_rkey() */
|
||||
enum ha_rkey_function last_key_func; /* CONTAIN, OVERLAP, etc */
|
||||
uint save_lastkey_length;
|
||||
int errkey; /* Got last error on this key */
|
||||
int lock_type; /* How database was locked */
|
||||
|
@ -270,6 +271,8 @@ struct st_myisam_info {
|
|||
#ifdef THREAD
|
||||
THR_LOCK_DATA lock;
|
||||
#endif
|
||||
uchar * rtree_recursion_state; /* For RTREE */
|
||||
int rtree_recursion_depth;
|
||||
};
|
||||
|
||||
|
||||
|
@ -324,13 +327,6 @@ struct st_myisam_info {
|
|||
{ *(key)=255; mi_int2store((key)+1,(length)); } \
|
||||
}
|
||||
|
||||
#define get_key_length(length,key) \
|
||||
{ if ((uchar) *(key) != 255) \
|
||||
length= (uint) (uchar) *((key)++); \
|
||||
else \
|
||||
{ length=mi_uint2korr((key)+1); (key)+=3; } \
|
||||
}
|
||||
|
||||
#define get_key_full_length(length,key) \
|
||||
{ if ((uchar) *(key) != 255) \
|
||||
length= ((uint) (uchar) *((key)++))+1; \
|
||||
|
@ -338,13 +334,6 @@ struct st_myisam_info {
|
|||
{ length=mi_uint2korr((key)+1)+3; (key)+=3; } \
|
||||
}
|
||||
|
||||
#define get_key_pack_length(length,length_pack,key) \
|
||||
{ if ((uchar) *(key) != 255) \
|
||||
{ length= (uint) (uchar) *((key)++); length_pack=1; }\
|
||||
else \
|
||||
{ length=mi_uint2korr((key)+1); (key)+=3; length_pack=3; } \
|
||||
}
|
||||
|
||||
#define get_pack_length(length) ((length) >= 255 ? 3 : 1)
|
||||
|
||||
#define MI_MIN_BLOCK_LENGTH 20 /* Because of delete-link */
|
||||
|
@ -365,7 +354,7 @@ struct st_myisam_info {
|
|||
#define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */
|
||||
#define PACK_TYPE_SPACE_FIELDS 2
|
||||
#define PACK_TYPE_ZERO_FILL 4
|
||||
#define MI_FOUND_WRONG_KEY 32738 /* Impossible value from _mi_key_cmp */
|
||||
#define MI_FOUND_WRONG_KEY 32738 /* Impossible value from ha_key_cmp */
|
||||
|
||||
#define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_MIN_KEY_BLOCK_LENGTH)
|
||||
#define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer) ((((key_length+data_pointer+key_pointer)*4+key_pointer+2)/myisam_block_size+1)*myisam_block_size)
|
||||
|
@ -482,14 +471,12 @@ extern int _mi_seq_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
|
|||
extern int _mi_prefix_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
|
||||
uchar *key,uint key_len,uint comp_flag,
|
||||
uchar **ret_pos,uchar *buff, my_bool *was_last_key);
|
||||
extern int _mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
|
||||
my_bool);
|
||||
extern my_off_t _mi_kpos(uint nod_flag,uchar *after_key);
|
||||
extern void _mi_kpointer(MI_INFO *info,uchar *buff,my_off_t pos);
|
||||
extern my_off_t _mi_dpos(MI_INFO *info, uint nod_flag,uchar *after_key);
|
||||
extern my_off_t _mi_rec_pos(MYISAM_SHARE *info, uchar *ptr);
|
||||
extern void _mi_dpointer(MI_INFO *info, uchar *buff,my_off_t pos);
|
||||
extern int _mi_key_cmp(MI_KEYSEG *keyseg, uchar *a,uchar *b,
|
||||
extern int ha_key_cmp(HA_KEYSEG *keyseg, uchar *a,uchar *b,
|
||||
uint key_length,uint nextflag,uint *diff_length);
|
||||
extern uint _mi_get_static_key(MI_KEYDEF *keyinfo,uint nod_flag,uchar * *page,
|
||||
uchar *key);
|
||||
|
@ -536,7 +523,7 @@ extern my_bool _mi_rec_check(MI_INFO *info,const char *record, byte *packpos);
|
|||
extern int _mi_write_part_record(MI_INFO *info,my_off_t filepos,ulong length,
|
||||
my_off_t next_filepos,byte **record,
|
||||
ulong *reclength,int *flag);
|
||||
extern void _mi_print_key(FILE *stream,MI_KEYSEG *keyseg,const uchar *key,
|
||||
extern void _mi_print_key(FILE *stream,HA_KEYSEG *keyseg,const uchar *key,
|
||||
uint length);
|
||||
extern my_bool _mi_read_pack_info(MI_INFO *info,pbool fix_keys);
|
||||
extern int _mi_read_pack_record(MI_INFO *info,my_off_t filepos,byte *buf);
|
||||
|
@ -627,8 +614,8 @@ char *mi_state_info_read(char *ptr, MI_STATE_INFO *state);
|
|||
uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead);
|
||||
uint mi_base_info_write(File file, MI_BASE_INFO *base);
|
||||
char *my_n_base_info_read(char *ptr, MI_BASE_INFO *base);
|
||||
int mi_keyseg_write(File file, const MI_KEYSEG *keyseg);
|
||||
char *mi_keyseg_read(char *ptr, MI_KEYSEG *keyseg);
|
||||
int mi_keyseg_write(File file, const HA_KEYSEG *keyseg);
|
||||
char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg);
|
||||
uint mi_keydef_write(File file, MI_KEYDEF *keydef);
|
||||
char *mi_keydef_read(char *ptr, MI_KEYDEF *keydef);
|
||||
uint mi_uniquedef_write(File file, MI_UNIQUEDEF *keydef);
|
||||
|
|
|
@ -345,7 +345,8 @@ static int examine_log(my_string file_name, char **table_names)
|
|||
if (!opt_processes)
|
||||
file_info.process=0;
|
||||
result= mi_uint2korr(head+7);
|
||||
if ((curr_file_info=(struct file_info*) tree_search(&tree,&file_info)))
|
||||
if ((curr_file_info=(struct file_info*) tree_search(&tree, &file_info,
|
||||
tree.custom_arg)))
|
||||
{
|
||||
curr_file_info->accessed=access_time;
|
||||
if (update && curr_file_info->used && curr_file_info->closed)
|
||||
|
@ -452,7 +453,7 @@ static int examine_log(my_string file_name, char **table_names)
|
|||
else
|
||||
file_info.isam->s->rnd= isamlog_process;
|
||||
}
|
||||
VOID(tree_insert(&tree,(gptr) &file_info,0));
|
||||
VOID(tree_insert(&tree, (gptr) &file_info, 0, tree.custom_arg));
|
||||
if (file_info.used)
|
||||
{
|
||||
if (verbose && !record_pos_file)
|
||||
|
@ -471,7 +472,7 @@ static int examine_log(my_string file_name, char **table_names)
|
|||
{
|
||||
if (!curr_file_info->closed)
|
||||
files_open--;
|
||||
VOID(tree_delete(&tree,(gptr) curr_file_info));
|
||||
VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
|
||||
}
|
||||
break;
|
||||
case MI_LOG_EXTRA:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue