Commit 65c4fdc0 authored by unknown's avatar unknown

merged


BitKeeper/etc/logging_ok:
  auto-union
configure.in:
  Auto merged
libmysqld/Makefile.am:
  Auto merged
myisam/Makefile.am:
  Auto merged
myisam/mi_check.c:
  Auto merged
myisam/myisampack.c:
  Auto merged
mysql-test/r/fulltext.result:
  Auto merged
mysys/Makefile.am:
  Auto merged
sql/Makefile.am:
  Auto merged
sql/sql_delete.cc:
  Auto merged
sql/sql_update.cc:
  Auto merged
strings/Makefile.am:
  Auto merged
parents 228bfb05 db85094b
......@@ -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
......@@ -6,8 +6,8 @@ path=`dirname $0`
extra_flags="$pentium_cflags $debug_cflags"
c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs $static_link"
extra_configs="$pentium_configs $debug_configs "
extra_configs="$extra_configs "
extra_configs="$extra_configs"
. "$path/FINISH.sh"
Administrador@light.
Administrator@co3064164-a.
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 +12,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
......@@ -47,12 +50,15 @@ monty@tramp.mysql.fi
monty@work.mysql.com
mwagner@cash.mwagner.org
mwagner@evoq.mwagner.org
mwagner@work.mysql.com
nick@mysql.com
nick@nick.leippe.com
paul@central.snake.net
paul@teton.kitebird.com
peter@linux.local
peter@mysql.com
ram@gw.udmsearch.izhnet.ru
ram@mysql.r18.ru
ram@ram.(none)
root@x3.internalnet
salle@geopard.(none)
......@@ -62,6 +68,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 +82,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,6 +90,3 @@ worm@altair.is.lan
zak@balfor.local
zak@linux.local
zgreant@mysql.com
tfr@beta.frontier86.ee
Administrador@light.
mwagner@work.mysql.com
......@@ -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+
......
......@@ -18,6 +18,9 @@
#undef CRAY_STACKSEG_END
/* Define the default charset name */
#undef DEFAULT_CHARSET_NAME
/* Version of .frm files */
#undef DOT_FRM_VERSION
......@@ -63,6 +66,43 @@
/* READLINE: */
#undef HAVE_BSD_SIGNALS
/* Define charsets you want */
#undef HAVE_CHARSET_armscii8
#undef HAVE_CHARSET_big5
#undef HAVE_CHARSET_cp1251
#undef HAVE_CHARSET_cp1257
#undef HAVE_CHARSET_croat
#undef HAVE_CHARSET_czech
#undef HAVE_CHARSET_danish
#undef HAVE_CHARSET_dec8
#undef HAVE_CHARSET_dos
#undef HAVE_CHARSET_estonia
#undef HAVE_CHARSET_euc_kr
#undef HAVE_CHARSET_gb2312
#undef HAVE_CHARSET_gbk
#undef HAVE_CHARSET_german1
#undef HAVE_CHARSET_greek
#undef HAVE_CHARSET_hebrew
#undef HAVE_CHARSET_hp8
#undef HAVE_CHARSET_hungarian
#undef HAVE_CHARSET_koi8_ru
#undef HAVE_CHARSET_koi8_ukr
#undef HAVE_CHARSET_latin1
#undef HAVE_CHARSET_latin1_de
#undef HAVE_CHARSET_latin2
#undef HAVE_CHARSET_latin5
#undef HAVE_CHARSET_sjis
#undef HAVE_CHARSET_swe7
#undef HAVE_CHARSET_tis620
#undef HAVE_CHARSET_ucs2
#undef HAVE_CHARSET_ujis
#undef HAVE_CHARSET_usa7
#undef HAVE_CHARSET_utf8
#undef HAVE_CHARSET_win1250
#undef HAVE_CHARSET_win1250ch
#undef HAVE_CHARSET_win1251ukr
#undef HAVE_CHARSET_win1251
/* ZLIB and compress: */
#undef HAVE_COMPRESS
......
......@@ -40,7 +40,7 @@
#include <signal.h>
#include <violite.h>
const char *VER= "12.15";
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
......@@ -872,14 +873,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
......@@ -891,7 +892,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))
......@@ -919,12 +921,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--;
......@@ -987,7 +990,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
......@@ -1363,9 +1366,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)
......@@ -1394,7 +1397,9 @@ 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_strnncoll(system_charset_info,
(const uchar*)buffer->ptr(),4,
(const uchar*)"SET ",4)))
{
(void) put_info("Ignoring query to other database",INFO_INFO);
return 0;
......@@ -1447,7 +1452,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
{
......@@ -1462,20 +1467,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);
......@@ -1772,8 +1787,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--;
......@@ -1833,7 +1849,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
{
......@@ -1852,11 +1868,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)
......@@ -1896,7 +1913,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
{
......@@ -1912,10 +1929,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);
......@@ -2051,7 +2069,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
......@@ -2097,15 +2115,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);
......@@ -2146,7 +2165,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
......@@ -2330,7 +2349,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);
......@@ -2439,7 +2458,7 @@ static void remove_cntrl(String &buffer)
{
char *start,*end;
end=(start=(char*) buffer.ptr())+buffer.length();
while (start < end && !isgraph(end[-1]))
while (start < end && !my_isgraph(system_charset_info,end[-1]))
end--;
buffer.length((uint) (end-start));
}
......
......@@ -518,7 +518,7 @@ static my_bool test_if_special_chars(const char *str)
{
#if MYSQL_VERSION_ID >= 32300
for ( ; *str ; str++)
if (!isvar(*str) && *str != '$')
if (!my_isvar(system_charset_info,*str) && *str != '$')
return 1;
#endif
return 0;
......@@ -1036,7 +1036,8 @@ static void dumpTable(uint numFields, char *table)
/* change any strings ("inf","nan",..) into NULL */
char *ptr = row[i];
dynstr_append(&extended_row,
(!isalpha(*ptr)) ? ptr : "NULL");
(!my_isalpha(system_charset_info,*ptr)) ?
ptr : "NULL");
}
}
else
......@@ -1068,9 +1069,11 @@ static void dumpTable(uint numFields, char *table)
char *ptr = row[i];
if (opt_xml)
fprintf(md_result_file, "\t\t<%s>%s</%s>\n",
field->name,!isalpha(*ptr) ?ptr: "NULL",field->name);
field->name,
!my_isalpha(system_charset_info,*ptr) ?ptr: "NULL",field->name);
else
fputs((!isalpha(*ptr)) ? ptr : "NULL", md_result_file);
fputs((!my_isalpha(system_charset_info,*ptr)) ?
ptr : "NULL", md_result_file);
}
}
else
......
......@@ -311,7 +311,7 @@ static int eval_result = 0;
void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
void mysql_disable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; }
int mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
#endif
#define MAX_SERVER_ARGS 20
......@@ -482,9 +482,9 @@ void init_parser()
int hex_val(int c)
{
if (isdigit(c))
if (my_isdigit(system_charset_info,c))
return c - '0';
else if ((c = tolower(c)) >= 'a' && c <= 'f')
else if ((c = my_tolower(system_charset_info,c)) >= 'a' && c <= 'f')
return c - 'a' + 10;
else
return -1;
......@@ -594,7 +594,7 @@ VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw,
{
const char* save_var_name = var_name, *end;
end = (var_name_end) ? *var_name_end : 0;
while (isvar(*var_name) && var_name != end)
while (my_isvar(system_charset_info,*var_name) && var_name != end)
++var_name;
if (var_name == save_var_name)
{
......@@ -757,7 +757,7 @@ int do_server_op(struct st_query* q,const char* op)
com_p=strmov(com_p,"_exec ");
if (!*p)
die("Missing server name in server_%s\n",op);
while (*p && !isspace(*p))
while (*p && !my_isspace(system_charset_info,*p))
{
*com_p++=*p++;
}
......@@ -790,7 +790,7 @@ int do_require_version(struct st_query* q)
if (!*p)
die("Missing version argument in require_version\n");
ver_arg = p;
while (*p && !isspace(*p))
while (*p && !my_isspace(system_charset_info,*p))
p++;
*p = 0;
ver_arg_len = p - ver_arg;
......@@ -820,7 +820,7 @@ int do_source(struct st_query* q)
if (!*p)
die("Missing file name in source\n");
name = p;
while (*p && !isspace(*p))
while (*p && !my_isspace(system_charset_info,*p))
p++;
*p = 0;
......@@ -1057,11 +1057,11 @@ int do_let(struct st_query* q)
if (!*p)
die("Missing variable name in let\n");
var_name = p;
while (*p && (*p != '=' || isspace(*p)))
while (*p && (*p != '=' || my_isspace(system_charset_info,*p)))
p++;
var_name_end = p;
if (*p == '=') p++;
while (*p && isspace(*p))
while (*p && my_isspace(system_charset_info,*p))
p++;
var_val_start = p;
return var_set(var_name, var_name_end, var_val_start, q->end);
......@@ -1090,8 +1090,8 @@ int do_disable_rpl_parse(struct st_query* q __attribute__((unused)))
int do_sleep(struct st_query* q, my_bool real_sleep)
{
char* p=q->first_argument;
while (*p && isspace(*p))
char *p=q->first_argument;
while (*p && my_isspace(system_charset_info,*p))
p++;
if (!*p)
die("Missing argument in sleep\n");
......@@ -1107,7 +1107,7 @@ static void get_file_name(char *filename, struct st_query* q)
char* p=q->first_argument;
strnmov(filename, p, FN_REFLEN);
/* Remove end space */
while (p > filename && isspace(p[-1]))
while (p > filename && my_isspace(system_charset_info,p[-1]))
p--;
p[0]=0;
}
......@@ -1193,7 +1193,7 @@ static char *get_string(char **to_ptr, char **from_ptr,
if (*from != ' ' && *from)
die("Wrong string argument in %s\n", q->query);
while (isspace(*from)) /* Point to next string */
while (my_isspace(system_charset_info,*from)) /* Point to next string */
from++;
*to =0; /* End of string marker */
......@@ -1250,8 +1250,8 @@ static void get_replace(struct st_query *q)
insert_pointer_name(&to_array,to);
}
for (i=1,pos=word_end_chars ; i < 256 ; i++)
if (isspace(i))
*pos++=i;
if (my_isspace(system_charset_info,i))
*pos++= i;
*pos=0; /* End pointer */
if (!(glob_replace=init_replace((char**) from_array.typelib.type_names,
(char**) to_array.typelib.type_names,
......@@ -1287,7 +1287,7 @@ int select_connection(char *p)
if (!*p)
die("Missing connection name in connect\n");
name = p;
while (*p && !isspace(*p))
while (*p && !my_isspace(system_charset_info,*p))
p++;
*p = 0;
......@@ -1313,7 +1313,7 @@ int close_connection(struct st_query* q)
if (!*p)
die("Missing connection name in connect\n");
name = p;
while (*p && !isspace(*p))
while (*p && !my_isspace(system_charset_info,*p))
p++;
*p = 0;
......@@ -1349,11 +1349,13 @@ int close_connection(struct st_query* q)
char* safe_get_param(char* str, char** arg, const char* msg)
{
DBUG_ENTER("safe_get_param");
while (*str && isspace(*str)) str++;
while (*str && my_isspace(system_charset_info,*str))
str++;
*arg = str;
for (; *str && *str != ',' && *str != ')' ; str++)
{
if (isspace(*str)) *str = 0;
if (my_isspace(system_charset_info,*str))
*str = 0;
}
if (!*str)
die(msg);
......@@ -1635,7 +1637,7 @@ int read_line(char* buf, int size)
{
state = R_COMMENT;
}
else if (isspace(c))
else if (my_isspace(system_charset_info,c))
{
if (c == '\n')
start_lineno= ++*lineno; /* Query hasn't started yet */
......@@ -1761,7 +1763,7 @@ int read_query(struct st_query** q_ptr)
{
expected_errno = 0;
p++;
for (;isdigit(*p);p++)
for (;my_isdigit(system_charset_info,*p);p++)
expected_errno = expected_errno * 10 + *p - '0';
q->expected_errno[0] = expected_errno;
q->expected_errno[1] = 0;
......@@ -1769,25 +1771,28 @@ int read_query(struct st_query** q_ptr)
}
}
while (*p && isspace(*p)) p++ ;
while (*p && my_isspace(system_charset_info,*p))
p++ ;
if (*p == '@')
{
p++;
p1 = q->record_file;
while (!isspace(*p) &&
while (!my_isspace(system_charset_info,*p) &&
p1 < q->record_file + sizeof(q->record_file) - 1)
*p1++ = *p++;
*p1 = 0;
}
}
while (*p && isspace(*p)) p++;
while (*p && my_isspace(system_charset_info,*p))
p++;
if (!(q->query_buf=q->query=my_strdup(p,MYF(MY_WME))))
die(NullS);
/* Calculate first word and first argument */
for (p=q->query; *p && !isspace(*p) ; p++) ;
for (p=q->query; *p && !my_isspace(system_charset_info,*p) ; p++) ;
q->first_word_len = (uint) (p - q->query);
while (*p && isspace(*p)) p++;
while (*p && my_isspace(system_charset_info,*p))
p++;
q->first_argument=p;
q->end = strend(q->query);
parser.read_lines++;
......@@ -2028,6 +2033,36 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
dynstr_append_mem(ds, val, len);
}
/*
Append all results to the dynamic string separated with '\t'
*/
static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
{
MYSQL_ROW row;
int num_fields= mysql_num_fields(res);
unsigned long *lengths;
while ((row = mysql_fetch_row(res)))
{
int i;
lengths = mysql_fetch_lengths(res);
for (i = 0; i < num_fields; i++)
{
const char *val= row[i];
ulonglong len= lengths[i];
if (!val)
{
val = "NULL";
len = 4;
}
if (i)
dynstr_append_mem(ds, "\t", 1);
replace_dynstr_append_mem(ds, val, len);
}
dynstr_append_mem(ds, "\n", 1);
}
}
/*
* flags control the phased/stages of query execution to be performed
......@@ -2038,12 +2073,7 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
int run_query(MYSQL* mysql, struct st_query* q, int flags)
{
MYSQL_RES* res = 0;
MYSQL_FIELD* fields;
MYSQL_ROW row;
int num_fields,i, error = 0;
unsigned long* lengths;
char* val;
int len;
int i, error = 0;
DYNAMIC_STRING *ds;
DYNAMIC_STRING ds_tmp;
DYNAMIC_STRING eval_query;
......@@ -2152,45 +2182,37 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
goto end;
}
if (!res)
goto end;
if (!disable_result_log)
if (!disable_result_log && res)
{
fields = mysql_fetch_fields(res);
num_fields = mysql_num_fields(res);
int num_fields= mysql_num_fields(res);
MYSQL_FIELD *fields= mysql_fetch_fields(res);
for (i = 0; i < num_fields; i++)
{
if (i)
dynstr_append_mem(ds, "\t", 1);
dynstr_append(ds, fields[i].name);
}
dynstr_append_mem(ds, "\n", 1);
append_result(ds, res);
}
while ((row = mysql_fetch_row(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
{
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);
dynstr_append_mem(ds, "Warnings:\n", 10);
append_result(ds, warn_res);
mysql_free_result(warn_res);
}
if (glob_replace)
free_replace();
}
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");
......
This diff is collapsed.
......@@ -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 @@ class String
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 @@ class String
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 @@ class String
}
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 @@ class String
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);
};
This diff is collapsed.
......@@ -157,7 +157,7 @@ static int get_answer(QUESTION_WIDGET* w)
char c;
if (!fgets(buf,sizeof(buf),w->in))
die("Failed fgets on input stream");
switch ((c=tolower(*buf)))
switch ((c=my_tolower(system_charset_info,*buf)))
{
case '\n':
return w->default_ind;
......
......@@ -113,7 +113,7 @@ char *argv[];
exit(1);
for (i=1,pos=word_end_chars ; i < 256 ; i++)
if (isspace(i))
if (my_isspace(system_charset_info,i))
*pos++=i;
*pos=0;
if (!(replace=init_replace((char**) from.typelib.type_names,
......
......@@ -175,9 +175,9 @@ trace dump and specify the path to it with -s or --symbols-file");
static uchar hex_val(char c)
{
uchar l;
if (isdigit(c))
if (my_isdigit(system_charset_info,c))
return c - '0';
l = tolower(c);
l = my_tolower(system_charset_info,c);
if (l < 'a' || l > 'f')
return HEX_INVALID;
return (uchar)10 + ((uchar)c - (uchar)'a');
......@@ -203,9 +203,11 @@ static int init_sym_entry(SYM_ENTRY* se, char* buf)
if (!se->addr)
return -1;
while (isspace(*buf++)) ;
while (my_isspace(system_charset_info,*buf++))
/* empty */;
while (isspace(*buf++)) ; /* skip more space */
while (my_isspace(system_charset_info,*buf++))
/* empty - skip more space */;
--buf;
/* now we are on the symbol */
for (p = se->symbol, p_end = se->symbol + sizeof(se->symbol) - 1;
......@@ -285,7 +287,8 @@ static void do_resolve()
while (fgets(buf, sizeof(buf), fp_dump))
{
p = buf;
while(isspace(*p))
/* skip space */
while (my_isspace(system_charset_info,*p))
++p;
if (*p++ == '0' && *p++ == 'x')
......
......@@ -122,7 +122,7 @@ int main(int argc, char **argv)
{
ip = *argv++;
if (isdigit(ip[0]))
if (my_isdigit(system_charset_info,ip[0]))
{
taddr = inet_addr(ip);
if (taddr == htonl(INADDR_BROADCAST))
......
......@@ -20,10 +20,12 @@
static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
ulong blength, my_bool print_status);
static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
my_bool print_status);
/* Returns 0 if the HEAP is ok */
int heap_check_heap(HP_INFO *info,my_bool print_status)
int heap_check_heap(HP_INFO *info, my_bool print_status)
{
int error;
uint key;
......@@ -31,8 +33,13 @@ int heap_check_heap(HP_INFO *info,my_bool print_status)
DBUG_ENTER("heap_check_keys");
for (error=key=0 ; key < share->keys ; key++)
error|=check_one_key(share->keydef+key,key, share->records,share->blength,
print_status);
{
if (share->keydef[key].algorithm == HA_KEY_ALG_BTREE)
error|= check_one_rb_key(info, key, share->records, print_status);
else
error|= check_one_key(share->keydef + key, key, share->records,
share->blength, print_status);
}
DBUG_RETURN(error);
}
......@@ -50,8 +57,8 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
for (i=found=max_links=seek=0 ; i < records ; i++)
{
hash_info=hp_find_hash(&keydef->block,i);
if (_hp_mask(_hp_rec_hashnr(keydef,hash_info->ptr_to_rec),
blength,records) == i)
if (hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
blength,records) == i)
{
found++;
seek++;
......@@ -59,8 +66,8 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
while ((hash_info=hash_info->next_key) && found < records + 1)
{
seek+= ++links;
if ((rec_link=_hp_mask(_hp_rec_hashnr(keydef,hash_info->ptr_to_rec),
blength,records))
if ((rec_link = hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
blength, records))
!= i)
{
DBUG_PRINT("error",("Record in wrong link: Link %d Record: %lx Record-link %d", i,hash_info->ptr_to_rec,rec_link));
......@@ -87,3 +94,46 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
(float) seek / (float) (records ? records : 1));
return error;
}
static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
my_bool print_status)
{
HP_KEYDEF *keydef= info->s->keydef + keynr;
int error= 0;
ulong found= 0;
byte *key, *recpos;
uint key_length;
uint not_used;
if ((key= tree_search_edge(&keydef->rb_tree, info->parents,
&info->last_pos, offsetof(TREE_ELEMENT, left))))
{
do
{
memcpy(&recpos, key + (*keydef->get_key_length)(keydef,key), sizeof(byte*));
key_length= hp_rb_make_key(keydef, info->recbuf, recpos, 0);
if (ha_key_cmp(keydef->seg, info->recbuf, key, key_length,
SEARCH_FIND | SEARCH_SAME, &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;
}
......@@ -19,9 +19,9 @@
#include "heapdef.h"
int _hp_rectest(register HP_INFO *info, register const byte *old)
int hp_rectest(register HP_INFO *info, register const byte *old)
{
DBUG_ENTER("_hp_rectest");
DBUG_ENTER("hp_rectest");
if (memcmp(info->current_ptr,old,(size_t) info->s->reclength))
{
......
......@@ -21,6 +21,7 @@
#include <my_pthread.h>
#endif
#include "heap.h" /* Structs & some defines */
#include "my_tree.h"
/* Some extern variables */
......@@ -29,10 +30,10 @@ extern LIST *heap_open_list,*heap_share_list;
#define test_active(info) \
if (!(info->update & HA_STATE_AKTIV))\
{ my_errno=HA_ERR_NO_ACTIVE_RECORD; DBUG_RETURN(-1); }
#define hp_find_hash(A,B) ((HASH_INFO*) _hp_find_block((A),(B)))
#define hp_find_hash(A,B) ((HASH_INFO*) hp_find_block((A),(B)))
/* Find pos for record and update it in info->current_ptr */
#define _hp_find_record(info,pos) (info)->current_ptr= _hp_find_block(&(info)->s->block,pos)
#define hp_find_record(info,pos) (info)->current_ptr= hp_find_block(&(info)->s->block,pos)
typedef struct st_hp_hash_info
{
......@@ -40,40 +41,52 @@ typedef struct st_hp_hash_info
byte *ptr_to_rec;
} HASH_INFO;
typedef struct {
HA_KEYSEG *keyseg;
uint key_length;
uint search_flag;
} heap_rb_param;
/* Prototypes for intern functions */
extern HP_SHARE *_hp_find_named_heap(const char *name);
extern int _hp_rectest(HP_INFO *info,const byte *old);
extern void _hp_delete_file_from_open_list(HP_INFO *info);
extern byte *_hp_find_block(HP_BLOCK *info,ulong pos);
extern int _hp_get_new_block(HP_BLOCK *info, ulong* alloc_length);
extern void _hp_free(HP_SHARE *info);
extern byte *_hp_free_level(HP_BLOCK *block,uint level,HP_PTRS *pos,
byte *last_pos);
extern int _hp_write_key(HP_SHARE *info,HP_KEYDEF *keyinfo,
const byte *record,byte *recpos);
extern int _hp_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
const byte *record,byte *recpos,int flag);
extern HP_SHARE *hp_find_named_heap(const char *name);
extern int hp_rectest(HP_INFO *info,const byte *old);
extern byte *hp_find_block(HP_BLOCK *info,ulong pos);
extern int hp_get_new_block(HP_BLOCK *info, ulong* alloc_length);
extern void hp_free(HP_SHARE *info);
extern byte *hp_free_level(HP_BLOCK *block,uint level,HP_PTRS *pos,
byte *last_pos);
extern int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
const byte *record, byte *recpos);
extern int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
const byte *record, byte *recpos);
extern int hp_rb_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
const byte *record,byte *recpos,int flag);
extern int hp_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
const byte *record,byte *recpos,int flag);
extern HASH_INFO *_heap_find_hash(HP_BLOCK *block,ulong pos);
extern byte *_hp_search(HP_INFO *info,HP_KEYDEF *keyinfo,const byte *key,
uint nextflag);
extern byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo,
const byte *key,
HASH_INFO *pos);
extern ulong _hp_hashnr(HP_KEYDEF *keyinfo,const byte *key);
extern ulong _hp_rec_hashnr(HP_KEYDEF *keyinfo,const byte *rec);
extern ulong _hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
extern void _hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
extern byte *hp_search(HP_INFO *info,HP_KEYDEF *keyinfo,const byte *key,
uint nextflag);
extern byte *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo,
const byte *key, HASH_INFO *pos);
extern ulong hp_hashnr(HP_KEYDEF *keyinfo,const byte *key);
extern ulong hp_rec_hashnr(HP_KEYDEF *keyinfo,const byte *rec);
extern ulong hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
extern void hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
HASH_INFO *newlink);
extern int _hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
const byte *rec2);
extern int _hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
const byte *key);
extern void _hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
extern int hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
const byte *rec2);
extern int hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
const byte *key);
extern void hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
extern uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos);
extern uint hp_rb_key_length(HP_KEYDEF *keydef, const byte *key);
extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key);
extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
extern int _hp_close(register HP_INFO *info);
extern void _hp_clear(HP_SHARE *info);
extern int hp_close(register HP_INFO *info);
extern void hp_clear(HP_SHARE *info);
extern uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old);
#ifdef THREAD
extern pthread_mutex_t THR_LOCK_heap;
#else
......
......@@ -20,7 +20,7 @@
/* Find record according to record-position */
byte *_hp_find_block(HP_BLOCK *block, ulong pos)
byte *hp_find_block(HP_BLOCK *block, ulong pos)
{
reg1 int i;
reg3 HP_PTRS *ptr;
......@@ -37,7 +37,7 @@ byte *_hp_find_block(HP_BLOCK *block, ulong pos)
/* get one new block-of-records. Alloc ptr to block if neaded */
/* Interrupts are stopped to allow ha_panic in interrupts */
int _hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
{
reg1 uint i,j;
HP_PTRS *root;
......@@ -84,7 +84,7 @@ int _hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
/* free all blocks under level */
byte *_hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
byte *hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
{
int i,max_pos;
byte *next_ptr;
......@@ -99,7 +99,7 @@ byte *_hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
next_ptr=(byte*) (pos+1);
for (i=0 ; i < max_pos ; i++)
next_ptr=_hp_free_level(block,level-1,
next_ptr=hp_free_level(block,level-1,
(HP_PTRS*) pos->blocks[i],next_ptr);
}
if ((byte*) pos != last_pos)
......
......@@ -24,25 +24,33 @@
void heap_clear(HP_INFO *info)
{
_hp_clear(info->s);
hp_clear(info->s);
}
void _hp_clear(HP_SHARE *info)
void hp_clear(HP_SHARE *info)
{
uint key;
DBUG_ENTER("_hp_clear");
DBUG_ENTER("hp_clear");
if (info->block.levels)
VOID(_hp_free_level(&info->block,info->block.levels,info->block.root,
VOID(hp_free_level(&info->block,info->block.levels,info->block.root,
(byte*) 0));
info->block.levels=0;
for (key=0 ; key < info->keys ; key++)
{
HP_BLOCK *block= &info->keydef[key].block;
if (block->levels)
VOID(_hp_free_level(block,block->levels,block->root,(byte*) 0));
block->levels=0;
block->last_allocated=0;
HP_KEYDEF *keyinfo = info->keydef + key;
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
delete_tree(&keyinfo->rb_tree);
}
else
{
HP_BLOCK *block= &keyinfo->block;
if (block->levels)
VOID(hp_free_level(block,block->levels,block->root,(byte*) 0));
block->levels=0;
block->last_allocated=0;
}
}
info->records=info->deleted=info->data_length=info->index_length=0;
info->blength=1;
......
......@@ -26,16 +26,16 @@ int heap_close(HP_INFO *info)
int tmp;
DBUG_ENTER("heap_close");
pthread_mutex_lock(&THR_LOCK_heap);
tmp= _hp_close(info);
tmp= hp_close(info);
pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(tmp);
}
int _hp_close(register HP_INFO *info)
int hp_close(register HP_INFO *info)
{
int error=0;
DBUG_ENTER("_hp_close");
DBUG_ENTER("hp_close");
#ifndef DBUG_OFF
if (info->s->changed && heap_check_heap(info,0))
{
......@@ -45,7 +45,7 @@ int _hp_close(register HP_INFO *info)
info->s->changed=0;
heap_open_list=list_delete(heap_open_list,&info->open_list);
if (!--info->s->open_count && info->s->delete_on_close)
_hp_free(info->s); /* Table was deleted */
hp_free(info->s); /* Table was deleted */
my_free((gptr) info,MYF(0));
DBUG_RETURN(error);
}
......@@ -14,30 +14,164 @@
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,
HP_CREATE_INFO *create_info)
{
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++)
{
keyinfo->seg= keyseg;
memcpy(keyseg, keydef[i].seg,
(size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
keyseg+= keydef[i].keysegs;
if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
{
/* additional HA_KEYTYPE_END keyseg */
keyseg->type= HA_KEYTYPE_END;
keyseg->length= sizeof(byte*);
keyseg->flag= 0;
keyseg->null_bit= 0;
keyseg++;
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;
}
else
{
init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
max_records);
keyinfo->delete_key= hp_delete_key;
keyinfo->write_key= hp_write_key;
}
}
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;
share->auto_key= create_info->auto_key;
share->auto_key_type= create_info->auto_key_type;
share->auto_increment= create_info->auto_increment;
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 +181,31 @@ int heap_delete_table(const char *name)
DBUG_ENTER("heap_delete_table");
pthread_mutex_lock(&THR_LOCK_heap);
if ((share=_hp_find_named_heap(name)))
if ((share= hp_find_named_heap(name)))
{
if (share->open_count == 0)
_hp_free(share);
hp_free(share);
else
share->delete_on_close=1;
result=0;
share->delete_on_close= 1;
result= 0;
}
else
{
result=my_errno=ENOENT;
result= my_errno=ENOENT;
}
pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(result);
}
void _hp_free(HP_SHARE *share)
void hp_free(HP_SHARE *share)
{
heap_share_list=list_delete(heap_share_list,&share->open_list);
_hp_clear(share); /* Remove blocks from memory */
heap_share_list= list_delete(heap_share_list, &share->open_list);
hp_clear(share); /* Remove blocks from memory */
#ifdef THREAD
thr_lock_delete(&share->lock);
VOID(pthread_mutex_destroy(&share->intern_lock));
#endif
my_free((gptr) share->name,MYF(0));
my_free((gptr) share,MYF(0));
my_free((gptr) share->name, MYF(0));
my_free((gptr) share, MYF(0));
return;
}
......@@ -20,25 +20,26 @@
int heap_delete(HP_INFO *info, const byte *record)
{
uint key;
byte *pos;
HP_SHARE *share=info->s;
HP_KEYDEF *keydef, *end, *p_lastinx;
DBUG_ENTER("heap_delete");
DBUG_PRINT("enter",("info: %lx record: %lx",info,record));
test_active(info);
if (info->opt_flag & READ_CHECK_USED && _hp_rectest(info,record))
if (info->opt_flag & READ_CHECK_USED && hp_rectest(info,record))
DBUG_RETURN(my_errno); /* Record changed */
share->changed=1;
if ( --(share->records) < share->blength >> 1) share->blength>>=1;
pos=info->current_ptr;
for (key=0 ; key < share->keys ; key++)
p_lastinx = share->keydef + info->lastinx;
for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
keydef++)
{
if (_hp_delete_key(info,share->keydef+key,record,pos,
key == (uint) info->lastinx))
if ((*keydef->delete_key)(info, keydef, record, pos, keydef == p_lastinx))
goto err;
}
......@@ -49,22 +50,39 @@ int heap_delete(HP_INFO *info, const byte *record)
share->deleted++;
info->current_hash_ptr=0;
DBUG_RETURN(0);
err:
err:
if (++(share->records) == share->blength)
share->blength+= share->blength;
DBUG_RETURN(my_errno);
}
/*
Remove one key from rb-tree
*/
int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
const byte *record, byte *recpos, int flag)
{
heap_rb_param custom_arg;
if (flag)
info->last_pos= NULL; /* For heap_rnext/heap_rprev */
custom_arg.keyseg= keyinfo->seg;
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
custom_arg.search_flag= SEARCH_SAME;
return tree_delete(&keyinfo->rb_tree, info->recbuf, &custom_arg);
}
/* Remove one key from hash-table */
/* Flag is set if we want's to correct info->current_ptr */
int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
const byte *record, byte *recpos, int flag)
{
ulong blength,pos2,pos_hashnr,lastpos_hashnr;
HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
HP_SHARE *share=info->s;
DBUG_ENTER("_hp_delete_key");
DBUG_ENTER("hp_delete_key");
blength=share->blength;
if (share->records+1 == blength)
......@@ -74,13 +92,13 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
/* Search after record with key */
pos= hp_find_hash(&keyinfo->block,
_hp_mask(_hp_rec_hashnr(keyinfo,record),blength,
share->records+1));
hp_mask(hp_rec_hashnr(keyinfo, record), blength,
share->records + 1));
gpos = pos3 = 0;
while (pos->ptr_to_rec != recpos)
{
if (flag && !_hp_rec_key_cmp(keyinfo,record,pos->ptr_to_rec))
if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
last_ptr=pos; /* Previous same key */
gpos=pos;
if (!(pos=pos->next_key))
......@@ -113,33 +131,33 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
DBUG_RETURN (0);
/* Move the last key (lastpos) */
lastpos_hashnr=_hp_rec_hashnr(keyinfo,lastpos->ptr_to_rec);
lastpos_hashnr = hp_rec_hashnr(keyinfo, lastpos->ptr_to_rec);
/* pos is where lastpos should be */
pos=hp_find_hash(&keyinfo->block,_hp_mask(lastpos_hashnr,share->blength,
pos=hp_find_hash(&keyinfo->block, hp_mask(lastpos_hashnr, share->blength,
share->records));
if (pos == empty) /* Move to empty position. */
{
empty[0]=lastpos[0];
DBUG_RETURN(0);
}
pos_hashnr=_hp_rec_hashnr(keyinfo,pos->ptr_to_rec);
pos_hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
/* pos3 is where the pos should be */
pos3= hp_find_hash(&keyinfo->block,
_hp_mask(pos_hashnr,share->blength,share->records));
hp_mask(pos_hashnr, share->blength, share->records));
if (pos != pos3)
{ /* pos is on wrong posit */
empty[0]=pos[0]; /* Save it here */
pos[0]=lastpos[0]; /* This shold be here */
_hp_movelink(pos,pos3,empty); /* Fix link to pos */
hp_movelink(pos, pos3, empty); /* Fix link to pos */
DBUG_RETURN(0);
}
pos2= _hp_mask(lastpos_hashnr,blength,share->records+1);
if (pos2 == _hp_mask(pos_hashnr,blength,share->records+1))
pos2= hp_mask(lastpos_hashnr, blength, share->records + 1);
if (pos2 == hp_mask(pos_hashnr, blength, share->records + 1))
{ /* Identical key-positions */
if (pos2 != share->records)
{
empty[0]=lastpos[0];
_hp_movelink(lastpos,pos,empty);
hp_movelink(lastpos, pos, empty);
DBUG_RETURN(0);
}
pos3= pos; /* Link pos->next after lastpos */
......@@ -147,7 +165,7 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
else pos3= 0; /* Different positions merge */
empty[0]=lastpos[0];
_hp_movelink(pos3,empty,pos->next_key);
hp_movelink(pos3, empty, pos->next_key);
pos->next_key=empty;
DBUG_RETURN(0);
}
This diff is collapsed.
......@@ -55,5 +55,7 @@ int heap_info(reg1 HP_INFO *info,reg2 HEAPINFO *x,
x->index_length= info->s->index_length;
x->max_records = info->s->max_records;
x->errkey = info->errkey;
if (flag & HA_STATUS_AUTO)
x->auto_increment= info->s->auto_increment + 1;
DBUG_RETURN(0);
} /* heap_info */
......@@ -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");
DBUG_ENTER("heap_open");
pthread_mutex_lock(&THR_LOCK_heap);
if (!(share=_hp_find_named_heap(name)))
if (!(share= hp_find_named_heap(name)))
{
DBUG_PRINT("info",("Initializing new table"));
for (i=key_segs=max_length=0 ; i < keys ; i++)
{
key_segs+= keydef[i].keysegs;
bzero((char*) &keydef[i].block,sizeof(keydef[i].block));
for (j=length=0 ; j < keydef[i].keysegs; j++)
{
length+=keydef[i].seg[j].length;
if (keydef[i].seg[j].null_bit &&
!(keydef[i].flag & HA_NULL_ARE_EQUAL))
keydef[i].flag |= HA_NULL_PART_KEY;
}
keydef[i].length=length;
if (length > max_length)
max_length=length;
}
if (!(share = (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
keys*sizeof(HP_KEYDEF)+
key_segs*sizeof(HP_KEYSEG),
MYF(MY_ZEROFILL))))
{
pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(0);
}
share->keydef=(HP_KEYDEF*) (share+1);
keyseg=(HP_KEYSEG*) (share->keydef+keys);
init_block(&share->block,reclength+1,min_records,max_records);
/* Fix keys */
memcpy(share->keydef,keydef,(size_t) (sizeof(keydef[0])*keys));
for (i=0 ; i < keys ; i++)
{
share->keydef[i].seg=keyseg;
memcpy(keyseg,keydef[i].seg,
(size_t) (sizeof(keyseg[0])*keydef[i].keysegs));
keyseg+=keydef[i].keysegs;
init_block(&share->keydef[i].block,sizeof(HASH_INFO),min_records,
max_records);
}
share->min_records=min_records;
share->max_records=max_records;
share->data_length=share->index_length=0;
share->reclength=reclength;
share->blength=1;
share->keys=keys;
share->max_key_length=max_length;
share->changed=0;
if (!(share->name=my_strdup(name,MYF(0))))
{
my_free((gptr) share,MYF(0));
pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(0);
}
#ifdef THREAD
thr_lock_init(&share->lock);
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
#endif
share->open_list.data=(void*) share;
heap_share_list=list_add(heap_share_list,&share->open_list);
my_errno= ENOENT;
pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(0);
}
if (!(info= (HP_INFO*) my_malloc((uint) sizeof(HP_INFO)+
share->max_key_length,
if (!(info= (HP_INFO*) my_malloc((uint) sizeof(HP_INFO) +
2 * share->max_key_length,
MYF(MY_ZEROFILL))))
{
pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(0);
}
share->open_count++;
share->open_count++;
#ifdef THREAD
thr_lock_data_init(&share->lock,&info->lock,NULL);
#endif
info->open_list.data=(void*) info;
heap_open_list=list_add(heap_open_list,&info->open_list);
info->open_list.data= (void*) info;
heap_open_list= list_add(heap_open_list,&info->open_list);
pthread_mutex_unlock(&THR_LOCK_heap);
info->s=share;
info->lastkey=(byte*) (info+1);
info->mode=mode;
info->s= share;
info->lastkey= (byte*) (info + 1);
info->recbuf= (byte*) (info->lastkey + share->max_key_length);
info->mode= mode;
info->current_record= (ulong) ~0L; /* No current record */
info->current_ptr=0;
info->current_hash_ptr=0;
info->lastinx= info->errkey= -1;
info->update=0;
info->current_ptr= 0;
info->current_hash_ptr= 0;
info->lastinx= info->errkey= -1;
info->update= 0;
#ifndef DBUG_OFF
info->opt_flag=READ_CHECK_USED; /* Check when changing */
info->opt_flag= READ_CHECK_USED; /* Check when changing */
#endif
DBUG_PRINT("exit",("heap: %lx reclength: %d records_in_block: %d",
info,share->reclength,share->block.records_in_block));
DBUG_RETURN(info);
} /* heap_open */
}
/* map name to a heap-nr. If name isn't found return 0 */
HP_SHARE *_hp_find_named_heap(const char *name)
HP_SHARE *hp_find_named_heap(const char *name)
{
LIST *pos;
HP_SHARE *info;
DBUG_ENTER("heap_find");
DBUG_PRINT("enter",("name: %s",name));
for (pos=heap_share_list ; pos ; pos=pos->next)
for (pos= heap_share_list; pos; pos= pos->next)
{
info=(HP_SHARE*) pos->data;
if (!strcmp(name,info->name))
info= (HP_SHARE*) pos->data;
if (!strcmp(name, info->name))
{
DBUG_PRINT("exit",("Old heap_database: %lx",info));
DBUG_PRINT("exit", ("Old heap_database: %lx",info));
DBUG_RETURN(info);
}
}
DBUG_RETURN((HP_SHARE *)0);
DBUG_RETURN((HP_SHARE *) 0);
}
static void init_block(HP_BLOCK *block, uint reclength, ulong min_records,
ulong max_records)
{
uint i,recbuffer,records_in_block;
max_records=max(min_records,max_records);
if (!max_records)
max_records=1000; /* As good as quess as anything */
recbuffer=(uint) (reclength+sizeof(byte**)-1) & ~(sizeof(byte**)-1);
records_in_block=max_records/10;
if (records_in_block < 10 && max_records)
records_in_block=10;
if (!records_in_block || records_in_block*recbuffer >
(my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
records_in_block=(my_default_record_cache_size-sizeof(HP_PTRS)*
HP_MAX_LEVELS)/recbuffer+1;
block->records_in_block=records_in_block;
block->recbuffer=recbuffer;
block->last_allocated= 0L;
for (i=0 ; i <= HP_MAX_LEVELS ; i++)
block->level_info[i].records_under_level=
(!i ? 1 : i == 1 ? records_in_block :
HP_PTRS_IN_NOD * block->level_info[i-1].records_under_level);
}
......@@ -31,7 +31,7 @@ int heap_panic(enum ha_panic_function flag)
next_open=element->next; /* Save if close */
switch (flag) {
case HA_PANIC_CLOSE:
_hp_close(info);
hp_close(info);
break;
default:
break;
......@@ -45,7 +45,7 @@ int heap_panic(enum ha_panic_function flag)
case HA_PANIC_CLOSE:
{
if (!share->open_count)
_hp_free(share);
hp_free(share);
break;
}
default:
......
......@@ -27,7 +27,7 @@ int heap_rename(const char *old_name, const char *new_name)
DBUG_ENTER("heap_rename");
pthread_mutex_lock(&THR_LOCK_heap);
if ((info=_hp_find_named_heap(old_name)))
if ((info = hp_find_named_heap(old_name)))
{
if (!(name_buff=(char*) my_strdup(new_name,MYF(MY_WME))))
{
......
......@@ -18,11 +18,43 @@
/* Read first record with the current key */
int heap_rfirst(HP_INFO *info, byte *record)
int heap_rfirst(HP_INFO *info, byte *record, int inx)
{
HP_SHARE *share = info->s;
HP_KEYDEF *keyinfo = share->keydef + inx;
DBUG_ENTER("heap_rfirst");
info->current_record=0;
info->current_hash_ptr=0;
info->update=HA_STATE_PREV_FOUND;
DBUG_RETURN(heap_rnext(info,record));
info->lastinx= inx;
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
byte *pos;
if ((pos = tree_search_edge(&keyinfo->rb_tree, info->parents,
&info->last_pos, offsetof(TREE_ELEMENT, left))))
{
memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
sizeof(byte*));
info->current_ptr = pos;
memcpy(record, pos, (size_t)share->reclength);
info->update = HA_STATE_AKTIV;
}
else
{
my_errno = HA_ERR_END_OF_FILE;
DBUG_RETURN(my_errno);
}
DBUG_RETURN(0);
}
else
{
if (!(info->s->records))
{
my_errno=HA_ERR_END_OF_FILE;
DBUG_RETURN(my_errno);
}
info->current_record=0;
info->current_hash_ptr=0;
info->update=HA_STATE_PREV_FOUND;
DBUG_RETURN(heap_rnext(info,record));
}
}
......@@ -16,29 +16,60 @@
#include "heapdef.h"
int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
uint key_len, enum ha_rkey_function find_flag)
{
byte *pos;
HP_SHARE *share=info->s;
HP_SHARE *share= info->s;
HP_KEYDEF *keyinfo= share->keydef + inx;
DBUG_ENTER("heap_rkey");
DBUG_PRINT("enter",("base: %lx inx: %d",info,inx));
if ((uint) inx >= share->keys)
{
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
DBUG_RETURN(my_errno= HA_ERR_WRONG_INDEX);
}
info->lastinx=inx;
info->current_record = (ulong) ~0L; /* For heap_rrnd() */
info->lastinx= inx;
info->current_record= (ulong) ~0L; /* For heap_rrnd() */
if (!(pos=_hp_search(info,share->keydef+inx,key,0)))
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
info->update=0;
DBUG_RETURN(my_errno);
heap_rb_param custom_arg;
hp_rb_pack_key(keyinfo, info->recbuf, key);
custom_arg.keyseg= info->s->keydef[inx].seg;
custom_arg.key_length= key_len;
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
/* for next rkey() after deletion */
if (find_flag == HA_READ_AFTER_KEY)
info->last_find_flag= HA_READ_KEY_OR_NEXT;
else if (find_flag == HA_READ_BEFORE_KEY)
info->last_find_flag= HA_READ_KEY_OR_PREV;
else
info->last_find_flag= find_flag;
info->lastkey_len= key_len;
if (!(pos= tree_search_key(&keyinfo->rb_tree, info->recbuf, info->parents,
&info->last_pos, find_flag, &custom_arg)))
{
info->update= 0;
DBUG_RETURN(my_errno= HA_ERR_KEY_NOT_FOUND);
}
memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos), sizeof(byte*));
info->current_ptr= pos;
}
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;
if (!(share->keydef[inx].flag & HA_NOSAME))
memcpy(info->lastkey,key,(size_t) share->keydef[inx].length);
memcpy(record, pos, (size_t) share->reclength);
info->update= HA_STATE_AKTIV;
DBUG_RETURN(0);
}
......@@ -47,5 +78,5 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
gptr heap_find(HP_INFO *info, int inx, const byte *key)
{
return _hp_search(info,info->s->keydef+inx,key,0);
return hp_search(info, info->s->keydef + inx, key, 0);
}
......@@ -19,11 +19,38 @@
/* Read first record with the current key */
int heap_rlast(HP_INFO *info, byte *record)
int heap_rlast(HP_INFO *info, byte *record, int inx)
{
HP_SHARE *share= info->s;
HP_KEYDEF *keyinfo= share->keydef + inx;
DBUG_ENTER("heap_rlast");
info->current_ptr=0;
info->current_hash_ptr=0;
info->update=HA_STATE_NEXT_FOUND;
DBUG_RETURN(heap_rprev(info,record));
info->lastinx= inx;
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
byte *pos;
if ((pos = tree_search_edge(&keyinfo->rb_tree, info->parents,
&info->last_pos, offsetof(TREE_ELEMENT, right))))
{
memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
sizeof(byte*));
info->current_ptr = pos;
memcpy(record, pos, (size_t)share->reclength);
info->update = HA_STATE_AKTIV;
}
else
{
my_errno = HA_ERR_END_OF_FILE;
DBUG_RETURN(my_errno);
}
DBUG_RETURN(0);
}
else
{
info->current_ptr=0;
info->current_hash_ptr=0;
info->update=HA_STATE_NEXT_FOUND;
DBUG_RETURN(heap_rprev(info,record));
}
}
......@@ -22,27 +22,58 @@ int heap_rnext(HP_INFO *info, byte *record)
{
byte *pos;
HP_SHARE *share=info->s;
HP_KEYDEF *keyinfo;
DBUG_ENTER("heap_rnext");
if (info->lastinx < 0)
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
if (info->current_hash_ptr)
pos= _hp_search_next(info,share->keydef+info->lastinx, info->lastkey,
info->current_hash_ptr);
else
keyinfo = share->keydef + info->lastinx;
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
if (!info->current_ptr && (info->update & HA_STATE_NEXT_FOUND))
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
{
pos=0; /* Read next after last */
my_errno=HA_ERR_KEY_NOT_FOUND;
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);
}
else
{
if (info->current_hash_ptr)
pos= hp_search_next(info, keyinfo, info->lastkey,
info->current_hash_ptr);
else
pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 1);
{
if (!info->current_ptr && (info->update & HA_STATE_NEXT_FOUND))
{
pos=0; /* Read next after last */
my_errno=HA_ERR_KEY_NOT_FOUND;
}
else if (!info->current_ptr) /* Deleted or first call */
pos= hp_search(info, keyinfo, info->lastkey, 0);
else
pos= hp_search(info, keyinfo, info->lastkey, 1);
}
}
if (!pos)
{
info->update=HA_STATE_NEXT_FOUND; /* For heap_rprev */
......
......@@ -23,22 +23,53 @@ int heap_rprev(HP_INFO *info, byte *record)
{
byte *pos;
HP_SHARE *share=info->s;
HP_KEYDEF *keyinfo;
DBUG_ENTER("heap_rprev");
if (info->lastinx < 0)
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
if (info->current_ptr || (info->update & HA_STATE_NEXT_FOUND))
keyinfo = share->keydef + info->lastinx;
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
if ((info->update & HA_STATE_DELETED))
pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 3);
heap_rb_param custom_arg;
if (info->last_pos)
pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos,
offsetof(TREE_ELEMENT, right),
offsetof(TREE_ELEMENT, left));
else
pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 2);
{
custom_arg.keyseg = keyinfo->seg;
custom_arg.key_length = keyinfo->length;
custom_arg.search_flag = SEARCH_SAME;
pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents,
&info->last_pos, info->last_find_flag, &custom_arg);
}
if (pos)
{
memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
sizeof(byte*));
info->current_ptr = pos;
}
else
{
my_errno = HA_ERR_KEY_NOT_FOUND;
}
}
else
{
pos=0; /* Read next after last */
my_errno=HA_ERR_KEY_NOT_FOUND;
if (info->current_ptr || (info->update & HA_STATE_NEXT_FOUND))
{
if ((info->update & HA_STATE_DELETED))
pos= hp_search(info, share->keydef + info->lastinx, info->lastkey, 3);
else
pos= hp_search(info, share->keydef + info->lastinx, info->lastkey, 2);
}
else
{
pos=0; /* Read next after last */
my_errno=HA_ERR_KEY_NOT_FOUND;
}
}
if (!pos)
{
......
......@@ -88,7 +88,7 @@ int heap_rrnd_old(register HP_INFO *info, byte *record, ulong pos)
}
/* Find record number pos */
_hp_find_record(info,pos);
hp_find_record(info, pos);
end:
if (!info->current_ptr[share->reclength])
......
......@@ -41,8 +41,8 @@ int heap_rsame(register HP_INFO *info, byte *record, int inx)
else if (inx != -1)
{
info->lastinx=inx;
_hp_make_key(share->keydef+inx,info->lastkey,record);
if (!_hp_search(info,share->keydef+inx,info->lastkey,3))
hp_make_key(share->keydef + inx, info->lastkey, record);
if (!hp_search(info, share->keydef + inx, info->lastkey, 3))
{
info->update=0;
DBUG_RETURN(my_errno);
......
......@@ -58,7 +58,7 @@ int heap_scan(register HP_INFO *info, byte *record)
DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
}
}
_hp_find_record(info,pos);
hp_find_record(info, pos);
}
if (!info->current_ptr[share->reclength])
{
......
......@@ -36,25 +36,31 @@ 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];
HP_CREATE_INFO hp_create_info;
MY_INIT(argv[0]);
filename= "test1";
get_options(argc,argv);
bzero(&hp_create_info, sizeof(hp_create_info));
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,
&hp_create_info) ||
!(file= heap_open(filename, 2)))
goto err;
printf("- Writing records:s\n");
strmov(record," ..... key ");
......@@ -77,7 +83,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 +91,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 +119,7 @@ int main(int argc, char **argv)
sprintf(key,"%6d",i);
bmove(record+1,key,6);
my_errno=0;
error=heap_rkey(file,record,0,key);
error=heap_rkey(file,record,0,key,0,6);
if (verbose ||
(error == 0 && flags[i] != 1) ||
(error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND)))
......
......@@ -26,7 +26,7 @@
#define SAFEMALLOC
#endif
#include "heapdef.h" /* Because of _hp_find_block */
#include "heapdef.h" /* Because of hp_find_block */
#include <signal.h>
#define MAX_RECORDS 100000
......@@ -61,8 +61,9 @@ 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;
HP_CREATE_INFO hp_create_info;
MY_INIT(argv[0]); /* init my_sys library & pthreads */
LINT_INIT(position);
......@@ -70,6 +71,8 @@ int main(int argc, char *argv[])
filename2= "test2_2";
file=file2=0;
get_options(argc,argv);
bzero(&hp_create_info, sizeof(hp_create_info));
write_count=update=opt_delete=0;
key_check=0;
......@@ -77,45 +80,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, &hp_create_info) ||
!(file= heap_open(filename, 2)))
goto err;
signal(SIGINT,endprog);
......@@ -167,14 +178,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 +238,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 +288,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 +317,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 +512,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 +524,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 +541,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 +549,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 +560,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,&hp_create_info) ||
!(file2= heap_open(filename2, 2)))
goto err;
printf("- Copying and removing records\n");
......
......@@ -20,47 +20,63 @@
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;
bool auto_key_changed= 0;
HP_SHARE *share= info->s;
DBUG_ENTER("heap_update");
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;
if (share->auto_key == (uint) (keydef - share->keydef + 1))
auto_key_changed= 1;
}
}
memcpy(pos,heap_new,(size_t) share->reclength);
if (++(share->records) == share->blength) share->blength+= share->blength;
if (auto_key_changed)
heap_update_auto_increment(info, heap_new);
DBUG_RETURN(0);
err:
if (my_errno == HA_ERR_FOUND_DUPP_KEY)
{
info->errkey=key;
do
info->errkey = keydef - share->keydef;
if (keydef->algorithm == HA_KEY_ALG_BTREE)
{
if (_hp_rec_key_cmp(share->keydef+key,old,heap_new))
/* we don't need to delete non-inserted key from rb-tree */
if ((*keydef->write_key)(info, keydef, old, pos))
{
if (_hp_delete_key(info,share->keydef+key,heap_new,pos,0) ||
_hp_write_key(share,share->keydef+key,old,pos))
if (++(share->records) == share->blength) share->blength+= share->blength;
DBUG_RETURN(my_errno);
}
keydef--;
}
while (keydef >= share->keydef)
{
if (hp_rec_key_cmp(keydef, old, heap_new))
{
if ((*keydef->delete_key)(info, keydef, heap_new, pos, 0) ||
(*keydef->write_key)(info, keydef, old, pos))
break;
}
} while (key-- > 0);
keydef--;
}
}
if (++(share->records) == share->blength) share->blength+= share->blength;
DBUG_RETURN(my_errno);
......
......@@ -27,12 +27,12 @@
#define HIGHUSED 8
static byte *next_free_record_pos(HP_SHARE *info);
static HASH_INFO *_hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
static HASH_INFO *hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
ulong records);
int heap_write(HP_INFO *info, const byte *record)
{
uint key;
HP_KEYDEF *keydef, *end;
byte *pos;
HP_SHARE *share=info->s;
DBUG_ENTER("heap_write");
......@@ -47,9 +47,10 @@ int heap_write(HP_INFO *info, const byte *record)
DBUG_RETURN(my_errno);
share->changed=1;
for (key=0 ; key < share->keys ; key++)
for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
keydef++)
{
if (_hp_write_key(share,share->keydef+key,record,pos))
if ((*keydef->write_key)(info, keydef, record, pos))
goto err;
}
......@@ -60,15 +61,23 @@ int heap_write(HP_INFO *info, const byte *record)
info->current_ptr=pos;
info->current_hash_ptr=0;
info->update|=HA_STATE_AKTIV;
if (share->auto_key)
heap_update_auto_increment(info, record);
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 +86,36 @@ int heap_write(HP_INFO *info, const byte *record)
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 +141,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 +152,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 +168,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 +251,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 +263,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 +274,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 +285,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 +297,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 +307,7 @@ static HASH_INFO *_hp_find_free_hash(HP_SHARE *info,
return hp_find_hash(block,records);
if (!(block_pos=(records % block->records_in_block)))
{
if (_hp_get_new_block(block,&length))
if (hp_get_new_block(block,&length))
return(NULL);
info->index_length+=length;
}
......
......@@ -28,7 +28,8 @@ noinst_HEADERS = config-win.h config-os2.h \
my_dir.h mysys_err.h my_base.h \
my_nosys.h my_alarm.h queues.h rijndael.h sha1.h \
my_aes.h my_tree.h hash.h thr_alarm.h \
thr_lock.h t_ctype.h violite.h md5.h mysql_version.h.in
thr_lock.h t_ctype.h violite.h md5.h \
mysql_version.h.in my_handler.h
# mysql_version.h are generated
SUPERCLEANFILES = mysql_version.h my_config.h
......
......@@ -61,3 +61,14 @@ extern const char *client_errors[]; /* Error messages */
#define CR_PROBE_SLAVE_HOSTS 2023
#define CR_PROBE_SLAVE_CONNECT 2024
#define CR_PROBE_MASTER_CONNECT 2025
/* new 4.1 error codes */
#define CR_INVALID_CONN_HANDLE 2026
#define CR_NULL_POINTER 2027
#define CR_NO_PREPARE_STMT 2028
#define CR_NOT_ALL_PARAMS_BOUND 2029
#define CR_DATA_TRUNCATED 2030
#define CR_NO_PARAMETERS_EXISTS 2031
#define CR_INVALID_PARAMETER_NO 2032
#define CR_INVALID_BUFFER_USE 2033
#define CR_UNSUPPORTED_PARAM_TYPE 2034
......@@ -40,13 +40,15 @@ typedef struct st_hash {
DYNAMIC_ARRAY array; /* Place for hash_keys */
hash_get_key get_key;
void (*free)(void *);
uint (*calc_hashnr)(const byte *key,uint length);
uint (*calc_hashnr)(CHARSET_INFO *cs, const byte *key,uint length);
CHARSET_INFO *charset;
} HASH;
#define hash_init(A,B,C,D,E,F,G) _hash_init(A,B,C,D,E,F,G CALLER_INFO)
my_bool _hash_init(HASH *hash,uint default_array_elements, uint key_offset,
uint key_length, hash_get_key get_key,
void (*free_element)(void*), uint flags CALLER_INFO_PROTO);
#define hash_init(A,B,C,D,E,F,G,H) _hash_init(A,B,C,D,E,F,G, H CALLER_INFO)
my_bool _hash_init(HASH *hash, CHARSET_INFO *charset,
uint default_array_elements, uint key_offset,
uint key_length, hash_get_key get_key,
void (*free_element)(void*), uint flags CALLER_INFO_PROTO);
void hash_free(HASH *tree);
byte *hash_element(HASH *hash,uint idx);
gptr hash_search(HASH *info,const byte *key,uint length);
......
......@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* This file should be included when using heap_database_funktions */
/* This file should be included when using heap_database_functions */
/* Author: Michael Widenius */
#ifndef _heap_h
......@@ -31,6 +31,9 @@ extern "C" {
#include <thr_lock.h>
#endif
#include "my_handler.h"
#include "my_tree.h"
/* defines used by heap-funktions */
#define HP_MAX_LEVELS 4 /* 128^5 records is enough */
......@@ -47,6 +50,7 @@ typedef struct st_heapinfo /* Struct from heap_info */
ulong index_length;
uint reclength; /* Length of one record */
int errkey;
ulonglong auto_increment;
} HEAPINFO;
......@@ -73,22 +77,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
......@@ -112,6 +116,9 @@ typedef struct st_heap_share
#endif
my_bool delete_on_close;
LIST open_list;
uint auto_key;
uint auto_key_type; /* real type of the auto key segment */
ulonglong auto_increment;
} HP_SHARE;
struct st_hp_hash_info;
......@@ -126,17 +133,27 @@ 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
LIST open_list;
} HP_INFO;
typedef struct st_heap_create_info
{
uint auto_key;
uint auto_key_type;
ulonglong auto_increment;
} HP_CREATE_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 +162,9 @@ 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,
HP_CREATE_INFO *create_info);
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 +172,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);
extern void heap_update_auto_increment(HP_INFO *info, const byte *record);
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);
......
This diff is collapsed.
......@@ -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 */
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA */
#ifndef _my_handler_h
#define _my_handler_h
#include "my_global.h"
#include "my_base.h"
#include "m_ctype.h"
#include "myisampack.h"
typedef struct st_HA_KEYSEG /* Key-portion */
{
uint8 type; /* Type of key (for sort) */
uint8 language;
uint8 null_bit; /* bitmask to test for NULL */
uint8 bit_start,bit_end; /* if bit field */
uint16 flag;
uint16 length; /* Keylength */
uint32 start; /* Start of key in record */
uint32 null_pos; /* position to NULL indicator */
CHARSET_INFO *charset;
} HA_KEYSEG;
#define get_key_length(length,key) \
{ if ((uchar) *(key) != 255) \
length= (uint) (uchar) *((key)++); \
else \
{ length=mi_uint2korr((key)+1); (key)+=3; } \
}
#define get_key_pack_length(length,length_pack,key) \
{ if ((uchar) *(key) != 255) \
{ length= (uint) (uchar) *((key)++); length_pack=1; }\
else \
{ length=mi_uint2korr((key)+1); (key)+=3; length_pack=3; } \
}
extern int mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
my_bool);
extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
register uchar *b, uint key_length, uint nextflag,
uint *diff_pos);
#endif /* _my_handler_h */
......@@ -105,13 +105,6 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_SEEK_CUR 1
#define MY_SEEK_END 2
/* My charsets_list flags */
#define MY_NO_SETS 0
#define MY_COMPILED_SETS 1 /* show compiled-in sets */
#define MY_CONFIG_SETS 2 /* sets that have a *.conf file */
#define MY_INDEX_SETS 4 /* all sets listed in the Index file */
#define MY_LOADED_SETS 8 /* the sets that are currently loaded */
/* Some constants */
#define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */
#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */
......@@ -300,6 +293,14 @@ extern struct my_file_info
#endif
} my_file_info[MY_NFILE];
typedef struct st_my_tmpdir
{
char **list;
uint cur, max;
#ifdef THREAD
pthread_mutex_t mutex;
#endif
} MY_TMPDIR;
typedef struct st_dynamic_array
{
......@@ -589,12 +590,11 @@ extern void allow_break(void);
#define allow_break()
#endif
extern my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist);
extern char *my_tmpdir(MY_TMPDIR *tmpdir);
extern void free_tmpdir(MY_TMPDIR *tmpdir);
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 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 +619,12 @@ 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 WF_PACK *wf_comp(my_string str);
extern int wf_test(struct wild_file_pack *wf_pack,const char *name);
extern void wf_end(struct wild_file_pack *buffer);
extern size_s strip_sp(my_string str);
extern void get_date(my_string to,int timeflag,time_t use_time);
extern void soundex(my_string out_pntr, my_string in_pntr,pbool remove_garbage);
extern void soundex(CHARSET_INFO *, my_string out_pntr, my_string in_pntr,pbool remove_garbage);
extern int init_record_cache(RECORD_CACHE *info,uint cachesize,File file,
uint reclength,enum cache_type type,
pbool use_async_io);
......
......@@ -20,13 +20,17 @@
extern "C" {
#endif
#define MAX_TREE_HIGHT 40 /* = max 1048576 leafs in tree */
#include "my_base.h" /* get 'enum ha_rkey_function' */
#define MAX_TREE_HEIGHT 40 /* = max 1048576 leafs in tree */
#define ELEMENT_KEY(tree,element)\
(tree->offset_to_key ? (void*)((byte*) element+tree->offset_to_key) :\
*((void**) (element+1)))
#define tree_set_pointer(element,ptr) *((byte **) (element+1))=((byte*) (ptr))
#define TREE_NO_DUPS 1
typedef enum { left_root_right, right_root_left } TREE_WALK;
typedef uint32 element_count;
typedef int (*tree_walk_action)(void *,element_count,void *);
......@@ -48,15 +52,18 @@ typedef struct st_tree_element {
} TREE_ELEMENT;
#endif /* MSDOS */
#define ELEMENT_CHILD(element, offs) (*(TREE_ELEMENT**)((char*)element + offs))
typedef struct st_tree {
TREE_ELEMENT *root,null_element;
TREE_ELEMENT **parents[MAX_TREE_HIGHT];
TREE_ELEMENT **parents[MAX_TREE_HEIGHT];
uint offset_to_key,elements_in_tree,size_of_element,memory_limit,allocated;
qsort_cmp2 compare;
void* custom_arg;
void *custom_arg;
MEM_ROOT mem_root;
my_bool with_delete;
tree_element_free free;
uint flag;
} TREE;
/* Functions on whole tree */
......@@ -70,12 +77,22 @@ void reset_tree(TREE*);
#define is_tree_inited(tree) ((tree)->root != 0)
/* Functions on leafs */
TREE_ELEMENT *tree_insert(TREE *tree,void *key,uint key_size);
void *tree_search(TREE *tree,void *key);
TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size,
void *custom_arg);
void *tree_search(TREE *tree, void *key, void *custom_arg);
int tree_walk(TREE *tree,tree_walk_action action,
void *argument, TREE_WALK visit);
int tree_delete(TREE *tree,void *key);
int tree_delete(TREE *tree, void *key, void *custom_arg);
void *tree_search_key(TREE *tree, const void *key,
TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos,
enum ha_rkey_function flag, void *custom_arg);
void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents,
TREE_ELEMENT ***last_pos, int child_offs);
void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs,
int r_offs);
uint tree_record_pos(TREE *tree, const void *key,
enum ha_rkey_function search_flag, void *custom_arg);
#ifdef __cplusplus
}
#endif
......
......@@ -28,6 +28,7 @@ extern "C" {
#ifndef _m_ctype_h
#include <m_ctype.h>
#endif
#include "my_handler.h"
/* defines used by myisam-funktions */
......@@ -105,20 +106,6 @@ typedef struct st_mi_create_info
struct st_myisam_info; /* For referense */
typedef struct st_myisam_info MI_INFO;
typedef struct st_mi_keyseg /* Key-portion */
{
uint8 type; /* Type of key (for sort) */
uint8 language;
uint8 null_bit; /* bitmask to test for NULL */
uint8 bit_start,bit_end; /* if bit field */
uint16 flag;
uint16 length; /* Keylength */
uint32 start; /* Start of key in record */
uint32 null_pos; /* position to NULL indicator */
CHARSET_INFO *charset;
} MI_KEYSEG;
struct st_mi_s_param;
typedef struct st_mi_keydef /* Key definition with open & info */
......@@ -135,7 +122,7 @@ typedef struct st_mi_keydef /* Key definition with open & info */
uint16 block_size; /* block_size (auto) */
uint32 version; /* For concurrent read/write */
MI_KEYSEG *seg,*end;
HA_KEYSEG *seg,*end;
int (*bin_search)(struct st_myisam_info *info,struct st_mi_keydef *keyinfo,
uchar *page,uchar *key,
uint key_len,uint comp_flag,uchar * *ret_pos,
......@@ -147,6 +134,8 @@ typedef struct st_mi_keydef /* Key definition with open & info */
struct st_mi_s_param *s_temp);
void (*store_key)(struct st_mi_keydef *keyinfo, uchar *key_pos,
struct st_mi_s_param *s_temp);
int (*ck_insert)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen);
int (*ck_delete)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen);
} MI_KEYDEF;
......@@ -157,7 +146,7 @@ typedef struct st_unique_def /* Segment definition of unique */
uint16 keysegs; /* Number of key-segment */
uchar key; /* Mapped to which key */
uint8 null_are_equal;
MI_KEYSEG *seg,*end;
HA_KEYSEG *seg,*end;
} MI_UNIQUEDEF;
typedef struct st_mi_decode_tree /* Decode huff-table */
......@@ -321,6 +310,7 @@ typedef struct st_sort_key_blocks /* Used when sorting */
int inited;
} SORT_KEY_BLOCKS;
typedef struct st_mi_check_param
{
ulonglong auto_increment_value;
......@@ -339,7 +329,8 @@ typedef struct st_mi_check_param
uint8 language;
my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
my_bool retry_repair, force_sort, calc_checksum;
char temp_filename[FN_REFLEN],*isam_file_name,*tmpdir;
char temp_filename[FN_REFLEN],*isam_file_name;
MY_TMPDIR *tmpdir;
int tmpfile_createflag;
myf myf_rw;
IO_CACHE read_cache;
......@@ -386,7 +377,7 @@ typedef struct st_mi_sort_param
byte *rec_buff;
void *wordlist, *wordptr;
char *record;
char *tmpdir;
MY_TMPDIR *tmpdir;
int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *);
int (*key_read)(struct st_mi_sort_param *,void *);
int (*key_write)(struct st_mi_sort_param *, const void *);
......
......@@ -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 */
unsigned long 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,
unsigned long length, my_bool skip_check);
unsigned long net_safe_read(MYSQL* mysql);
#ifdef __cplusplus
......
......@@ -34,14 +34,15 @@
#define MYSQL_SERVICENAME "MySql"
#endif /* __WIN__ */
enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
COM_FIELD_LIST,COM_CREATE_DB,COM_DROP_DB,COM_REFRESH,
COM_SHUTDOWN,COM_STATISTICS,
COM_PROCESS_INFO,COM_CONNECT,COM_PROCESS_KILL,
COM_DEBUG,COM_PING,COM_TIME,COM_DELAYED_INSERT,
COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT,
COM_REGISTER_SLAVE};
enum enum_server_command
{
COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST,
COM_CREATE_DB, COM_DROP_DB, COM_REFRESH, COM_SHUTDOWN, COM_STATISTICS,
COM_PROCESS_INFO, COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING,
COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT
};
#define NOT_NULL_FLAG 1 /* Field can't be NULL */
#define PRI_KEY_FLAG 2 /* Field is part of a primary key */
......@@ -95,9 +96,11 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
#define CLIENT_SSL 2048 /* Switch to SSL after handshake */
#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
#define CLIENT_PROTOCOL_41 16384 /* New 4.1 protocol */
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
#define SERVER_STATUS_MORE_RESULTS 4 /* More results on server */
#define MYSQL_ERRMSG_SIZE 200
#define NET_READ_TIMEOUT 30 /* Timeout on read */
......@@ -130,33 +133,75 @@ typedef struct st_net {
unsigned int *return_status;
unsigned char reading_or_writing;
char save_char;
my_bool report_error; /* We should report error (we have unreported error) */
my_bool no_send_ok;
gptr query_cache_query;
/*
Pointer to query object in query cache, do not equal NULL (0) for
queries in cache that have not stored its results yet
*/
gptr query_cache_query;
} 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 +209,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 +302,6 @@ void my_thread_end(void);
#endif
#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */
#define MYSQL_LONG_DATA_HEADER 8
#endif
......@@ -253,4 +253,9 @@
#define ER_CANT_USE_OPTION_HERE 1234
#define ER_NOT_SUPPORTED_YET 1235
#define ER_MASTER_FATAL_ERROR_READING_BINLOG 1236
#define ER_ERROR_MESSAGES 237
#define ER_WRONG_FK_DEF 1237
#define ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1238
#define ER_SUBSELECT_NO_1_COL 1239
#define ER_SUBSELECT_NO_1_ROW 1240
#define ER_UNKNOWN_STMT_HANDLER 1241
#define ER_ERROR_MESSAGES 242
......@@ -54,11 +54,11 @@ uint _nisam_make_key(register N_INFO *info, uint keynr, uchar *key, const char *
*key++= (uchar) (length=(uint) (end-pos));
memcpy((byte*) key,(byte*) pos,(size_t) length);
#ifdef USE_STRCOLL
if (!use_strcoll(default_charset_info))
if (!use_strnxfrm(default_charset_info))
#endif
{
if (type == HA_KEYTYPE_TEXT)
case_sort((byte*) key,length);
my_tosort(default_charset_info,(byte*) key,length);
}
key+=length;
}
......@@ -67,11 +67,11 @@ uint _nisam_make_key(register N_INFO *info, uint keynr, uchar *key, const char *
memcpy((byte*) key,(byte*) record+keyseg->base.start,
(size_t) keyseg->base.length);
#ifdef USE_STRCOLL
if (!use_strcoll(default_charset_info))
if (!use_strnxfrm(default_charset_info))
#endif
{
if (type == HA_KEYTYPE_TEXT)
case_sort((byte*) key,(uint) keyseg->base.length);
my_tosort(default_charset_info,(byte*) key,(uint) keyseg->base.length);
}
#ifdef NAN_TEST
else if (type == HA_KEYTYPE_FLOAT)
......@@ -150,11 +150,11 @@ uint _nisam_pack_key(register N_INFO *info, uint keynr, uchar *key, uchar *old,
else
memcpy((byte*) key,old,(size_t) length);
#ifdef USE_STRCOLL
if (!use_strcoll(default_charset_info))
if (!use_strnxfrm(default_charset_info))
#endif
{
if (type == HA_KEYTYPE_TEXT)
case_sort((byte*) key,length);
my_tosort(default_charset_info,(byte*) key,length);
}
key+= length;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment