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:
unknown 2002-10-02 17:55:12 +03:00
commit 95e772b656
370 changed files with 74781 additions and 5578 deletions

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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+

View file

@ -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

View file

@ -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

View file

@ -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));
}

View file

@ -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

View file

@ -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");

View file

@ -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));
}

View file

@ -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);
};

View file

@ -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])

View file

@ -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;

View file

@ -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,

View file

@ -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')

View file

@ -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))

View file

@ -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, &not_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;
}

View file

@ -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))
{

View file

@ -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

View file

@ -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)

View file

@ -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;

View file

@ -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);
}

View file

@ -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, &not_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;
}

View file

@ -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);
}

View file

@ -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))

View file

@ -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);
}

View file

@ -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:

View file

@ -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))))
{

View file

@ -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));
}
}

View file

@ -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);
}

View file

@ -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));
}
}

View file

@ -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 */

View file

@ -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)
{

View file

@ -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])

View file

@ -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);

View file

@ -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])
{

View file

@ -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)))

View file

@ -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");

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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
View 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 */

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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;

View file

@ -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:

View file

@ -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;

View file

@ -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; \

View file

@ -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

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -101,8 +101,8 @@ EXPORTS
mysql_rpl_probe
mysql_set_master
mysql_add_slave
mysql_warning_count
mysql_warnings

View file

@ -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);

View file

@ -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

View file

@ -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");

View file

@ -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
****************************************************************************/

View file

@ -7,6 +7,8 @@ ft_test1
mi_test1
mi_test2
mi_test3
rt_test
sp_test
myisamchk
myisamlog
myisampack

View file

@ -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

View file

@ -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;

View file

@ -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]++;

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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) */

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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, &not_used)) >=0)
(flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length,
comp_flag, &not_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,&not_used));
return (ha_key_cmp(sort_param->keyinfo->seg, *((uchar**) a), *((uchar**) b),
USE_WHOLE_KEY, SEARCH_SAME,&not_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++)

View file

@ -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;

View file

@ -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;

View file

@ -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;
}
}
}

View file

@ -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) {

View file

@ -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++;

View file

@ -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);
}

View file

@ -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)

View file

@ -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;
}
}
}
}

View file

@ -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, &not_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]);

View file

@ -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,
&not_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,&not_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,&not_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,
&not_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,&not_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;

View file

@ -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[]=

View file

@ -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;
}

View file

@ -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++)
{

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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,
&not_used);
}

View file

@ -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;

View file

@ -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);

View file

@ -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