Commit b3cb7b7f authored by unknown's avatar unknown

merge with 4.0.5


BitKeeper/etc/logging_ok:
  auto-union
configure.in:
  Auto merged
Docs/manual.texi:
  Auto merged
myisam/mi_open.c:
  Auto merged
mysql-test/r/null_key.result:
  Auto merged
mysql-test/r/select.result:
  Auto merged
sql/field.h:
  Auto merged
sql/field_conv.cc:
  Auto merged
sql/ha_innodb.cc:
  Auto merged
sql/log.cc:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/table.cc:
  Auto merged
parents 6f38e308 aee5ef85
......@@ -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
......@@ -14,7 +14,8 @@ $make -k clean || true
/bin/rm -f */.deps/*.P config.cache innobase/config.cache bdb/build_unix/config.cache
aclocal && autoheader && aclocal && automake && autoconf
(cd bdb/dist && sh s_all)
# TODO: remove when DBD will be OK
#(cd bdb/dist && sh s_all)
(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
if [ -d gemini ]
then
......
......@@ -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"
......@@ -4,6 +4,7 @@ Administrator@co3064164-a.rochd1.qld.optushome.com.au
Administrator@fred.
Miguel@light.local
Sinisa@sinisa.nasamreza.org
WAX@sergbook.mysql.com
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
akishkin@work.mysql.com
arjen@co3064164-a.bitbike.com
......@@ -11,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
......@@ -57,6 +59,8 @@ paul@teton.kitebird.com
pem@mysql.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)
......@@ -80,6 +84,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
......
......@@ -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+
......
......@@ -136,6 +136,10 @@ SOURCE="..\strings\ctype-latin1_de.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-simple.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-sjis.c"
# End Source File
# Begin Source File
......
#!/bin/sh
#
# Change linefeed -> return+linefeed for all VC++ project files
#
find . \( -name "*.dsp" -o -name "*.dsw" \) -print | grep -v "SCCS" | xargs replace '\r\$' ' ' '\$' ' ' --
......@@ -147,6 +147,10 @@ SOURCE="..\strings\ctype-latin1_de.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-simple.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-sjis.c"
# End Source File
# Begin Source File
......@@ -256,6 +260,7 @@ SOURCE=..\mysys\my_alloc.c
# Begin Source File
SOURCE=..\mysys\my_compress.c
# ADD CPP /I "../zlib"
# End Source File
# Begin Source File
......
......@@ -43,8 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBMYSQLD_EXPORTS" /YX /FD /c
# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FR /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FR /FD /mktyplib203 /win32 # ADD BASE MTL /c
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
......@@ -53,8 +52,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib /nologo /dll /machine:I386 /out:"../lib_release/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
# SUBTRACT LINK32 /pdb:none
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib # SUBTRACT LINK32 /nologo /dll /pdb:none /machine:I386 /out:"../lib_release/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
!ELSEIF "$(CFG)" == "libmysqld - Win32 Debug"
......@@ -70,8 +68,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBMYSQLD_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MT /W3 /Gm /Zi /Od /I "../include" /I "../sql" /I "../regex" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD CPP /nologo /MT /W3 /Gm /Zi /Od /I "../include" /I "../sql" /I "../regex" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /mktyplib203 /win32 # ADD BASE MTL /c
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x416 /d "_DEBUG"
# ADD RSC /l 0x416 /d "_DEBUG"
......@@ -80,8 +77,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\innodb.lib /nologo /dll /incremental:no /debug /machine:I386 /nodefaultlib:"LIBCMTD" /out:"../lib_debug/libmysqld.dll" /implib:"../lib_debug/libmysqld.lib" /pdbtype:sept
# SUBTRACT LINK32 /pdb:none
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\innodb.lib # SUBTRACT LINK32 /nologo /dll /pdb:none /debug /machine:I386 /nodefaultlib:"LIBCMTD" /out:"../lib_debug/libmysqld.dll" /implib:"../lib_debug/libmysqld.lib"
!ENDIF
......@@ -119,6 +115,10 @@ SOURCE=..\libmysql\get_password.c
# End Source File
# Begin Source File
SOURCE=..\sql\gstream.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\ha_berkeley.cpp
# End Source File
# Begin Source File
......@@ -176,6 +176,7 @@ SOURCE=..\sql\item_create.cpp
# Begin Source File
SOURCE=..\sql\item_func.cpp
# ADD CPP /I "../zlib"
# End Source File
# Begin Source File
......@@ -183,6 +184,10 @@ SOURCE=..\sql\item_strfunc.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\item_subselect.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\item_sum.cpp
# End Source File
# Begin Source File
......@@ -271,7 +276,7 @@ SOURCE=..\sql\set_var.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\slave.cpp
SOURCE=..\sql\spatial.cpp
# End Source File
# Begin Source File
......@@ -307,10 +312,18 @@ SOURCE=..\sql\sql_delete.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\sql_derived.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\sql_do.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\sql_error.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\sql_handler.cpp
# End Source File
# Begin Source File
......@@ -327,10 +340,6 @@ SOURCE=..\sql\sql_list.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\sql_load.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\sql_manager.cpp
# End Source File
# Begin Source File
......@@ -340,6 +349,10 @@ SOURCE=..\sql\sql_map.cpp
# Begin Source File
SOURCE=..\sql\sql_parse.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\sql_prepare.cpp
# End Source File
# Begin Source File
......
......@@ -265,8 +265,28 @@ SOURCE=.\mi_write.c
# End Source File
# Begin Source File
SOURCE=.\rt_index.c
# End Source File
# Begin Source File
SOURCE=.\rt_key.c
# End Source File
# Begin Source File
SOURCE=.\rt_mbr.c
# End Source File
# Begin Source File
SOURCE=.\rt_split.c
# End Source File
# Begin Source File
SOURCE=.\sort.c
# End Source File
# Begin Source File
SOURCE=.\sp_key.c
# End Source File
# End Group
# Begin Group "Header Files"
......@@ -279,6 +299,10 @@ SOURCE=.\ft_eval.h
SOURCE=.\myisamdef.h
# End Source File
# Begin Source File
SOURCE=.\rt_index.h
# End Source File
# End Group
# End Target
# End Project
......@@ -326,6 +326,10 @@ SOURCE=.\my_getwd.c
# End Source File
# Begin Source File
SOURCE=.\my_handler.c
# End Source File
# Begin Source File
SOURCE=.\my_init.c
# End Source File
# Begin Source File
......
......@@ -282,6 +282,10 @@ SOURCE=.\filesort.cpp
# End Source File
# Begin Source File
SOURCE=.\gstream.cpp
# End Source File
# Begin Source File
SOURCE=.\ha_berkeley.cpp
# End Source File
# Begin Source File
......@@ -460,17 +464,25 @@ SOURCE=.\item_func.cpp
!IF "$(CFG)" == "mysqld - Win32 Release"
# ADD CPP /I "../zlib"
!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
# ADD CPP /G5
# ADD CPP /G5 /I "../zlib"
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
# ADD CPP /I "../zlib"
!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
# ADD CPP /I "../zlib"
!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
# ADD CPP /I "../zlib"
!ENDIF
# End Source File
......@@ -496,6 +508,10 @@ SOURCE=.\item_strfunc.cpp
# End Source File
# Begin Source File
SOURCE=.\item_subselect.cpp
# End Source File
# Begin Source File
SOURCE=.\item_sum.cpp
!IF "$(CFG)" == "mysqld - Win32 Release"
......@@ -811,6 +827,10 @@ SOURCE=.\slave.cpp
# End Source File
# Begin Source File
SOURCE=.\spatial.cpp
# End Source File
# Begin Source File
SOURCE=.\sql_acl.cpp
!IF "$(CFG)" == "mysqld - Win32 Release"
......@@ -927,10 +947,18 @@ SOURCE=.\sql_delete.cpp
# End Source File
# Begin Source File
SOURCE=.\sql_derived.cpp
# End Source File
# Begin Source File
SOURCE=.\sql_do.cpp
# End Source File
# Begin Source File
SOURCE=.\sql_error.cpp
# End Source File
# Begin Source File
SOURCE=.\sql_handler.cpp
# End Source File
# Begin Source File
......@@ -1059,6 +1087,10 @@ SOURCE=.\sql_parse.cpp
# End Source File
# Begin Source File
SOURCE=.\sql_prepare.cpp
# End Source File
# Begin Source File
SOURCE=.\sql_rename.cpp
# End Source File
# Begin Source File
......
......@@ -128,6 +128,10 @@ SOURCE=".\ctype-latin1_de.c"
# End Source File
# Begin Source File
SOURCE=".\ctype-simple.c"
# End Source File
# Begin Source File
SOURCE=".\ctype-sjis.c"
# End Source File
# Begin Source File
......
......@@ -18,6 +18,9 @@
#undef CRAY_STACKSEG_END
/* Define the default charset name */
#undef DEFAULT_CHARSET_NAME
/* Version of .frm files */
#undef DOT_FRM_VERSION
......@@ -63,6 +66,43 @@
/* READLINE: */
#undef HAVE_BSD_SIGNALS
/* Define charsets you want */
#undef HAVE_CHARSET_armscii8
#undef HAVE_CHARSET_big5
#undef HAVE_CHARSET_cp1251
#undef HAVE_CHARSET_cp1257
#undef HAVE_CHARSET_croat
#undef HAVE_CHARSET_czech
#undef HAVE_CHARSET_danish
#undef HAVE_CHARSET_dec8
#undef HAVE_CHARSET_dos
#undef HAVE_CHARSET_estonia
#undef HAVE_CHARSET_euc_kr
#undef HAVE_CHARSET_gb2312
#undef HAVE_CHARSET_gbk
#undef HAVE_CHARSET_german1
#undef HAVE_CHARSET_greek
#undef HAVE_CHARSET_hebrew
#undef HAVE_CHARSET_hp8
#undef HAVE_CHARSET_hungarian
#undef HAVE_CHARSET_koi8_ru
#undef HAVE_CHARSET_koi8_ukr
#undef HAVE_CHARSET_latin1
#undef HAVE_CHARSET_latin1_de
#undef HAVE_CHARSET_latin2
#undef HAVE_CHARSET_latin5
#undef HAVE_CHARSET_sjis
#undef HAVE_CHARSET_swe7
#undef HAVE_CHARSET_tis620
#undef HAVE_CHARSET_ucs2
#undef HAVE_CHARSET_ujis
#undef HAVE_CHARSET_usa7
#undef HAVE_CHARSET_utf8
#undef HAVE_CHARSET_win1250
#undef HAVE_CHARSET_win1250ch
#undef HAVE_CHARSET_win1251ukr
#undef HAVE_CHARSET_win1251
/* ZLIB and compress: */
#undef HAVE_COMPRESS
......
......@@ -40,7 +40,7 @@
#include <signal.h>
#include <violite.h>
const char *VER= "12.16";
const char *VER= "13.0";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
......@@ -91,8 +91,8 @@ extern "C" {
#define vidattr(A) {} // Can't get this to work
#endif
#ifdef __WIN__
#define cmp_database(A,B) my_strcasecmp((A),(B))
#ifdef FN_NO_CASE_SENCE
#define cmp_database(A,B) my_strcasecmp(system_charset_info, (A), (B))
#else
#define cmp_database(A,B) strcmp((A),(B))
#endif
......@@ -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
......@@ -877,14 +878,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
......@@ -896,7 +897,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))
......@@ -924,12 +926,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--;
......@@ -992,7 +995,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
......@@ -1368,9 +1371,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)
......@@ -1399,7 +1402,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;
......@@ -1452,7 +1457,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
{
......@@ -1467,20 +1472,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);
......@@ -1777,8 +1792,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--;
......@@ -1838,7 +1854,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
{
......@@ -1857,11 +1873,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)
......@@ -1901,7 +1918,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
{
......@@ -1917,10 +1934,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);
......@@ -2056,7 +2074,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
......@@ -2102,15 +2120,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);
......@@ -2151,7 +2170,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
......@@ -2335,7 +2354,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);
......@@ -2444,7 +2463,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 @@ public:
char *new_ptr;
if (!(new_ptr=(char*) my_realloc(Ptr,arg_length,MYF(0))))
{
(void) my_free(Ptr,MYF(0));
Alloced_length = 0;
real_alloc(arg_length);
}
else
......@@ -153,6 +179,7 @@ public:
bool append(const char *s,uint32 arg_length=0);
bool append(IO_CACHE* file, uint32 arg_length);
int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
int strstr_case(const String &s,uint32 offset=0);
int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
bool replace(uint32 offset,uint32 arg_length,const String &to);
inline bool append(char chr)
......@@ -171,8 +198,8 @@ public:
}
bool fill(uint32 max_length,char fill);
void strip_sp();
inline void caseup() { ::caseup(Ptr,str_length); }
inline void casedn() { ::casedn(Ptr,str_length); }
inline void caseup() { my_caseup(str_charset,Ptr,str_length); }
inline void casedn() { my_casedn(str_charset,Ptr,str_length); }
friend int sortcmp(const String *a,const String *b);
friend int stringcmp(const String *a,const String *b);
friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
......@@ -180,4 +207,49 @@ public:
friend int wild_compare(String &match,String &wild,char escape);
uint32 numchars();
int charpos(int i,uint32 offset=0);
// added by Holyfoot for "geometry" needs
int reserve(uint32 space_needed)
{
return realloc(str_length + space_needed);
}
int reserve(uint32 space_needed, uint32 grow_by);
// these append operations do NOT check alloced memory
// q_*** methods writes values of parameters itself
// qs_*** methods writes string representation of value
void q_append(const char &c)
{
Ptr[str_length++] = c;
}
void q_append(const uint32 &n)
{
int4store(Ptr + str_length, n);
str_length += 4;
}
void q_append(double d)
{
float8store(Ptr + str_length, d);
str_length += 8;
}
void q_append(double *d)
{
float8store(Ptr + str_length, *d);
str_length += 8;
}
void q_append(const char *data, uint32 data_len)
{
memcpy(Ptr + str_length, data, data_len);
str_length += data_len;
}
void WriteAtPosition(int position, uint32 value)
{
int4store(Ptr + position,value);
}
void qs_append(const char *str);
void qs_append(double d);
void qs_append(double *d);
void qs_append(const char &c);
};
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,44 @@ 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: key: %d Record: %lx\n",
keynr, 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 %lu of %lu records", found, 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"
/*
When allocating keys /rows in the internal block structure, do it
......@@ -40,10 +41,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
{
......@@ -51,40 +52,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,165 +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 < HP_MIN_RECORDS_IN_BLOCK && max_records)
records_in_block= HP_MIN_RECORDS_IN_BLOCK;
/*
Don't allocate too many rows at one time too keep memory consumption
done when we don't need it.
*/
if (records_in_block > HP_MAX_RECORDS_IN_BLOCK)
records_in_block= HP_MAX_RECORDS_IN_BLOCK;
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 @@ err:
DBUG_RETURN(my_errno);
} /* heap_write */
/*
Write a key to rb_tree-index
*/
int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record,
byte *recpos)
{
heap_rb_param custom_arg;
info->last_pos= NULL; /* For heap_rnext/heap_rprev */
custom_arg.keyseg= keyinfo->seg;
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
if (keyinfo->flag & HA_NOSAME)
{
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
keyinfo->rb_tree.flag= TREE_NO_DUPS;
}
else
{
custom_arg.search_flag= SEARCH_SAME;
keyinfo->rb_tree.flag= 0;
}
if (!tree_insert(&keyinfo->rb_tree, (void*)info->recbuf,
custom_arg.key_length, &custom_arg))
{
my_errno= HA_ERR_FOUND_DUPP_KEY;
return 1;
}
return 0;
}
/* Find where to place new record */
......@@ -102,7 +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 *);
......
This diff is collapsed.
This diff is collapsed.
......@@ -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;
}
......
......@@ -332,7 +332,7 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
end= a+ min(key_length,(uint) length);
#ifdef USE_STRCOLL
if (use_strcoll(default_charset_info)) {
if (use_strnxfrm(default_charset_info)) {
if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
{
while (a < end)
......@@ -383,7 +383,7 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
else
{
#ifdef USE_STRCOLL
if (use_strcoll(default_charset_info)) {
if (use_strnxfrm(default_charset_info)) {
if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
{
while (a < end)
......@@ -515,11 +515,13 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
if (*a++ != *b++)
{
a--; b--;
if (isdigit((char) *a) && isdigit((char) *b))
if (my_isdigit(default_charset_info, (char) *a) &&
my_isdigit(default_charset_info, (char) *b))
return ((int) *a - (int) *b);
if (*a == '-' || isdigit((char) *b))
if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
return (-1);
if (*b == '-' || *b++ == ' ' || isdigit((char) *a))
if (*b == '-' || *b++ == ' ' ||
my_isdigit(default_charset_info,(char) *a))
return (1);
if (*a++ == ' ')
return (-1);
......@@ -539,11 +541,13 @@ int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar
if (*a++ != *b++)
{
a--; b--;
if (isdigit((char) *a) && isdigit((char) *b))
if (my_isdigit(default_charset_info,(char) *a) &&
my_isdigit(default_charset_info,(char) *b))
return ((int) *a - (int) *b);
if (*a == '-' || isdigit((char) *b))
if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
return (-1);
if (*b == '-' || *b++ == ' ' || isdigit((char) *a))
if (*b == '-' || *b++ == ' ' ||
my_isdigit(default_charset_info,(char) *a))
return (1);
if (*a++ == ' ')
return -1;
......
......@@ -342,7 +342,7 @@ static int examine_log(my_string file_name, char **table_names)
file_info.process=0;
result=uint2korr(head+7);
if ((curr_file_info=(struct isamlog_file_info*)
tree_search(&tree,&file_info)))
tree_search(&tree, &file_info, tree.custom_arg)))
{
curr_file_info->accessed=access_time;
if (update && curr_file_info->used && curr_file_info->closed)
......@@ -444,7 +444,7 @@ static int examine_log(my_string file_name, char **table_names)
files_open++;
file_info.closed=0;
}
VOID(tree_insert(&tree,(gptr) &file_info,0));
VOID(tree_insert(&tree, (gptr) &file_info, 0, tree.custom_arg));
if (file_info.used)
{
if (verbose && !record_pos_file)
......@@ -463,7 +463,7 @@ static int examine_log(my_string file_name, char **table_names)
{
if (!curr_file_info->closed)
files_open--;
VOID(tree_delete(&tree,(gptr) curr_file_info));
VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
}
break;
case LOG_EXTRA:
......
This diff is collapsed.
......@@ -49,10 +49,6 @@ link_sources:
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \
done; \
for f in $(mystringsgen); do \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ ../strings/$$f $(srcdir)/$$f; \
done; \
for f in $$qs; do \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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