diff --git a/.bzrignore b/.bzrignore index 10bfea9154d..388dcac2ca6 100644 --- a/.bzrignore +++ b/.bzrignore @@ -312,6 +312,7 @@ emacs.h extra/charset2html extra/comp_err extra/created_include_files +extra/innochecksum extra/my_print_defaults extra/mysql_install extra/mysql_tzinfo_to_sql @@ -477,6 +478,8 @@ libmysqld/sql_cache.cc libmysqld/sql_class.cc libmysqld/sql_command libmysqld/sql_crypt.cc +libmysqld/sql_cursor.cc +libmysqld/sql_cursor.h libmysqld/sql_db.cc libmysqld/sql_delete.cc libmysqld/sql_derived.cc @@ -858,6 +861,7 @@ ndb/test/ndbapi/testNodeRestart ndb/test/ndbapi/testOIBasic ndb/test/ndbapi/testOperations ndb/test/ndbapi/testRestartGci +ndb/test/ndbapi/testSRBank ndb/test/ndbapi/testScan ndb/test/ndbapi/testScan.dsp ndb/test/ndbapi/testScanInterpreter diff --git a/BUILD/FINISH.sh b/BUILD/FINISH.sh index 8cd78bf4165..2fc8015ea28 100644 --- a/BUILD/FINISH.sh +++ b/BUILD/FINISH.sh @@ -14,7 +14,7 @@ path=`dirname $0` if [ -z "$just_clean" ] then commands="$commands -CFLAGS=\"$cflags\" CXX=\"$CXX\" CXXFLAGS=\"$cxxflags\" CXXLDFLAGS=\"$CXXLDFLAGS\" \ +CC=\"$CC\" CFLAGS=\"$cflags\" CXX=\"$CXX\" CXXFLAGS=\"$cxxflags\" CXXLDFLAGS=\"$CXXLDFLAGS\" \ $configure" fi diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 1603cfadbed..96ec5803b63 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -10,6 +10,11 @@ prefix_configs="--prefix=/usr/local/mysql" just_print= just_configure= full_debug= +if test -n "$MYSQL_BUILD_PREFIX" +then + prefix_configs="--prefix=$MYSQL_BUILD_PREFIX" +fi + while test $# -gt 0 do case "$1" in @@ -47,10 +52,11 @@ global_warnings="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wch #debug_extra_warnings="-Wuninitialized" c_warnings="$global_warnings -Wunused" cxx_warnings="$global_warnings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor" - -base_max_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-openssl --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine" -max_leave_isam_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-federated-storage-engine --with-blackhole-storage-engine --with-openssl --with-embedded-server --with-big-tables" +base_max_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-openssl --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine --with-csv-storage-engine" +base_max_no_ndb_configs="--with-innodb --with-berkeley-db --without-ndbcluster --with-archive-storage-engine --with-openssl --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine --with-csv-storage-engine" +max_leave_isam_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-federated-storage-engine --with-blackhole-storage-engine --with-csv-storage-engine --with-openssl --with-embedded-server --with-big-tables" max_configs="$base_max_configs --with-embedded-server" +max_no_ndb_configs="$base_max_no_ndb_configs --with-embedded-server" path=`dirname $0` . "$path/check-cpu" @@ -98,6 +104,10 @@ else make=make fi +if test -z "$CC" ; then + CC=gcc +fi + if test -z "$CXX" ; then CXX=gcc fi diff --git a/BUILD/autorun.sh b/BUILD/autorun.sh index 47a80a709a8..f5986720b48 100755 --- a/BUILD/autorun.sh +++ b/BUILD/autorun.sh @@ -7,7 +7,7 @@ aclocal || die "Can't execute aclocal" autoheader || die "Can't execute autoheader" # --force means overwrite ltmain.sh script if it already exists # Added glibtoolize reference to make native OSX autotools work -if [ -f /usr/bin/glibtoolize ] ; then +if test -f /usr/bin/glibtoolize ; then glibtoolize --automake --force || die "Can't execute glibtoolize" else libtoolize --automake --force || die "Can't execute libtoolize" diff --git a/BUILD/compile-pentium-debug-max-no-ndb b/BUILD/compile-pentium-debug-max-no-ndb new file mode 100755 index 00000000000..26ec7eacc9d --- /dev/null +++ b/BUILD/compile-pentium-debug-max-no-ndb @@ -0,0 +1,11 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" $@ --with-debug=full + +extra_flags="$pentium_cflags $debug_cflags $max_cflags" +c_warnings="$c_warnings $debug_extra_warnings" +cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$pentium_configs $debug_configs $max_no_ndb_configs" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium-icc b/BUILD/compile-pentium-icc index eee8b6c9d90..bf550a4b574 100755 --- a/BUILD/compile-pentium-icc +++ b/BUILD/compile-pentium-icc @@ -8,29 +8,16 @@ path=`dirname $0` CC=icc CXX=icpc CXXLD="$CXX -static-libcxa" -export CC CXX - - -extra_flags="$pentium_cflags $debug_cflags $max_cflags -USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify -DMYSQL_SERVER_SUFFIX=-valgrind-max" - -# Disable following warnings as these are generated by header files: -# 161 unrecognized pragma -# 444 destructor for base class xxx is not virtual -# 279 controlling expression is constant -# 810 conversion from ulonglong to ulong with cast -# 981 operands are evaluated in unspecified order -# 1292 warning for unknown 'attribute' options -# 1469 "xxx" clobber ignored -# 1572 floating-point equality and inequality comparisons are unreliable - -# In C++ -# 869 parameter "xxx" was never referenced -# (Problem with virtual functions) -# 874 support for placement delete is disabled +export CC CXX CXXLD c_warnings="" cxx_warnings="" -extra_flags="-O3 -unroll2 -ip -mp -no-gcc -restrict" +extra_flags="$fast_cflags -unroll2 -ip -mp -restrict" + +# Use -no-ipo if you get this error +# IPO link: can not find "-lstdc++_shared" +# icpc: error: problem during multi-file optimization compilation (code 1) +extra_flags="$extra_flags -no-ipo" base_cxxflags="-fno-exceptions -fno-rtti" extra_configs="$pentium_configs $static_link" diff --git a/BUILD/compile-pentium-icc-yassl b/BUILD/compile-pentium-icc-yassl new file mode 100644 index 00000000000..53b191e4db3 --- /dev/null +++ b/BUILD/compile-pentium-icc-yassl @@ -0,0 +1,24 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +# Note that we can't use ccache with icc as the generated .deps file will +# then contain wrong information +CC=icc +CXX=icpc +CXXLD="$CXX -static-libcxa" +export CC CXX CXXLD + +c_warnings="" +cxx_warnings="" +extra_flags="$fast_cflags -unroll2 -ip -mp -restrict" + +# Use -no-ipo if you get this error +# IPO link: can not find "-lstdc++_shared" +# icpc: error: problem during multi-file optimization compilation (code 1) +extra_flags="$extra_flags -no-ipo" +base_cxxflags="-fno-exceptions -fno-rtti" +extra_configs="$pentium_configs $static_link --with-yassl" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium64-valgrind-max b/BUILD/compile-pentium64-valgrind-max old mode 100644 new mode 100755 diff --git a/BUILD/compile-ppc-debug-max-no-ndb b/BUILD/compile-ppc-debug-max-no-ndb new file mode 100755 index 00000000000..a5b922a1ec9 --- /dev/null +++ b/BUILD/compile-ppc-debug-max-no-ndb @@ -0,0 +1,11 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$ppc_cflags $debug_cflags $max_cflags" +c_warnings="$c_warnings $debug_extra_warnings" +cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$debug_configs $max_no_ndb_configs" + +. "$path/FINISH.sh" diff --git a/BitKeeper/etc/RESYNC_TREE b/BitKeeper/etc/RESYNC_TREE new file mode 100644 index 00000000000..e69de29bb2d diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config index 81e867e514f..b68810b77ac 100644 --- a/BitKeeper/etc/config +++ b/BitKeeper/etc/config @@ -73,5 +73,6 @@ hours: [nick:]checkout:get [jonas:]checkout:get [tomas:]checkout:get +[guilhem:]checkout:get checkout:edit eoln:unix diff --git a/Makefile.am b/Makefile.am index 353a05eeb14..403a4ba2137 100644 --- a/Makefile.am +++ b/Makefile.am @@ -97,12 +97,6 @@ tags: support-files/build-tags .PHONY: init-db bin-dist -# Test installation - -test: - cd mysql-test; \ - ./mysql-test-run && ./mysql-test-run --ps-protocol - # Test installation. Ports are configurable from the environment. MYSQL_TEST_MANAGER_PORT = 9305 @@ -113,15 +107,26 @@ MYSQL_TEST_RUN_ARGS = --manager-port=$(MYSQL_TEST_MANAGER_PORT) \ --master_port=$(MYSQL_TEST_MASTER_PORT) \ --slave_port=$(MYSQL_TEST_SLAVE_PORT) \ --ndbcluster_port=$(MYSQL_TEST_NDB_PORT) + test: cd mysql-test ; \ - ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) && \ - ./mysql-test-run.pl --ps-protocol $(MYSQL_TEST_RUN_ARGS) + ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) && \ + ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) --ps-protocol test-force: cd mysql-test ; \ - ./mysql-test-run --force $(MYSQL_TEST_RUN_ARGS) ; \ - ./mysql-test-run --ps-protocol --force $(MYSQL_TEST_RUN_ARGS) + ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) --force ; \ + ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) --ps-protocol --force + +test-pl: + cd mysql-test ; \ + ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) && \ + ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) --ps-protocol + +test-force-pl: + cd mysql-test ; \ + ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) --force ; \ + ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) --ps-protocol --force # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/README b/README index 29851358765..88cdaaf67d4 100644 --- a/README +++ b/README @@ -1,52 +1,35 @@ -This is a release of MySQL, a GPL (free) SQL database server (more -licence information in the PUBLIC file and in the reference manual). +This is a release of MySQL, a dual-license SQL database server. +MySQL is brought to you by the MySQL team at MySQL AB. -Please read the "Upgrading from..." section in the manual first, if you are -migrating from older versions of MySQL! +License information can be found in these files: +- For GPL (free) distributions, see the COPYING file. +- For commercial distributions, see the MySQLEULA.txt file. -The latest information about MySQL can be found at: -http://www.mysql.com -To see what it can do take a look at the features section in the -manual. +For further information about MySQL or additional documentation, see: +- The latest information about MySQL: http://www.mysql.com +- The current MySQL documentation: http:/dev.mysql.com/doc -For installation instructions see the Installation chapter in the -manual. +Some manual sections of special interest: -For future plans see the TODO appendix in the manual. +- If you are migrating from an older version of MySQL, please read the + "Upgrading from..." section first! +- To see what MySQL can do, take a look at the features section. +- For installation instructions, see the Installation chapter. +- For future plans, see the TODO appendix. +- For the new features/bugfix history, see the News appendix. +- For the currently known bugs/misfeatures (known errors) see the problems + appendix. +- For a list of developers and other contributors, see the Credits + appendix. -New features/bug fixes history is in the news appendix in the manual. - -For the currently known bugs/misfeatures (known errors) see the bugs -appendix in the manual. - -For examples of SQL and benchmarking information see the bench -directory. - -The manual mentioned above can be found in the Docs directory. The -manual is available in the following formats: as plain ASCII text in -Docs/manual.txt, in HTML format in Docs/manual_toc.html, as GNU Info in -Docs/mysql.info and as PostScript in Docs/manual.ps. - -MySQL is brought to you by the MySQL team at MySQL AB - -For a list of developers and other contributors, see the Credits appendix -in the manual. +A local copy of the MySQL Reference Manual can be found in the Docs +directory in GNU Info format. You can also browse the manual online or +download it in any of several formats at the URL given earlier in this +file. ************************************************************ IMPORTANT: -Send bug (error) reports, questions and comments to the mailing list -at mysql@lists.mysql.com - -Please use the 'mysqlbug' script when posting bug reports or questions -about MySQL. mysqlbug will gather some information about your system -and start your editor with a form in which you can describe your -problem. Bug reports might be silently ignored by the MySQL -maintainers if there is not a good reason included in the report as to -why mysqlbug has not been used. A report that says 'MySQL does not -work for me. Why?' is not considered a valid bug report. - -The mysqlbug script can be found in the 'scripts' directory of the -distribution, that is '/scripts'. +Bug or error reports should be sent to http://bugs.mysql.com. diff --git a/VC++Files/bdb/bdb.vcproj b/VC++Files/bdb/bdb.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/client/mysql.vcproj b/VC++Files/client/mysql.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/client/mysqladmin.vcproj b/VC++Files/client/mysqladmin.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/client/mysqlclient.vcproj b/VC++Files/client/mysqlclient.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/client/mysqldump.vcproj b/VC++Files/client/mysqldump.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/client/mysqlimport.vcproj b/VC++Files/client/mysqlimport.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/client/mysqlshow.vcproj b/VC++Files/client/mysqlshow.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/client/mysqltest.vcproj b/VC++Files/client/mysqltest.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/comp_err/comp_err.vcproj b/VC++Files/comp_err/comp_err.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/dbug/dbug.vcproj b/VC++Files/dbug/dbug.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/heap/heap.vcproj b/VC++Files/heap/heap.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/innobase/innobase.vcproj b/VC++Files/innobase/innobase.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/isam/isam.dsp b/VC++Files/isam/isam.dsp deleted file mode 100644 index 759a1b6ee03..00000000000 --- a/VC++Files/isam/isam.dsp +++ /dev/null @@ -1,260 +0,0 @@ -# Microsoft Developer Studio Project File - Name="isam" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=isam - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "isam.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "isam.mak" CFG="isam - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "isam - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "isam - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE "isam - Win32 TLS_DEBUG" (based on "Win32 (x86) Static Library") -!MESSAGE "isam - Win32 TLS" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=xicl6.exe -RSC=rc.exe - -!IF "$(CFG)" == "isam - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "release" -# PROP Intermediate_Dir "release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "DBUG_OFF" /D "_WINDOWS" /D "NDEBUG" /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=xilink6.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\lib_release\isam.lib" - -!ELSEIF "$(CFG)" == "isam - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "debug" -# PROP Intermediate_Dir "debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=xilink6.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\lib_Debug\isam.lib" - -!ELSEIF "$(CFG)" == "isam - Win32 TLS_DEBUG" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "isam___Win32_TLS_DEBUG" -# PROP BASE Intermediate_Dir "isam___Win32_TLS_DEBUG" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "isam___Win32_TLS_DEBUG" -# PROP Intermediate_Dir "isam___Win32_TLS_DEBUG" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c -# SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /Gf /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /D "USE_TLS" /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo /out:"..\lib_Debug\isam_tls.lib" -# ADD LIB32 /nologo /out:"..\lib_Debug\isam_tls.lib" - -!ELSEIF "$(CFG)" == "isam - Win32 TLS" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "isam___Win32_TLS" -# PROP BASE Intermediate_Dir "isam___Win32_TLS" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "isam___Win32_TLS" -# PROP Intermediate_Dir "isam___Win32_TLS" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "DBUG_OFF" /D "_WINDOWS" /D "NDEBUG" /FD /c -# SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "DBUG_OFF" /D "_WINDOWS" /D "NDEBUG" /D "USE_TLS" /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo /out:"..\lib_release\isam_tls.lib" -# ADD LIB32 /nologo /out:"..\lib_release\isam_tls.lib" - -!ENDIF - -# Begin Target - -# Name "isam - Win32 Release" -# Name "isam - Win32 Debug" -# Name "isam - Win32 TLS_DEBUG" -# Name "isam - Win32 TLS" -# Begin Source File - -SOURCE=.\_cache.c -# End Source File -# Begin Source File - -SOURCE=.\_dbug.c -# End Source File -# Begin Source File - -SOURCE=.\_dynrec.c -# End Source File -# Begin Source File - -SOURCE=.\_key.c -# End Source File -# Begin Source File - -SOURCE=.\_locking.c -# End Source File -# Begin Source File - -SOURCE=.\_packrec.c -# End Source File -# Begin Source File - -SOURCE=.\_page.c -# End Source File -# Begin Source File - -SOURCE=.\_search.c -# End Source File -# Begin Source File - -SOURCE=.\_statrec.c -# End Source File -# Begin Source File - -SOURCE=.\changed.c -# End Source File -# Begin Source File - -SOURCE=.\close.c -# End Source File -# Begin Source File - -SOURCE=.\create.c -# End Source File -# Begin Source File - -SOURCE=.\delete.c -# End Source File -# Begin Source File - -SOURCE=.\extra.c -# End Source File -# Begin Source File - -SOURCE=.\info.c -# End Source File -# Begin Source File - -SOURCE=.\log.c -# End Source File -# Begin Source File - -SOURCE=.\open.c -# End Source File -# Begin Source File - -SOURCE=.\panic.c -# End Source File -# Begin Source File - -SOURCE=.\range.c -# End Source File -# Begin Source File - -SOURCE=.\rfirst.c -# End Source File -# Begin Source File - -SOURCE=.\rkey.c -# End Source File -# Begin Source File - -SOURCE=.\rlast.c -# End Source File -# Begin Source File - -SOURCE=.\rnext.c -# End Source File -# Begin Source File - -SOURCE=.\rprev.c -# End Source File -# Begin Source File - -SOURCE=.\rrnd.c -# End Source File -# Begin Source File - -SOURCE=.\rsame.c -# End Source File -# Begin Source File - -SOURCE=.\rsamepos.c -# End Source File -# Begin Source File - -SOURCE=.\static.c -# End Source File -# Begin Source File - -SOURCE=.\update.c -# End Source File -# Begin Source File - -SOURCE=.\write.c -# End Source File -# End Target -# End Project diff --git a/VC++Files/isam/isam.dsw b/VC++Files/isam/isam.dsw deleted file mode 100644 index c18224a6d73..00000000000 --- a/VC++Files/isam/isam.dsw +++ /dev/null @@ -1,28 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 5.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "isam"=".\isam.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### diff --git a/VC++Files/isam/isam_ia64.dsp b/VC++Files/isam/isam_ia64.dsp deleted file mode 100644 index f9dce0bed4a..00000000000 --- a/VC++Files/isam/isam_ia64.dsp +++ /dev/null @@ -1,260 +0,0 @@ -# Microsoft Developer Studio Project File - Name="isam" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=isam - WinIA64 TLS -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "isam.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "isam.mak" CFG="isam - WinIA64 TLS" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "isam - WinIA64 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "isam - WinIA64 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE "isam - WinIA64 TLS_DEBUG" (based on "Win32 (x86) Static Library") -!MESSAGE "isam - WinIA64 TLS" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "isam - WinIA64 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "release" -# PROP Intermediate_Dir "release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN64" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /Zi /O2 /I "../include" /D "DBUG_OFF" /D "_WINDOWS" /D "NDEBUG" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\lib_release\isam.lib" - -!ELSEIF "$(CFG)" == "isam - WinIA64 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "debug" -# PROP Intermediate_Dir "debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN64" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MTd /W3 /Zi /Od /GF /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\lib_Debug\isam.lib" - -!ELSEIF "$(CFG)" == "isam - WinIA64 TLS_DEBUG" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "isam___WinIA64_TLS_DEBUG" -# PROP BASE Intermediate_Dir "isam___WinIA64_TLS_DEBUG" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "isam___WinIA64_TLS_DEBUG" -# PROP Intermediate_Dir "isam___WinIA64_TLS_DEBUG" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /G6 /MTd /W3 /Z7 /Od /GF /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /FD /c -# SUBTRACT BASE CPP /YX -# ADD CPP /nologo /MTd /W3 /Zi /O2 /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /D "USE_TLS" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo /out:"..\lib_Debug\isam_tls.lib" -# ADD LIB32 /nologo /out:"..\lib_Debug\isam_tls.lib" - -!ELSEIF "$(CFG)" == "isam - WinIA64 TLS" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "isam___WinIA64_TLS" -# PROP BASE Intermediate_Dir "isam___WinIA64_TLS" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "isam___WinIA64_TLS" -# PROP Intermediate_Dir "isam___WinIA64_TLS" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "DBUG_OFF" /D "_WINDOWS" /D "NDEBUG" /FD /c -# SUBTRACT BASE CPP /YX -# ADD CPP /nologo /MT /W3 /Zi /O2 /I "../include" /D "DBUG_OFF" /D "_WINDOWS" /D "NDEBUG" /D "USE_TLS" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo /out:"..\lib_release\isam_tls.lib" -# ADD LIB32 /nologo /out:"..\lib_release\isam_tls.lib" - -!ENDIF - -# Begin Target - -# Name "isam - WinIA64 Release" -# Name "isam - WinIA64 Debug" -# Name "isam - WinIA64 TLS_DEBUG" -# Name "isam - WinIA64 TLS" -# Begin Source File - -SOURCE=.\_cache.c -# End Source File -# Begin Source File - -SOURCE=.\_dbug.c -# End Source File -# Begin Source File - -SOURCE=.\_dynrec.c -# End Source File -# Begin Source File - -SOURCE=.\_key.c -# End Source File -# Begin Source File - -SOURCE=.\_locking.c -# End Source File -# Begin Source File - -SOURCE=.\_packrec.c -# End Source File -# Begin Source File - -SOURCE=.\_page.c -# End Source File -# Begin Source File - -SOURCE=.\_search.c -# End Source File -# Begin Source File - -SOURCE=.\_statrec.c -# End Source File -# Begin Source File - -SOURCE=.\changed.c -# End Source File -# Begin Source File - -SOURCE=.\close.c -# End Source File -# Begin Source File - -SOURCE=.\create.c -# End Source File -# Begin Source File - -SOURCE=.\delete.c -# End Source File -# Begin Source File - -SOURCE=.\extra.c -# End Source File -# Begin Source File - -SOURCE=.\info.c -# End Source File -# Begin Source File - -SOURCE=.\log.c -# End Source File -# Begin Source File - -SOURCE=.\open.c -# End Source File -# Begin Source File - -SOURCE=.\panic.c -# End Source File -# Begin Source File - -SOURCE=.\range.c -# End Source File -# Begin Source File - -SOURCE=.\rfirst.c -# End Source File -# Begin Source File - -SOURCE=.\rkey.c -# End Source File -# Begin Source File - -SOURCE=.\rlast.c -# End Source File -# Begin Source File - -SOURCE=.\rnext.c -# End Source File -# Begin Source File - -SOURCE=.\rprev.c -# End Source File -# Begin Source File - -SOURCE=.\rrnd.c -# End Source File -# Begin Source File - -SOURCE=.\rsame.c -# End Source File -# Begin Source File - -SOURCE=.\rsamepos.c -# End Source File -# Begin Source File - -SOURCE=.\static.c -# End Source File -# Begin Source File - -SOURCE=.\update.c -# End Source File -# Begin Source File - -SOURCE=.\write.c -# End Source File -# End Target -# End Project diff --git a/VC++Files/isamchk/isamchk.dsp b/VC++Files/isamchk/isamchk.dsp deleted file mode 100644 index 2026be94ea0..00000000000 --- a/VC++Files/isamchk/isamchk.dsp +++ /dev/null @@ -1,129 +0,0 @@ -# Microsoft Developer Studio Project File - Name="isamchk" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=isamchk - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "isamchk.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "isamchk.mak" CFG="isamchk - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "isamchk - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "isamchk - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE "isamchk - Win32 classic" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=xicl6.exe -RSC=rc.exe - -!IF "$(CFG)" == "isamchk - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "release" -# PROP Intermediate_Dir "release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../isam" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x41d /d "NDEBUG" -# ADD RSC /l 0x41d /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=xilink6.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 /subsystem:console /machine:I386 -# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /machine:I386 /out:"../client_release/isamchk.exe" -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "isamchk - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "isamchk_" -# PROP BASE Intermediate_Dir "isamchk_" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "debug" -# PROP Intermediate_Dir "debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /I "../isam" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c -# SUBTRACT CPP /Fr /YX -# ADD BASE RSC /l 0x41d /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=xilink6.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 /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/isamchk.exe" /pdbtype:sept -# SUBTRACT LINK32 /verbose /pdb:none - -!ELSEIF "$(CFG)" == "isamchk - Win32 classic" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "isamchk___Win32_classic" -# PROP BASE Intermediate_Dir "isamchk___Win32_classic" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "classic" -# PROP Intermediate_Dir "classic" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../isam" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /FD /c -# SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../isam" /D "_CONSOLE" /D "_WINDOWS" /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /D LICENSE=Commercial /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x41d /d "NDEBUG" -# ADD RSC /l 0x41d /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=xilink6.exe -# ADD BASE LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /machine:I386 /out:"../client_release/isamchk.exe" -# SUBTRACT BASE LINK32 /pdb:none -# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj ..\lib_release\isam.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/isamchk.exe" /libpath:"..\lib_release\\" -# SUBTRACT LINK32 /pdb:none - -!ENDIF - -# Begin Target - -# Name "isamchk - Win32 Release" -# Name "isamchk - Win32 Debug" -# Name "isamchk - Win32 classic" -# Begin Source File - -SOURCE=..\isam\isamchk.c -# End Source File -# Begin Source File - -SOURCE=..\isam\sort.c -# End Source File -# End Target -# End Project diff --git a/VC++Files/isamchk/isamchk_ia64.dsp b/VC++Files/isamchk/isamchk_ia64.dsp deleted file mode 100644 index 61eab230e1f..00000000000 --- a/VC++Files/isamchk/isamchk_ia64.dsp +++ /dev/null @@ -1,100 +0,0 @@ -# Microsoft Developer Studio Project File - Name="isamchk" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=isamchk - WinIA64 classic -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "isamchk_ia64.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "isamchk_ia64.mak" CFG="isamchk - WinIA64 classic" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "isamchk - WinIA64 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "isamchk - WinIA64 classic" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "isamchk - WinIA64 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "release" -# PROP Intermediate_Dir "release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -MTL=midl.exe -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN64" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /Zi /O2 /I "../include" /I "../isam" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x41d /d "NDEBUG" -# ADD RSC /l 0x41d /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# 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 /subsystem:console /machine:IA64 -# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj bufferoverflowU.lib ..\lib_release\isam.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib /nologo /subsystem:console /out:"../client_release/isamchk.exe" /machine:IA64 - -!ELSEIF "$(CFG)" == "isamchk - WinIA64 classic" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "isamchk___WinIA64_classic" -# PROP BASE Intermediate_Dir "isamchk___WinIA64_classic" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "classic" -# PROP Intermediate_Dir "classic" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -MTL=midl.exe -# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../isam" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /FD /c -# SUBTRACT BASE CPP /YX -# ADD CPP /nologo /MT /W3 /Zi /O2 /I "../include" /I "../isam" /D "_CONSOLE" /D "_WINDOWS" /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /D LICENSE=Commercial /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x41d /d "NDEBUG" -# ADD RSC /l 0x41d /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /out:"../client_release/isamchk.exe" /machine:IA64 -# ADD LINK32 ..\lib_release\isam.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj bufferoverflowU.lib /nologo /subsystem:console /out:"../client_classic/isamchk.exe" /libpath:"..\lib_release\\" /machine:IA64 - -!ENDIF - -# Begin Target - -# Name "isamchk - WinIA64 Release" -# Name "isamchk - WinIA64 classic" -# Begin Source File - -SOURCE=..\isam\isamchk.c -# End Source File -# Begin Source File - -SOURCE=..\isam\sort.c -# End Source File -# End Target -# End Project diff --git a/VC++Files/libmysql/libmysql.vcproj b/VC++Files/libmysql/libmysql.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/libmysqld/examples/test_libmysqld.vcproj b/VC++Files/libmysqld/examples/test_libmysqld.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp index 0fb3a645a48..87a88333a2a 100644 --- a/VC++Files/libmysqld/libmysqld.dsp +++ b/VC++Files/libmysqld/libmysqld.dsp @@ -396,10 +396,6 @@ SOURCE=..\sql\protocol.cpp # End Source File # Begin Source File -SOURCE=..\sql\protocol_cursor.cpp -# End Source File -# Begin Source File - SOURCE=..\sql\records.cpp # End Source File # Begin Source File @@ -556,6 +552,10 @@ SOURCE=..\sql\sql_trigger.cpp # End Source File # Begin Source File +SOURCE=..\sql\sql_cursor.cpp +# End Source File +# Begin Source File + SOURCE=..\sql\sql_udf.cpp # End Source File # Begin Source File diff --git a/VC++Files/libmysqld/libmysqld.vcproj b/VC++Files/libmysqld/libmysqld.vcproj old mode 100755 new mode 100644 index 187a63ece38..eb411f79362 --- a/VC++Files/libmysqld/libmysqld.vcproj +++ b/VC++Files/libmysqld/libmysqld.vcproj @@ -24,7 +24,7 @@ AdditionalIncludeDirectories="../include,../libmysqld,../sql,../regex,../extra/yassl/include,../bdb/build_win32,../zlib" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__" BasicRuntimeChecks="3" - RuntimeLibrary="0" + RuntimeLibrary="1" PrecompiledHeaderFile=".\debug/libmysqld.pch" AssemblerListingLocation=".\debug/" ObjectFile=".\debug/" @@ -37,11 +37,11 @@ Name="VCCustomBuildTool"/> + RelativePath="..\sql\sql_cursor.cpp"> @@ -63,7 +63,7 @@ @@ -117,6 +117,9 @@ + + diff --git a/VC++Files/mysys/mysys.dsp b/VC++Files/mysys/mysys.dsp index 230c2221b6e..935f1411530 100644 --- a/VC++Files/mysys/mysys.dsp +++ b/VC++Files/mysys/mysys.dsp @@ -369,6 +369,10 @@ SOURCE=.\my_compress.c # End Source File # Begin Source File +SOURCE=.\my_conio.c +# End Source File +# Begin Source File + SOURCE=.\my_copy.c # End Source File # Begin Source File diff --git a/VC++Files/mysys/mysys.vcproj b/VC++Files/mysys/mysys.vcproj old mode 100755 new mode 100644 index 3d53fd3923c..6ec9ca6d564 --- a/VC++Files/mysys/mysys.vcproj +++ b/VC++Files/mysys/mysys.vcproj @@ -1638,6 +1638,9 @@ PreprocessorDefinitions=""/> + + + + + + + + + + + + + + + + + + + -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=pack_isam - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "pack_isam.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "pack_isam.mak" CFG="pack_isam - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "pack_isam - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "pack_isam - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE "pack_isam - Win32 classic" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=xicl6.exe -RSC=rc.exe - -!IF "$(CFG)" == "pack_isam - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "release" -# PROP Intermediate_Dir "release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../isam" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=xilink6.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 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 /subsystem:console /machine:I386 -# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /machine:I386 /out:"../client_release/pack_isam.exe" - -!ELSEIF "$(CFG)" == "pack_isam - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "debug" -# PROP Intermediate_Dir "debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /I "../isam" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c -# SUBTRACT CPP /Fr -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=xilink6.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 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 /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib wsock32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /debug /machine:I386 /out:"../client_debug/pack_isam.exe" /pdbtype:sept - -!ELSEIF "$(CFG)" == "pack_isam - Win32 classic" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "pack_isam___Win32_classic" -# PROP BASE Intermediate_Dir "pack_isam___Win32_classic" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "classic" -# PROP Intermediate_Dir "classic" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../isam" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /FD /c -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../isam" /D "_CONSOLE" /D "_WINDOWS" /D LICENSE=Commercial /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=xilink6.exe -# ADD BASE LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /machine:I386 /out:"../client_release/pack_isam.exe" -# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj ..\lib_release\isam.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/pack_isam.exe" /libpath:"..\lib_release\\" - -!ENDIF - -# Begin Target - -# Name "pack_isam - Win32 Release" -# Name "pack_isam - Win32 Debug" -# Name "pack_isam - Win32 classic" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\isam\pack_isam.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/VC++Files/pack_isam/pack_isam_ia64.dsp b/VC++Files/pack_isam/pack_isam_ia64.dsp deleted file mode 100644 index 58b88f02f08..00000000000 --- a/VC++Files/pack_isam/pack_isam_ia64.dsp +++ /dev/null @@ -1,133 +0,0 @@ -# Microsoft Developer Studio Project File - Name="pack_isam" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=pack_isam - WinIA64 classic -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "pack_isam_ia64.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "pack_isam_ia64.mak" CFG="pack_isam - WinIA64 classic" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "pack_isam - WinIA64 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "pack_isam - WinIA64 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE "pack_isam - WinIA64 classic" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "pack_isam - WinIA64 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "release" -# PROP Intermediate_Dir "release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -MTL=midl.exe -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WinIA64" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /Zi /O2 /I "../include" /I "../isam" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /D "_IA64_" /D "WinIA64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# 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 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 /subsystem:console /machine:IA64 -# ADD LINK32 ..\lib_release\isam.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj bufferoverflowU.lib /nologo /subsystem:console /out:"../client_release/pack_isam.exe" /machine:IA64 - -!ELSEIF "$(CFG)" == "pack_isam - WinIA64 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "debug" -# PROP Intermediate_Dir "debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -MTL=midl.exe -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WinIA64" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Zi /Od /I "../include" /I "../isam" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "_IA64_" /D "WinIA64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c -# SUBTRACT CPP /Fr -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# 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 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 /subsystem:console /debug /machine:IA64 -# ADD LINK32 ..\lib_debug\dbug.lib ..\lib_debug\isam.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj bufferoverflowU.lib /nologo /subsystem:console /incremental:no /debug /out:"../client_debug/pack_isam.exe" /machine:IA64 - -!ELSEIF "$(CFG)" == "pack_isam - WinIA64 classic" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "pack_isam___WinIA64 _classic" -# PROP BASE Intermediate_Dir "pack_isam___WinIA64 _classic" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "classic" -# PROP Intermediate_Dir "classic" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -MTL=midl.exe -# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../isam" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /FD /c -# ADD CPP /nologo /MT /W3 /Zi /O2 /I "../include" /I "../isam" /D "_CONSOLE" /D "_WINDOWS" /D LICENSE=Commercial /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /D "_IA64_" /D "WinIA64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj /nologo /subsystem:console /out:"../client_release/pack_isam.exe" /machine:IA64 -# ADD LINK32 ..\lib_release\isam.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setargv.obj bufferoverflowU.lib /nologo /subsystem:console /out:"../client_classic/pack_isam.exe" /libpath:"..\lib_release\\" /machine:IA64 - -!ENDIF - -# Begin Target - -# Name "pack_isam - WinIA64 Release" -# Name "pack_isam - WinIA64 Debug" -# Name "pack_isam - WinIA64 classic" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\isam\pack_isam.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/VC++Files/perror/perror.vcproj b/VC++Files/perror/perror.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/regex/regex.vcproj b/VC++Files/regex/regex.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/replace/replace.vcproj b/VC++Files/replace/replace.vcproj old mode 100755 new mode 100644 diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index 6db2aca8d1c..7a9ad3e1c76 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -1283,10 +1283,6 @@ SOURCE=.\protocol.cpp # End Source File # Begin Source File -SOURCE=.\protocol_cursor.cpp -# End Source File -# Begin Source File - SOURCE=.\records.cpp !IF "$(CFG)" == "mysqld - Win32 Release" @@ -1863,6 +1859,10 @@ SOURCE=.\sql_trigger.cpp # End Source File # Begin Source File +SOURCE=.\sql_cursor.cpp +# End Source File +# Begin Source File + SOURCE=.\sql_udf.cpp # End Source File # Begin Source File diff --git a/VC++Files/sql/mysqld.vcproj b/VC++Files/sql/mysqld.vcproj old mode 100755 new mode 100644 index db84f081ac8..49bf74ae5a2 --- a/VC++Files/sql/mysqld.vcproj +++ b/VC++Files/sql/mysqld.vcproj @@ -1252,7 +1252,7 @@ + RelativePath="ha_archive.cpp"> + RelativePath="sql_cursor.cpp"> = 9 && + my_strnncoll(charset_info,(uchar*) name, + 9, + (const uchar*) "delimiter", 9))) + DBUG_RETURN((COMMANDS *) 0); if ((end=strcont(name," \t"))) { len=(uint) (end - name); @@ -1121,15 +1153,18 @@ static COMMANDS *find_command (char *name,char cmd_char) for (uint i= 0; commands[i].name; i++) { if (commands[i].func && - ((name && + ((name && !my_strnncoll(charset_info,(uchar*)name,len, (uchar*)commands[i].name,len) && !commands[i].name[len] && (!end || (end && commands[i].takes_params))) || !name && commands[i].cmd_char == cmd_char)) - return (&commands[i]); + { + DBUG_PRINT("exit",("found command: %s", commands[i].name)); + DBUG_RETURN(&commands[i]); + } } - return ((COMMANDS *) 0); + DBUG_RETURN((COMMANDS *) 0); } @@ -1140,15 +1175,16 @@ static bool add_line(String &buffer,char *line,char *in_string, char buff[80], *pos, *out; COMMANDS *com; bool need_space= 0; + DBUG_ENTER("add_line"); if (!line[0] && buffer.is_empty()) - return 0; + DBUG_RETURN(0); #ifdef HAVE_READLINE if (status.add_to_history && line[0] && not_in_history(line)) add_history(line); #endif #ifdef USE_MB - char *strend=line+(uint) strlen(line); + char *end_of_line=line+(uint) strlen(line); #endif for (pos=out=line ; (inchar= (uchar) *pos) ; pos++) @@ -1157,13 +1193,19 @@ static bool add_line(String &buffer,char *line,char *in_string, buffer.is_empty()) continue; #ifdef USE_MB - int l; + int length; if (use_mb(charset_info) && - (l = my_ismbchar(charset_info, pos, strend))) { - while (l--) - *out++ = *pos++; - pos--; - continue; + (length= my_ismbchar(charset_info, pos, end_of_line))) + { + if (!*ml_comment) + { + while (length--) + *out++ = *pos++; + pos--; + } + else + pos+= length - 1; + continue; } #endif if (!*ml_comment && inchar == '\\') @@ -1183,7 +1225,7 @@ static bool add_line(String &buffer,char *line,char *in_string, const String tmp(line,(uint) (out-line), charset_info); buffer.append(tmp); if ((*com->func)(&buffer,pos-1) > 0) - return 1; // Quit + DBUG_RETURN(1); // Quit if (com->takes_params) { for (pos++ ; @@ -1201,29 +1243,40 @@ static bool add_line(String &buffer,char *line,char *in_string, { sprintf(buff,"Unknown command '\\%c'.",inchar); if (put_info(buff,INFO_ERROR) > 0) - return 1; + DBUG_RETURN(1); *out++='\\'; *out++=(char) inchar; continue; } } - - else if (!*ml_comment && (*pos == *delimiter && - is_prefix(pos + 1, delimiter + 1)) && - !*in_string) + else if (!*ml_comment && !*in_string && + (*pos == *delimiter && is_prefix(pos + 1, delimiter + 1) || + buffer.length() == 0 && (out - line) >= 9 && + !my_strcasecmp(charset_info, line, "delimiter"))) { uint old_delimiter_length= delimiter_length; if (out != line) buffer.append(line, (uint) (out - line)); // Add this line if ((com= find_command(buffer.c_ptr(), 0))) { + if (com->func == com_delimiter) + { + /* + Delimiter wants the get rest of the given line as argument to + allow one to change ';' to ';;' and back + */ + char *end= strend(pos); + buffer.append(pos, (uint) (end - pos)); + /* Ensure pos will point at \0 after the pos+= below */ + pos= end - old_delimiter_length + 1; + } if ((*com->func)(&buffer, buffer.c_ptr()) > 0) - return 1; // Quit + DBUG_RETURN(1); // Quit } else { if (com_go(&buffer, 0) > 0) // < 0 is not fatal - return 1; + DBUG_RETURN(1); } buffer.length(0); out= line; @@ -1275,9 +1328,9 @@ static bool add_line(String &buffer,char *line,char *in_string, if (buffer.length() + length >= buffer.alloced_length()) buffer.realloc(buffer.length()+length+IO_SIZE); if (!(*ml_comment) && buffer.append(line,length)) - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } /***************************************************************** diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index fb9ed3af70c..ffb653eabdb 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1003,7 +1003,8 @@ static int dump_remote_log_entries(const char* logname) { char buf[128]; LAST_EVENT_INFO last_event_info; - uint len, logname_len; + ulong len; + uint logname_len; NET* net; int error= 0; my_off_t old_off= start_position_mot; @@ -1434,7 +1435,7 @@ int main(int argc, char** argv) of transaction. */ fprintf(result_file, - "ROLLBACK;\n" + "# End of log file\nROLLBACK /* added by mysqlbinlog */;\n" "/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n"); if (disable_log_bin) fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n"); diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 35d57e0394e..2eb3e55c2e9 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -497,6 +497,9 @@ static int process_all_tables_in_db(char *database) static int use_db(char *database) { + if (mysql_get_server_version(sock) >= 50003 && + !my_strcasecmp(&my_charset_latin1, database, "information_schema")) + return 1; if (mysql_select_db(sock, database)) { DBerror(sock, "when selecting the database"); diff --git a/client/mysqldump.c b/client/mysqldump.c index 7c81f6909c1..0e7248697c2 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -30,7 +30,7 @@ ** master/autocommit code by Brian Aker ** SSL by ** Andrei Errapart -** Tõnu Samuel +** Tõnu Samuel ** XML by Gary Huntress 10/10/01, cleaned up ** and adapted to mysqldump 05/11/01 by Jani Tolonen ** Added --single-transaction option 06/06/2002 by Peter Zaitsev @@ -70,6 +70,11 @@ /* Size of buffer for dump's select query */ #define QUERY_LENGTH 1536 +/* ignore table flags */ +#define IGNORE_NONE 0x00 /* no ignore */ +#define IGNORE_DATA 0x01 /* don't dump data for this table */ +#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */ + static char *add_load_option(char *ptr, const char *object, const char *statement); static ulong find_set(TYPELIB *lib, const char *x, uint length, @@ -87,7 +92,7 @@ static my_bool verbose=0,tFlag=0,dFlag=0,quick= 1, extended_insert= 1, opt_single_transaction=0, opt_comments= 0, opt_compact= 0, opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0, opt_complete_insert= 0, opt_drop_database= 0, - opt_dump_triggers= 0; + opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1; static ulong opt_max_allowed_packet, opt_net_buffer_length; static MYSQL mysql_connection,*sock=0; static my_bool insert_pat_inited=0; @@ -209,9 +214,7 @@ static struct my_option my_long_options[] = {"default-character-set", OPT_DEFAULT_CHARSET, "Set the default character set.", (gptr*) &default_charset, (gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; " - "currently ignored because of http://bugs.mysql.com/bug.php?id=7815 " - "but will be re-enabled later", + {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; ", (gptr*) &opt_delayed, (gptr*) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"delete-master-logs", OPT_DELETE_MASTER_LOGS, @@ -339,6 +342,9 @@ static struct my_option my_long_options[] = {"result-file", 'r', "Direct output to a given file. This option should be used in MSDOS, because it prevents new line '\\n' from being converted to '\\r\\n' (carriage return + line feed).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"routines", 'R', "Dump routines FUNCTIONS and PROCEDURES.", + (gptr*) &opt_routines, (gptr*) &opt_routines, 0, GET_BOOL, + NO_ARG, 0, 0, 0, 0, 0, 0}, {"set-charset", OPT_SET_CHARSET, "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.", (gptr*) &opt_set_charset, (gptr*) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1, @@ -379,6 +385,9 @@ static struct my_option my_long_options[] = {"triggers", OPT_TRIGGERS, "Dump triggers for each dumped table", (gptr*) &opt_dump_triggers, (gptr*) &opt_dump_triggers, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"tz-utc", OPT_TZ_UTC, + "SET TIME_ZONE='+00:00' at top of dump to allow dumping of TIMESTAMP data between servers with different time zones.", + (gptr*) &opt_tz_utc, (gptr*) &opt_tz_utc, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, #ifndef DONT_ALLOW_USER_CHANGE {"user", 'u', "User for login if not current user.", (gptr*) ¤t_user, (gptr*) ¤t_user, 0, GET_STR, REQUIRED_ARG, @@ -408,7 +417,7 @@ static int init_dumping(char *); static int dump_databases(char **); static int dump_all_databases(); static char *quote_name(const char *name, char *buff, my_bool force); -static const char *check_if_ignore_table(const char *table_name); +char check_if_ignore_table(const char *table_name, char *table_type); static char *primary_key_fields(const char *table_name); static my_bool get_view_structure(char *table, char* db); static my_bool dump_all_views_in_db(char *database); @@ -503,6 +512,13 @@ static void write_header(FILE *sql_file, char *db_name) "\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;" "\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;" "\n/*!40101 SET NAMES %s */;\n",default_charset); + + if (opt_tz_utc) + { + fprintf(sql_file, "/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n"); + fprintf(sql_file, "/*!40103 SET TIME_ZONE='+00:00' */;\n"); + } + if (!path) { fprintf(md_result_file,"\ @@ -529,6 +545,9 @@ static void write_footer(FILE *sql_file) } else if (!opt_compact) { + if (opt_tz_utc) + fprintf(sql_file,"/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n"); + fprintf(sql_file,"\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n"); if (!path) { @@ -717,25 +736,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } break; } -#ifndef REMOVE_THIS_CODE_WHEN_FIX_BUG_7815 - case (int) OPT_DELAYED: - /* - Because of http://bugs.mysql.com/bug.php?id=7815, we disable - --delayed-insert; when the bug gets fixed by checking the storage engine - (using the table definition cache) before printing INSERT DELAYED, we - can correct the option's description and re-enable it again (scheduled - for later 5.0 or 5.1 versions). - It's ok to do the if() below as get_one_option is called after - opt_delayed is set. - */ - if (opt_delayed) - { - fprintf(stderr, "Warning: ignoring --delayed-insert (as explained " - "in the output of 'mysqldump --help').\n"); - opt_delayed= 0; - } - break; -#endif } return 0; } @@ -915,6 +915,20 @@ static int dbConnect(char *host, char *user,char *passwd) safe_exit(EX_MYSQLERR); return 1; } + /* + set time_zone to UTC to allow dumping date types between servers with + different time zone settings + */ + if (opt_tz_utc) + { + my_snprintf(buff, sizeof(buff), "/*!40103 SET TIME_ZONE='+00:00' */"); + if (mysql_query_with_error_report(sock, 0, buff)) + { + mysql_close(sock); + safe_exit(EX_MYSQLERR); + return 1; + } + } return 0; } /* dbConnect */ @@ -961,6 +975,22 @@ static my_bool test_if_special_chars(const char *str) +/* + quote_name(name, buff, force) + + Quotes char string, taking into account compatible mode + + Args + + name Unquoted string containing that which will be quoted + buff The buffer that contains the quoted value, also returned + force Flag to make it ignore 'test_if_special_chars' + + Returns + + buff quoted string + +*/ static char *quote_name(const char *name, char *buff, my_bool force) { char *to= buff; @@ -1157,7 +1187,7 @@ static void print_xml_row(FILE *xml_file, const char *row_name, uint i; MYSQL_FIELD *field; ulong *lengths= mysql_fetch_lengths(tableRes); - + fprintf(xml_file, "\t\t<%s", row_name); check_io(xml_file); mysql_field_seek(tableRes, 0); @@ -1177,21 +1207,131 @@ static void print_xml_row(FILE *xml_file, const char *row_name, check_io(xml_file); } +/* + dump_routines_for_db + -- retrievs list of routines for a given db, and prints out + the CREATE PROCEDURE definition into the output (the dump). + + This function has logic to print the appropriate syntax depending on whether + this is a procedure or functions + + RETURN + 0 Success + 1 Error +*/ + +static uint dump_routines_for_db(char *db) +{ + char query_buff[512]; + const char *routine_type[]= {"FUNCTION", "PROCEDURE"}; + char db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3]; + char *routine_name; + int i; + FILE *sql_file= md_result_file; + MYSQL_RES *routine_res, *routine_list_res; + MYSQL_ROW row, routine_list_row; + DBUG_ENTER("dump_routines_for_db"); + DBUG_PRINT("enter", ("db: '%s'", db)); + + mysql_real_escape_string(sock, db_name_buff, db, strlen(db)); + + /* nice comments */ + if (opt_comments) + fprintf(sql_file, "\n--\n-- Dumping routines for database '%s'\n--\n", db); + + /* + not using "mysql_query_with_error_report" because we may have not + enough privileges to lock mysql.proc. + */ + if (lock_tables) + mysql_query(sock, "LOCK TABLES mysql.proc READ"); + + fprintf(sql_file, "DELIMITER ;;\n"); + + /* 0, retrieve and dump functions, 1, procedures */ + for (i= 0; i <= 1; i++) + { + my_snprintf(query_buff, sizeof(query_buff), + "SHOW %s STATUS WHERE Db = '%s'", + routine_type[i], db_name_buff); + + if (mysql_query_with_error_report(sock, &routine_list_res, query_buff)) + DBUG_RETURN(1); + + if (mysql_num_rows(routine_list_res)) + { + + while ((routine_list_row= mysql_fetch_row(routine_list_res))) + { + DBUG_PRINT("info", ("retrieving CREATE %s for %s", routine_type[i], + name_buff)); + routine_name= quote_name(routine_list_row[1], name_buff, 0); + my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE %s %s", + routine_type[i], routine_name); + + if (mysql_query_with_error_report(sock, &routine_res, query_buff)) + DBUG_RETURN(1); + + while ((row= mysql_fetch_row(routine_res))) + { + /* + if the user has EXECUTE privilege he see routine names, but NOT the + routine body of other routines that are not the creator of! + */ + DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d", + routine_name, row[2], strlen(row[2]))); + if (strlen(row[2])) + { + if (opt_drop) + fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;;\n", + routine_type[i], routine_name); + /* + we need to change sql_mode only for the CREATE + PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name + */; + fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n", + row[1] /* sql_mode */); + fprintf(sql_file, "/*!50003 %s */;;\n", row[2]); + fprintf(sql_file, + "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/" + ";;\n"); + } + } /* end of routine printing */ + } /* end of list of routines */ + mysql_free_result(routine_res); + } + mysql_free_result(routine_list_res); + } /* end of for i (0 .. 1) */ + /* set the delimiter back to ';' */ + fprintf(sql_file, "DELIMITER ;\n"); + + if (lock_tables) + mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"); + DBUG_RETURN(0); +} /* - getTableStructure -- retrievs database structure, prints out corresponding - CREATE statement and fills out insert_pat. + get_table_structure -- retrievs database structure, prints out corresponding + CREATE statement and fills out insert_pat if the table is the type we will + be dumping. + + ARGS + table - table name + db - db name + table_type - table type ie "InnoDB" + ignore_flag - what we must particularly ignore - see IGNORE_ defines above RETURN number of fields in table, 0 if error */ -static uint get_table_structure(char *table, char *db) +static uint get_table_structure(char *table, char *db, char *table_type, + char *ignore_flag) { MYSQL_RES *tableRes; MYSQL_ROW row; - my_bool init=0; - uint numFields; + my_bool init=0, delayed, write_data, complete_insert; + uint num_fields; char *result_table, *opt_quoted_table; const char *insert_option; char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3]; @@ -1200,18 +1340,32 @@ static uint get_table_structure(char *table, char *db) FILE *sql_file = md_result_file; int len; DBUG_ENTER("get_table_structure"); - DBUG_PRINT("enter", ("db: %s, table: %s", db, table)); + DBUG_PRINT("enter", ("db: %s table: %s", db, table)); - if (!insert_pat_inited) + *ignore_flag= check_if_ignore_table(table, table_type); + + delayed= opt_delayed; + if (delayed && (*ignore_flag & IGNORE_INSERT_DELAYED)) { - insert_pat_inited= init_dynamic_string(&insert_pat, "", 1024, 1024); + delayed= 0; + if (verbose) + fprintf(stderr, + "-- Warning: Unable to use delayed inserts for table '%s' " + "because it's of type %s\n", table, table_type); } - else - dynstr_set(&insert_pat, ""); - insert_option= ((opt_delayed && opt_ignore) ? " DELAYED IGNORE " : - opt_delayed ? " DELAYED " : - opt_ignore ? " IGNORE " : ""); + complete_insert= 0; + if ((write_data= !(*ignore_flag & IGNORE_DATA))) + { + complete_insert= opt_complete_insert; + if (!insert_pat_inited) + insert_pat_inited= init_dynamic_string(&insert_pat, "", 1024, 1024); + else + dynstr_set(&insert_pat, ""); + } + + insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " : + delayed ? " DELAYED " : opt_ignore ? " IGNORE " : ""); if (verbose) fprintf(stderr, "-- Retrieving table structure for table %s...\n", table); @@ -1220,7 +1374,8 @@ static uint get_table_structure(char *table, char *db) "SET OPTION SQL_QUOTE_SHOW_CREATE=%d", (opt_quoted || opt_keywords)); if (!create_options) - strmov(query_buff+len, "/*!40102 ,SQL_MODE=concat(@@sql_mode, _utf8 ',NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS') */"); + strmov(query_buff+len, + "/*!40102 ,SQL_MODE=concat(@@sql_mode, _utf8 ',NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS') */"); result_table= quote_name(table, table_buff, 1); opt_quoted_table= quote_name(table, table_buff2, 0); @@ -1330,41 +1485,6 @@ static uint get_table_structure(char *table, char *db) fprintf(sql_file, "%s;\n", row[1]); check_io(sql_file); mysql_free_result(tableRes); - if (opt_dump_triggers && - mysql_get_server_version(sock) >= 50009) - { - my_snprintf(query_buff, sizeof(query_buff), - "SHOW TRIGGERS LIKE %s", - quote_for_like(table, name_buff)); - - - if (mysql_query_with_error_report(sock, &tableRes, query_buff)) - { - if (path) - my_fclose(sql_file, MYF(MY_WME)); - safe_exit(EX_MYSQLERR); - DBUG_RETURN(0); - } - if (mysql_num_rows(tableRes)) - fprintf(sql_file, "\n/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n\ -DELIMITER //;\n"); - while ((row=mysql_fetch_row(tableRes))) - { - fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/ //\n\ -/*!50003 CREATE TRIGGER %s %s %s ON %s FOR EACH ROW%s*/ //\n\n", - row[6], /* sql_mode */ - quote_name(row[0], name_buff, 0), /* Trigger */ - row[4], /* Timing */ - row[1], /* Event */ - result_table, - row[3] /* Statement */); - } - if (mysql_num_rows(tableRes)) - fprintf(sql_file, - "DELIMITER ;//\n\ -/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;"); - mysql_free_result(tableRes); - } } my_snprintf(query_buff, sizeof(query_buff), "show fields from %s", result_table); @@ -1376,34 +1496,44 @@ DELIMITER //;\n"); DBUG_RETURN(0); } - dynstr_append_mem(&insert_pat, "INSERT ", 7); - dynstr_append(&insert_pat, insert_option); - dynstr_append_mem(&insert_pat, "INTO ", 5); - dynstr_append(&insert_pat, opt_quoted_table); - if (opt_complete_insert) + /* + If write_data is true, then we build up insert statements for + the table's data. Note: in subsequent lines of code, this test + will have to be performed each time we are appending to + insert_pat. + */ + if (write_data) { - dynstr_append_mem(&insert_pat, " (", 2); - } - else - { - dynstr_append_mem(&insert_pat, " VALUES ", 8); - if (!extended_insert) - dynstr_append_mem(&insert_pat, "(", 1); + dynstr_append_mem(&insert_pat, "INSERT ", 7); + dynstr_append(&insert_pat, insert_option); + dynstr_append_mem(&insert_pat, "INTO ", 5); + dynstr_append(&insert_pat, opt_quoted_table); + if (complete_insert) + { + dynstr_append_mem(&insert_pat, " (", 2); + } + else + { + dynstr_append_mem(&insert_pat, " VALUES ", 8); + if (!extended_insert) + dynstr_append_mem(&insert_pat, "(", 1); + } } while ((row=mysql_fetch_row(tableRes))) { - if (init) + if (complete_insert) { - if (opt_complete_insert) + if (init) + { dynstr_append_mem(&insert_pat, ", ", 2); - } - init=1; - if (opt_complete_insert) + } + init=1; dynstr_append(&insert_pat, quote_name(row[SHOW_FIELDNAME], name_buff, 0)); + } } - numFields = (uint) mysql_num_rows(tableRes); + num_fields= (uint) mysql_num_rows(tableRes); mysql_free_result(tableRes); } else @@ -1449,19 +1579,20 @@ DELIMITER //;\n"); check_io(sql_file); } - dynstr_append_mem(&insert_pat, "INSERT ", 7); - dynstr_append(&insert_pat, insert_option); - dynstr_append_mem(&insert_pat, "INTO ", 5); - dynstr_append(&insert_pat, result_table); - if (opt_complete_insert) + if (write_data) { - dynstr_append_mem(&insert_pat, " (", 2); - } - else - { - dynstr_append_mem(&insert_pat, " VALUES ", 8); - if (!extended_insert) - dynstr_append_mem(&insert_pat, "(", 1); + dynstr_append_mem(&insert_pat, "INSERT ", 7); + dynstr_append(&insert_pat, insert_option); + dynstr_append_mem(&insert_pat, "INTO ", 5); + dynstr_append(&insert_pat, result_table); + if (opt_complete_insert) + dynstr_append_mem(&insert_pat, " (", 2); + else + { + dynstr_append_mem(&insert_pat, " VALUES ", 8); + if (!extended_insert) + dynstr_append_mem(&insert_pat, "(", 1); + } } while ((row=mysql_fetch_row(tableRes))) @@ -1474,7 +1605,7 @@ DELIMITER //;\n"); fputs(",\n",sql_file); check_io(sql_file); } - if (opt_complete_insert) + if (complete_insert) dynstr_append_mem(&insert_pat, ", ", 2); } init=1; @@ -1509,7 +1640,7 @@ DELIMITER //;\n"); check_io(sql_file); } } - numFields = (uint) mysql_num_rows(tableRes); + num_fields = (uint) mysql_num_rows(tableRes); mysql_free_result(tableRes); if (!tFlag) { @@ -1561,7 +1692,7 @@ DELIMITER //;\n"); print_xml_row(sql_file, "key", tableRes, &row); continue; } - + if (atoi(row[3]) == 1) { if (keynr++) @@ -1618,9 +1749,7 @@ DELIMITER //;\n"); else { if (opt_xml) - { print_xml_row(sql_file, "options", tableRes, &row); - } else { fputs("/*!",sql_file); @@ -1653,10 +1782,75 @@ continue_xml: write_footer(sql_file); my_fclose(sql_file, MYF(MY_WME)); } - DBUG_RETURN(numFields); + DBUG_RETURN(num_fields); } /* get_table_structure */ +/* + + dump_triggers_for_table + + Dumps the triggers given a table/db name. This should be called after + the tables have been dumped in case a trigger depends on the existence + of a table + +*/ + +static void dump_triggers_for_table (char *table, char *db) +{ + char *result_table; + char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3]; + char query_buff[512]; + uint old_opt_compatible_mode=opt_compatible_mode; + FILE *sql_file = md_result_file; + MYSQL_RES *result; + MYSQL_ROW row; + + DBUG_ENTER("dump_triggers_for_table"); + DBUG_PRINT("enter", ("db: %s, table: %s", db, table)); + + /* Do not use ANSI_QUOTES on triggers in dump */ + opt_compatible_mode&= ~MASK_ANSI_QUOTES; + result_table= quote_name(table, table_buff, 1); + + my_snprintf(query_buff, sizeof(query_buff), + "SHOW TRIGGERS LIKE %s", + quote_for_like(table, name_buff)); + + if (mysql_query_with_error_report(sock, &result, query_buff)) + { + if (path) + my_fclose(sql_file, MYF(MY_WME)); + safe_exit(EX_MYSQLERR); + DBUG_VOID_RETURN; + } + if (mysql_num_rows(result)) + fprintf(sql_file, "\n/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n\ +DELIMITER ;;\n"); + while ((row=mysql_fetch_row(result))) + { + fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n\ +/*!50003 CREATE TRIGGER %s %s %s ON %s FOR EACH ROW%s */;;\n\n", + row[6], /* sql_mode */ + quote_name(row[0], name_buff, 0), /* Trigger */ + row[4], /* Timing */ + row[1], /* Event */ + result_table, + row[3] /* Statement */); + } + if (mysql_num_rows(result)) + fprintf(sql_file, + "DELIMITER ;\n" + "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n"); + mysql_free_result(result); + /* + make sure to set back opt_compatible mode to + original value + */ + opt_compatible_mode=old_opt_compatible_mode; + DBUG_VOID_RETURN; +} + static char *add_load_option(char *ptr,const char *object, const char *statement) { @@ -1678,10 +1872,10 @@ static char *add_load_option(char *ptr,const char *object, /* -** Allow the user to specify field terminator strings like: -** "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline) -** This is done by doubleing ' and add a end -\ if needed to avoid -** syntax errors from the SQL parser. + Allow the user to specify field terminator strings like: + "'", "\", "\\" (escaped backslash), "\t" (tab), "\n" (newline) + This is done by doubling ' and add a end -\ if needed to avoid + syntax errors from the SQL parser. */ static char *field_escape(char *to,const char *from,uint length) @@ -1722,20 +1916,40 @@ static char *alloc_query_str(ulong size) /* -** dump_table saves database contents as a series of INSERT statements. + + SYNOPSIS + dump_table() + + dump_table saves database contents as a series of INSERT statements. + + ARGS + table - table name + db - db name + + RETURNS + void */ -static void dump_table(uint numFields, char *table) +static void dump_table(char *table, char *db) { + char ignore_flag; char query_buf[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3]; + char table_type[NAME_LEN]; char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table; char *query= query_buf; + int error= 0; + ulong rownr, row_break, total_length, init_length; + uint num_fields; MYSQL_RES *res; MYSQL_FIELD *field; MYSQL_ROW row; - ulong rownr, row_break, total_length, init_length; - const char *table_type; - int error= 0; + DBUG_ENTER("dump_table"); + + /* + Make sure you get the create table info before the following check for + --no-data flag below. Otherwise, the create table info won't be printed. + */ + num_fields= get_table_structure(table, db, table_type, &ignore_flag); /* Check --no-data flag */ if (dFlag) @@ -1744,32 +1958,37 @@ static void dump_table(uint numFields, char *table) fprintf(stderr, "-- Skipping dump data for table '%s', --no-data was used\n", table); - return; + DBUG_VOID_RETURN; } + DBUG_PRINT("info", + ("ignore_flag: %x num_fields: %d", (int) ignore_flag, + num_fields)); + /* + If the table type is a merge table or any type that has to be + _completely_ ignored and no data dumped + */ + if (ignore_flag & IGNORE_DATA) + { + if (verbose) + fprintf(stderr, + "-- Warning: Skipping data for table '%s' because it's of type %s\n", + table, table_type); + DBUG_VOID_RETURN; + } /* Check that there are any fields in the table */ - if (numFields == 0) + if (num_fields == 0) { if (verbose) fprintf(stderr, "-- Skipping dump data for table '%s', it has no fields\n", table); - return; + DBUG_VOID_RETURN; } result_table= quote_name(table,table_buff, 1); opt_quoted_table= quote_name(table, table_buff2, 0); - /* Check table type */ - if ((table_type= check_if_ignore_table(table))) - { - if (verbose) - fprintf(stderr, - "-- Skipping data for table '%s' because it's of type %s\n", - table, table_type); - return; - } - if (verbose) fprintf(stderr, "-- Sending SELECT query...\n"); if (path) @@ -1812,7 +2031,7 @@ static void dump_table(uint numFields, char *table) if (mysql_real_query(sock, query, (uint) (end - query))) { DB_error(sock, "when executing 'SELECT INTO OUTFILE'"); - return; + DBUG_VOID_RETURN; } } else @@ -1867,7 +2086,7 @@ static void dump_table(uint numFields, char *table) DB_error(sock, "when retrieving data from server"); if (verbose) fprintf(stderr, "-- Retrieving rows...\n"); - if (mysql_num_fields(res) != numFields) + if (mysql_num_fields(res) != num_fields) { fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n", my_progname, result_table); @@ -1930,14 +2149,15 @@ static void dump_table(uint numFields, char *table) error= EX_CONSCHECK; goto err; } - + /* 63 is my_charset_bin. If charsetnr is not 63, we have not a BLOB but a TEXT column. we'll dump in hex only BLOB columns. */ is_blob= (opt_hex_blob && field->charsetnr == 63 && - (field->type == MYSQL_TYPE_STRING || + (field->type == MYSQL_TYPE_BIT || + field->type == MYSQL_TYPE_STRING || field->type == MYSQL_TYPE_VAR_STRING || field->type == MYSQL_TYPE_VARCHAR || field->type == MYSQL_TYPE_BLOB || @@ -2164,14 +2384,14 @@ static void dump_table(uint numFields, char *table) mysql_free_result(res); if (query != query_buf) my_free(query, MYF(MY_ALLOW_ZERO_PTR)); - } - return; + } + DBUG_VOID_RETURN; err: if (query != query_buf) my_free(query, MYF(MY_ALLOW_ZERO_PTR)); safe_exit(error); - return; + DBUG_VOID_RETURN; } /* dump_table */ @@ -2372,12 +2592,20 @@ static int dump_all_tables_in_db(char *database) char *end= strmov(afterdot, table); if (include_table(hash_key, end - hash_key)) { - numrows = get_table_structure(table, database); - dump_table(numrows,table); + dump_table(table,database); my_free(order_by, MYF(MY_ALLOW_ZERO_PTR)); order_by= 0; + if (opt_dump_triggers && ! opt_xml && + mysql_get_server_version(sock) >= 50009) + dump_triggers_for_table(table, database); } } + if (opt_routines && !opt_xml && + mysql_get_server_version(sock) >= 50009) + { + DBUG_PRINT("info", ("Dumping routines for database %s", database)); + dump_routines_for_db(database); + } if (opt_xml) { fputs("\n", md_result_file); @@ -2498,7 +2726,7 @@ static int get_actual_table_name(const char *old_table_name, static int dump_selected_tables(char *db, char **table_names, int tables) { - uint numrows, i; + uint i; char table_buff[NAME_LEN*+3]; char new_table_name[NAME_LEN]; DYNAMIC_STRING lock_tables_query; @@ -2567,8 +2795,10 @@ static int dump_selected_tables(char *db, char **table_names, int tables) { table_name= hash_element(&dump_tables, i); DBUG_PRINT("info",("Dumping table %s", table_name)); - numrows= get_table_structure(table_name, db); - dump_table(numrows, table_name); + dump_table(table_name,db); + if (opt_dump_triggers && + mysql_get_server_version(sock) >= 50009) + dump_triggers_for_table(table_name, db); } /* Dump each selected view */ @@ -2580,6 +2810,13 @@ static int dump_selected_tables(char *db, char **table_names, int tables) get_view_structure(table_name, db); } } + /* obtain dump of routines (procs/functions) */ + if (opt_routines && !opt_xml && + mysql_get_server_version(sock) >= 50009) + { + DBUG_PRINT("info", ("Dumping routines for database %s", db)); + dump_routines_for_db(db); + } hash_free(&dump_tables); my_free(order_by, MYF(MY_ALLOW_ZERO_PTR)); order_by= 0; @@ -2757,28 +2994,37 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row, /* - Check if we the table is one of the table types that should be ignored: - MRG_ISAM, MRG_MYISAM SYNOPSIS + + Check if we the table is one of the table types that should be ignored: + MRG_ISAM, MRG_MYISAM, if opt_delayed, if that table supports delayed inserts. + If the table should be altogether ignored, it returns a TRUE, FALSE if it + should not be ignored. If the user has selected to use INSERT DELAYED, it + sets the value of the bool pointer supports_delayed_inserts to 0 if not + supported, 1 if it is supported. + + ARGS + check_if_ignore_table() table_name Table name to check + table_type Type of table GLOBAL VARIABLES sock MySQL socket verbose Write warning messages RETURN - 0 Table should be backuped - # Type of table (that should be skipped) + char (bit value) See IGNORE_ values at top */ -static const char *check_if_ignore_table(const char *table_name) +char check_if_ignore_table(const char *table_name, char *table_type) { + char result= IGNORE_NONE; char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN]; MYSQL_RES *res; MYSQL_ROW row; - const char *result= 0; + DBUG_ENTER("check_if_ignore_table"); /* Check memory for quote_for_like() */ DBUG_ASSERT(2*sizeof(table_name) < sizeof(show_name_buff)); @@ -2792,7 +3038,7 @@ static const char *check_if_ignore_table(const char *table_name) fprintf(stderr, "-- Warning: Couldn't get status information for table %s (%s)\n", table_name,mysql_error(sock)); - return 0; /* assume table is ok */ + DBUG_RETURN(result); /* assume table is ok */ } } if (!(row= mysql_fetch_row(res))) @@ -2801,18 +3047,38 @@ static const char *check_if_ignore_table(const char *table_name) "Error: Couldn't read status information for table %s (%s)\n", table_name, mysql_error(sock)); mysql_free_result(res); - return 0; /* assume table is ok */ + DBUG_RETURN(result); /* assume table is ok */ } if (!(row[1])) - result= "VIEW"; + strmake(table_type, "VIEW", NAME_LEN-1); else { - if (strcmp(row[1], (result= "MRG_MyISAM")) && - strcmp(row[1], (result= "MRG_ISAM"))) - result= 0; + /* + If the table type matches any of these, we do support delayed inserts. + Note: we do not want to skip dumping this table if if is not one of + these types, but we do want to use delayed inserts in the dump if + the table type is _NOT_ one of these types + */ + strmake(table_type, row[1], NAME_LEN-1); + if (opt_delayed) + { + if (strcmp(table_type,"MyISAM") && + strcmp(table_type,"ISAM") && + strcmp(table_type,"ARCHIVE") && + strcmp(table_type,"HEAP") && + strcmp(table_type,"MEMORY")) + result= IGNORE_INSERT_DELAYED; + } + + /* + If these two types, we do want to skip dumping the table + */ + if (!dFlag && + (!strcmp(table_type,"MRG_MyISAM") || !strcmp(table_type,"MRG_ISAM"))) + result= IGNORE_DATA; } mysql_free_result(res); - return result; + DBUG_RETURN(result); } /* diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 43b0672e03e..ca0a751e963 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -37,8 +37,9 @@ static char *add_load_option(char *ptr,const char *object, const char *statement); static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0, - replace=0,silent=0,ignore=0,opt_compress=0,opt_local_file=0, + replace=0,silent=0,ignore=0,opt_compress=0, opt_low_priority= 0, tty_password= 0; +static uint opt_local_file=0; static MYSQL mysql_connection; static char *opt_password=0, *current_user=0, *current_host=0, *current_db=0, *fields_terminated=0, diff --git a/client/mysqltest.c b/client/mysqltest.c index 57b81e46b66..6653d24e575 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -59,12 +59,16 @@ #include #include #include -#include /* Our own version of lib */ +#include "my_regex.h" /* Our own version of lib */ #ifdef HAVE_SYS_WAIT_H #include #endif #ifndef WEXITSTATUS -# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +# ifdef __WIN__ +# define WEXITSTATUS(stat_val) (stat_val) +# else +# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +# endif #endif /* MAX_QUERY is 256K -- there is a test in sp-big that is >128K */ #define MAX_QUERY (256*1024) @@ -98,6 +102,10 @@ #define DEFAULT_DELIMITER ";" #define MAX_DELIMITER 16 +#define RESULT_OK 0 +#define RESULT_CONTENT_MISMATCH 1 +#define RESULT_LENGTH_MISMATCH 2 + enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD, OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC, OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH, @@ -105,12 +113,11 @@ enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD, /* ************************************************************************ */ /* - A line that starts with !$ or $S, and the list of error codes to - --error are stored in an internal array of structs. This struct can - hold numeric SQL error codes or SQLSTATE codes as strings. The - element next to the last active element in the list is set to type - ERR_EMPTY. When an SQL statement return an error we use this list to - check if this is an expected error. + The list of error codes to --error are stored in an internal array of + structs. This struct can hold numeric SQL error codes or SQLSTATE codes + as strings. The element next to the last active element in the list is + set to type ERR_EMPTY. When an SQL statement return an error we use + this list to check if this is an expected error. */ enum match_err_type @@ -136,7 +143,8 @@ typedef struct long code; } st_error; -static st_error global_error[] = { +static st_error global_error[] = +{ #include { 0, 0 } }; @@ -148,13 +156,13 @@ static uint global_expected_errors; static int record = 0, opt_sleep=0; static char *db = 0, *pass=0; -const char* user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./"; +const char *user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./"; static int port = 0; static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0; static my_bool tty_password= 0, ps_protocol= 0, ps_protocol_enabled= 0; static int parsing_disabled= 0; static uint start_lineno, *lineno; -const char* manager_user="root",*manager_host=0; +const char *manager_user="root",*manager_host=0; char *manager_pass=0; int manager_port=MYSQL_MANAGER_PORT; int manager_wait_timeout=3; @@ -164,9 +172,16 @@ static char **default_argv; static const char *load_default_groups[]= { "mysqltest","client",0 }; static char line_buffer[MAX_DELIMITER], *line_buffer_pos= line_buffer; -static FILE* file_stack[MAX_INCLUDE_DEPTH]; -static FILE** cur_file; -static FILE** file_stack_end; +typedef struct +{ + FILE* file; + const char *file_name; +} test_file; + +static test_file file_stack[MAX_INCLUDE_DEPTH]; +static test_file* cur_file; +static test_file* file_stack_end; + static uint lineno_stack[MAX_INCLUDE_DEPTH]; static char TMPDIR[FN_REFLEN]; static char delimiter[MAX_DELIMITER]= DEFAULT_DELIMITER; @@ -198,13 +213,14 @@ static int got_end_timer= FALSE; static void timer_output(void); static ulonglong timer_now(void); -static regex_t ps_re; /* Holds precompiled re for valid PS statements */ +static my_regex_t ps_re; /* Holds precompiled re for valid PS statements */ static void ps_init_re(void); static int ps_match_re(char *); static char *ps_eprint(int); static void ps_free_reg(void); -static const char *embedded_server_groups[] = { +static const char *embedded_server_groups[]= +{ "server", "embedded", "mysqltest_SERVER", @@ -320,7 +336,7 @@ Q_COMMENT_WITH_COMMAND /* this should really be called command */ struct st_query { - char *query, *query_buf,*first_argument,*end; + char *query, *query_buf,*first_argument,*last_argument,*end; int first_word_len; my_bool abort_on_error, require_file; match_err expected_errno[MAX_EXPECTED_ERRORS]; @@ -336,7 +352,7 @@ const char *command_names[]= "connect", /* the difference between sleep and real_sleep is that sleep will use the delay from command line (--sleep) if there is one. - real_sleep always uses delay from it's argument. + real_sleep always uses delay from mysqltest's command line argument. the logic is that sometimes delays are cpu-dependent (and --sleep can be used to set this delay. real_sleep is used for cpu-independent delays @@ -423,7 +439,7 @@ static void var_free(void* v); int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname); void reject_dump(const char *record_file, char *buf, int size); -int close_connection(struct st_query* q); +int close_connection(struct st_query*); static void set_charset(struct st_query*); VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw, my_bool ignore_not_existing); @@ -449,9 +465,9 @@ static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name); void free_pointer_array(POINTER_ARRAY *pa); static int initialize_replace_buffer(void); static void free_replace_buffer(void); -static void do_eval(DYNAMIC_STRING* query_eval, const char *query); +static void do_eval(DYNAMIC_STRING *query_eval, const char *query); void str_to_file(const char *fname, char *str, int size); -int do_server_op(struct st_query* q,const char *op); +int do_server_op(struct st_query *q,const char *op); struct st_replace *glob_replace; static char *out_buff; @@ -475,13 +491,14 @@ my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; } static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, int len); static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val); -static int normal_handle_error(const char *query, struct st_query *q, - MYSQL *mysql, DYNAMIC_STRING *ds); -static int normal_handle_no_error(struct st_query *q); +static int handle_error(const char *query, struct st_query *q, + unsigned int err_errno, const char *err_error, + const char *err_sqlstate, DYNAMIC_STRING *ds); +static int handle_no_error(struct st_query *q); -static void do_eval(DYNAMIC_STRING* query_eval, const char* query) +static void do_eval(DYNAMIC_STRING* query_eval, const char *query) { - const char* p; + const char *p; register char c; register int escaped = 0; VAR* v; @@ -538,10 +555,13 @@ static void close_cons() static void close_files() { DBUG_ENTER("close_files"); - for (; cur_file != file_stack ; cur_file--) + for (; cur_file >= file_stack; cur_file--) { - if (*cur_file != stdin && *cur_file) - my_fclose(*cur_file,MYF(0)); + DBUG_PRINT("info", ("file_name: %s", cur_file->file_name)); + if (cur_file->file && cur_file->file != stdin) + my_fclose(cur_file->file, MYF(0)); + my_free((gptr)cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR)); + cur_file->file_name= 0; } DBUG_VOID_RETURN; } @@ -584,14 +604,19 @@ static void free_used_memory() DBUG_VOID_RETURN; } -static void die(const char* fmt, ...) +static void die(const char *fmt, ...) { va_list args; DBUG_ENTER("die"); va_start(args, fmt); if (fmt) { - fprintf(stderr, "%s: ", my_progname); + fprintf(stderr, "mysqltest: "); + if (cur_file && cur_file != file_stack) + fprintf(stderr, "In included file \"%s\": ", + cur_file->file_name); + if (start_lineno != 0) + fprintf(stderr, "At line %u: ", start_lineno); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); fflush(stderr); @@ -615,7 +640,7 @@ static void abort_not_supported_test() exit(62); } -static void verbose_msg(const char* fmt, ...) +static void verbose_msg(const char *fmt, ...) { va_list args; DBUG_ENTER("verbose_msg"); @@ -624,7 +649,9 @@ static void verbose_msg(const char* fmt, ...) va_start(args, fmt); - fprintf(stderr, "%s: At line %u: ", my_progname, start_lineno); + fprintf(stderr, "mysqltest: "); + if (start_lineno > 0) + fprintf(stderr, "At line %u: ", start_lineno); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); @@ -634,12 +661,12 @@ static void verbose_msg(const char* fmt, ...) void init_parser() { - parser.current_line = parser.read_lines = 0; - memset(&var_reg,0, sizeof(var_reg)); + parser.current_line= parser.read_lines= 0; + memset(&var_reg, 0, sizeof(var_reg)); } -int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname) +int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) { MY_STAT stat_info; char *tmp, *res_ptr; @@ -665,7 +692,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname) DBUG_PRINT("info",("Size differs: result size: %u file size: %u", ds->length, stat_info.st_size)); DBUG_PRINT("info",("result: '%s'", ds->str)); - DBUG_RETURN(2); + DBUG_RETURN(RESULT_LENGTH_MISMATCH); } if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME)))) die(NullS); @@ -682,7 +709,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname) res_ptr = res_ds.str; if ((res_len = res_ds.length) != ds->length) { - res = 2; + res= RESULT_LENGTH_MISMATCH; goto err; } } @@ -692,7 +719,8 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname) res_len = stat_info.st_size; } - res = (memcmp(res_ptr, ds->str, res_len)) ? 1 : 0; + res= (memcmp(res_ptr, ds->str, res_len)) ? + RESULT_CONTENT_MISMATCH : RESULT_OK; err: if (res && eval_result) @@ -706,36 +734,33 @@ err: DBUG_RETURN(res); } -static int check_result(DYNAMIC_STRING* ds, const char* fname, +static int check_result(DYNAMIC_STRING* ds, const char *fname, my_bool require_option) { - int error = 0; - int res=dyn_string_cmp(ds, fname); + int res= dyn_string_cmp(ds, fname); DBUG_ENTER("check_result"); if (res && require_option) abort_not_supported_test(); switch (res) { - case 0: + case RESULT_OK: break; /* ok */ - case 2: + case RESULT_LENGTH_MISMATCH: verbose_msg("Result length mismatch"); - error = 1; break; - case 1: + case RESULT_CONTENT_MISMATCH: verbose_msg("Result content mismatch"); - error = 1; break; default: /* impossible */ die("Unknown error code from dyn_string_cmp()"); } - if (error) + if (res != RESULT_OK) reject_dump(fname, ds->str, ds->length); - DBUG_RETURN(error); + DBUG_RETURN(res); } -VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw, +VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw, my_bool ignore_not_existing) { int digit; @@ -748,7 +773,7 @@ VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw, digit = *++var_name - '0'; if (digit < 0 || digit >= 10) { - const char* save_var_name = var_name, *end; + const char *save_var_name = var_name, *end; uint length; end = (var_name_end) ? *var_name_end : 0; while (my_isvar(charset_info,*var_name) && var_name != end) @@ -790,7 +815,7 @@ err: DBUG_RETURN(0); } -static VAR *var_obtain(const char* name, int len) +static VAR *var_obtain(const char *name, int len) { VAR* v; if ((v = (VAR*)hash_search(&var_hash, name, len))) @@ -827,9 +852,11 @@ int var_set(const char *var_name, const char *var_name_end, } -int open_file(const char* name) +int open_file(const char *name) { char buff[FN_REFLEN]; + DBUG_ENTER("open_file"); + DBUG_PRINT("enter", ("name: %s", name)); if (!test_if_hard_path(name)) { strxmov(buff, opt_basedir, name, NullS); @@ -837,19 +864,51 @@ int open_file(const char* name) } fn_format(buff,name,"","",4); - if (*cur_file && cur_file == file_stack_end) + if (cur_file == file_stack_end) die("Source directives are nesting too deep"); - if (!(*(cur_file+1) = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME)))) - die(NullS); cur_file++; + if (!(cur_file->file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0)))) + { + cur_file--; + die("Could not open file %s", buff); + } + cur_file->file_name= my_strdup(buff, MYF(MY_FAE)); *++lineno=1; + DBUG_RETURN(0); +} - return 0; + +/* + Check for unexpected "junk" after the end of query + This is normally caused by missing delimiters +*/ + +int check_eol_junk(const char *eol) +{ + const char *p= eol; + DBUG_ENTER("check_eol_junk"); + DBUG_PRINT("enter", ("eol: %s", eol)); + /* Remove all spacing chars except new line */ + while (*p && my_isspace(charset_info, *p) && (*p != '\n')) + p++; + + /* Check for extra delimiter */ + if (*p && !strncmp(p, delimiter, delimiter_length)) + die("Extra delimiter \"%s\" found", delimiter); + + /* Allow trailing # comment */ + if (*p && *p != '#') + { + if (*p == '\n') + die("Missing delimiter"); + die("End of line junk detected: \"%s\"", p); + } + DBUG_RETURN(0); } /* ugly long name, but we are following the convention */ -int do_wait_for_slave_to_stop(struct st_query* q __attribute__((unused))) +int do_wait_for_slave_to_stop(struct st_query *q __attribute__((unused))) { MYSQL* mysql = &cur_con->mysql; for (;;) @@ -877,7 +936,7 @@ int do_wait_for_slave_to_stop(struct st_query* q __attribute__((unused))) return 0; } -int do_require_manager(struct st_query* a __attribute__((unused))) +int do_require_manager(struct st_query *query __attribute__((unused)) ) { if (!manager) abort_not_supported_test(); @@ -885,95 +944,121 @@ int do_require_manager(struct st_query* a __attribute__((unused))) } #ifndef EMBEDDED_LIBRARY -int do_server_start(struct st_query* q) +int do_server_start(struct st_query *q) { - return do_server_op(q,"start"); + return do_server_op(q, "start"); } -int do_server_stop(struct st_query* q) +int do_server_stop(struct st_query *q) { - return do_server_op(q,"stop"); + return do_server_op(q, "stop"); } -int do_server_op(struct st_query* q,const char* op) +int do_server_op(struct st_query *q, const char *op) { - char* p=q->first_argument; - char com_buf[256],*com_p; + char *p= q->first_argument; + char com_buf[256], *com_p; if (!manager) { die("Manager is not initialized, manager commands are not possible"); } - com_p=strmov(com_buf,op); - com_p=strmov(com_p,"_exec "); + com_p= strmov(com_buf,op); + com_p= strmov(com_p,"_exec "); if (!*p) - die("Missing server name in server_%s\n",op); - while (*p && !my_isspace(charset_info,*p)) + die("Missing server name in server_%s", op); + while (*p && !my_isspace(charset_info, *p)) *com_p++= *p++; - *com_p++=' '; - com_p=int10_to_str(manager_wait_timeout,com_p,10); - *com_p++ = '\n'; - *com_p=0; - if (mysql_manager_command(manager,com_buf,(int)(com_p-com_buf))) - die("Error in command: %s(%d)",manager->last_error,manager->last_errno); + *com_p++= ' '; + com_p= int10_to_str(manager_wait_timeout, com_p, 10); + *com_p++= '\n'; + *com_p= 0; + if (mysql_manager_command(manager, com_buf, (int)(com_p-com_buf))) + die("Error in command: %s(%d)", manager->last_error, manager->last_errno); while (!manager->eof) { - if (mysql_manager_fetch_line(manager,com_buf,sizeof(com_buf))) + if (mysql_manager_fetch_line(manager, com_buf, sizeof(com_buf))) die("Error fetching result line: %s(%d)", manager->last_error, manager->last_errno); } + q->last_argument= p; return 0; } #endif -int do_source(struct st_query* q) + +/* + Source and execute the given file + + SYNOPSIS + do_source() + query called command + + DESCRIPTION + source + + Open the file and execute it + +*/ + +int do_source(struct st_query *query) { - char* p=q->first_argument, *name; + char *p= query->first_argument, *name; if (!*p) - die("Missing file name in source\n"); - name = p; + die("Missing file name in source"); + name= p; while (*p && !my_isspace(charset_info,*p)) p++; - *p = 0; - + if (*p) + *p++= 0; + query->last_argument= p; + /* + If this file has already been sourced, dont source it again. + It's already available in the q_lines cache + */ + if (parser.current_line < (parser.read_lines - 1)) + return 0; return open_file(name); } + /* Execute given command. SYNOPSIS do_exec() - q called command + query called command DESCRIPTION - If one uses --exec command [args] command in .test file - we will execute the command and record its output. + exec + + Execute the text between exec and end of line in a subprocess. + The error code returned from the subprocess is checked against the + expected error array, previously set with the --error command. + It can thus be used to execute a command that shall fail. - RETURN VALUES - 0 ok - 1 error */ -static void do_exec(struct st_query* q) +static void do_exec(struct st_query *query) { int error; - DYNAMIC_STRING *ds= NULL; /* Assign just to avoid warning */ + DYNAMIC_STRING *ds= NULL; DYNAMIC_STRING ds_tmp; char buf[1024]; FILE *res_file; - char *cmd= q->first_argument; + char *cmd= query->first_argument; DBUG_ENTER("do_exec"); while (*cmd && my_isspace(charset_info, *cmd)) cmd++; if (!*cmd) - die("Missing argument in exec\n"); + die("Missing argument in exec"); + query->last_argument= query->end; DBUG_PRINT("info", ("Executing '%s'", cmd)); - if (!(res_file= popen(cmd, "r")) && q->abort_on_error) - die("popen() failed\n"); + if (!(res_file= popen(cmd, "r")) && query->abort_on_error) + die("popen(\"%s\", \"r\") failed", cmd); if (disable_result_log) { @@ -985,7 +1070,7 @@ static void do_exec(struct st_query* q) } else { - if (q->record_file[0]) + if (query->record_file[0]) { init_dynamic_string(&ds_tmp, "", 16384, 65536); ds= &ds_tmp; @@ -1002,33 +1087,35 @@ static void do_exec(struct st_query* q) uint status= WEXITSTATUS(error), i; my_bool ok= 0; - if (q->abort_on_error) - die("At line %u: command \"%s\" failed", start_lineno, cmd); + if (query->abort_on_error) + die("command \"%s\" failed", cmd); DBUG_PRINT("info", ("error: %d, status: %d", error, status)); - for (i=0 ; (uint) i < q->expected_errors ; i++) + for (i= 0; i < query->expected_errors; i++) { DBUG_PRINT("info", ("error: %d, status: %d", error, status)); DBUG_PRINT("info", ("expected error: %d", - q->expected_errno[i].code.errnum)); - if ((q->expected_errno[i].type == ERR_ERRNO) && - (q->expected_errno[i].code.errnum == status)) + query->expected_errno[i].code.errnum)); + if ((query->expected_errno[i].type == ERR_ERRNO) && + (query->expected_errno[i].code.errnum == status)) + { ok= 1; - verbose_msg("At line %u: command \"%s\" failed with expected error: %d", - start_lineno, cmd, status); + DBUG_PRINT("info", ("command \"%s\" failed with expected error: %d", + cmd, status)); + } } if (!ok) - die("At line: %u: command \"%s\" failed with wrong error: %d", - start_lineno, cmd, status); + die("command \"%s\" failed with wrong error: %d", + cmd, status); } - else if (q->expected_errno[0].type == ERR_ERRNO && - q->expected_errno[0].code.errnum != 0) + else if (query->expected_errno[0].type == ERR_ERRNO && + query->expected_errno[0].code.errnum != 0) { /* Error code we wanted was != 0, i.e. not an expected success */ - die("At line: %u: command \"%s\" succeeded - should have failed with errno %d...", - start_lineno, cmd, q->expected_errno[0].code.errnum); + die("command \"%s\" succeeded - should have failed with errno %d...", + cmd, query->expected_errno[0].code.errnum); } if (!disable_result_log) @@ -1038,14 +1125,14 @@ static void do_exec(struct st_query* q) if (record) { - if (!q->record_file[0] && !result_file) - die("At line %u: Missing result file", start_lineno); + if (!query->record_file[0] && !result_file) + die("Missing result file"); if (!result_file) - str_to_file(q->record_file, ds->str, ds->length); + str_to_file(query->record_file, ds->str, ds->length); } - else if (q->record_file[0]) + else if (query->record_file[0]) { - error= check_result(ds, q->record_file, q->require_file); + error= check_result(ds, query->record_file, query->require_file); } if (ds == &ds_tmp) dynstr_free(&ds_tmp); @@ -1053,7 +1140,7 @@ static void do_exec(struct st_query* q) } -int var_query_set(VAR* v, const char* p, const char** p_end) +int var_query_set(VAR* v, const char *p, const char** p_end) { char* end = (char*)((p_end && *p_end) ? *p_end : p + strlen(p)); MYSQL_RES *res; @@ -1104,19 +1191,27 @@ int var_query_set(VAR* v, const char* p, const char** p_end) return 0; } -void var_copy(VAR* dest, VAR* src) +void var_copy(VAR *dest, VAR *src) { - dest->int_val=src->int_val; - dest->int_dirty=src->int_dirty; + dest->int_val= src->int_val; + dest->int_dirty= src->int_dirty; + + /* Alloc/realloc data for str_val in dest */ if (dest->alloced_len < src->alloced_len && - !(dest->str_val=my_realloc(dest->str_val,src->alloced_len+1, - MYF(MY_WME)))) + !(dest->str_val= dest->str_val + ? my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME)) + : my_malloc(src->alloced_len, MYF(MY_WME)))) die("Out of memory"); - dest->str_val_len=src->str_val_len; - memcpy(dest->str_val,src->str_val,src->str_val_len+1); + else + dest->alloced_len= src->alloced_len; + + /* Copy str_val data to dest */ + dest->str_val_len= src->str_val_len; + if (src->str_val_len) + memcpy(dest->str_val, src->str_val, src->str_val_len); } -int eval_expr(VAR* v, const char* p, const char** p_end) +int eval_expr(VAR* v, const char *p, const char** p_end) { VAR* vp; if (*p == '$') @@ -1157,29 +1252,58 @@ int eval_expr(VAR* v, const char* p, const char** p_end) return 1; } -int do_inc(struct st_query* q) + +enum enum_operator { - char* p=q->first_argument; + DO_DEC, + DO_INC +}; + +/* + Decrease or increase the value of a variable + + SYNOPSIS + do_modify_var() + query called command + name human readable name of operator + operator operation to perform on the var + + DESCRIPTION + dec $var_name + inc $var_name + +*/ + +int do_modify_var(struct st_query *query, const char *name, + enum enum_operator operator) +{ + const char *p= query->first_argument; VAR* v; - v = var_get(p, 0, 1, 0); - v->int_val++; - v->int_dirty = 1; + if (!*p) + die("Missing arguments to %s", name); + if (*p != '$') + die("First argument to %s must be a variable (start with $)", name); + v= var_get(p, &p, 1, 0); + switch (operator) { + case DO_DEC: + v->int_val--; + break; + case DO_INC: + v->int_val++; + break; + default: + die("Invalid operator to do_operator"); + break; + } + v->int_dirty= 1; + query->last_argument= (char*)++p; return 0; } -int do_dec(struct st_query* q) -{ - char* p=q->first_argument; - VAR* v; - v = var_get(p, 0, 1, 0); - v->int_val--; - v->int_dirty = 1; - return 0; -} -int do_system(struct st_query* q) +int do_system(struct st_query *q) { - char* p=q->first_argument; + char *p=q->first_argument; VAR v; var_init(&v, 0, 0, 0, 0); eval_expr(&v, p, 0); /* NULL terminated */ @@ -1191,63 +1315,96 @@ int do_system(struct st_query* q) memcpy(expr_buf, v.str_val, v.str_val_len); expr_buf[v.str_val_len] = 0; DBUG_PRINT("info", ("running system command '%s'", expr_buf)); - if (system(expr_buf) && q->abort_on_error) - die("system command '%s' failed", expr_buf); + if (system(expr_buf)) + { + if (q->abort_on_error) + die("system command '%s' failed", expr_buf); + /* If ! abort_on_error, display message and continue */ + verbose_msg("system command '%s' failed", expr_buf); + } } + else + die("Missing arguments to system, nothing to do!"); var_free(&v); + q->last_argument= q->end; return 0; } -int do_echo(struct st_query* q) + +/* + Print the content between echo and to result file. + If content is a variable, the variable value will be retrieved + + SYNOPSIS + do_echo() + q called command + + DESCRIPTION + Usage 1: + echo text + Print the text after echo until end of command to result file + + Usage 2: + echo $ + Print the content of the variable to result file + +*/ + +int do_echo(struct st_query *q) { - char* p=q->first_argument; + char *p= q->first_argument; + DYNAMIC_STRING *ds; + DYNAMIC_STRING ds_tmp; VAR v; var_init(&v,0,0,0,0); + + if (q->record_file[0]) + { + init_dynamic_string(&ds_tmp, "", 256, 512); + ds= &ds_tmp; + } + else + ds= &ds_res; + eval_expr(&v, p, 0); /* NULL terminated */ if (v.str_val_len) - { - fflush(stdout); - write(1, v.str_val, v.str_val_len); - } - write(1, "\n", 1); + dynstr_append_mem(ds, v.str_val, v.str_val_len); + dynstr_append_mem(ds, "\n", 1); var_free(&v); + if (ds == &ds_tmp) + dynstr_free(&ds_tmp); + q->last_argument= q->end; return 0; } -int do_sync_with_master2(const char* p) +int do_sync_with_master2(long offset) { MYSQL_RES* res; MYSQL_ROW row; - MYSQL* mysql = &cur_con->mysql; + MYSQL* mysql= &cur_con->mysql; char query_buf[FN_REFLEN+128]; - int offset= 0, tries= 0; + int tries= 0; int rpl_parse; if (!master_pos.file[0]) - { - die("Line %u: Calling 'sync_with_master' without calling 'save_master_pos'", start_lineno); - } - rpl_parse = mysql_rpl_parse_enabled(mysql); + die("Calling 'sync_with_master' without calling 'save_master_pos'"); + rpl_parse= mysql_rpl_parse_enabled(mysql); mysql_disable_rpl_parse(mysql); - if (*p) - offset = atoi(p); - sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file, master_pos.pos + offset); wait_for_position: if (mysql_query(mysql, query_buf)) - die("line %u: failed in %s: %d: %s", start_lineno, query_buf, - mysql_errno(mysql), mysql_error(mysql)); + die("failed in %s: %d: %s", query_buf, mysql_errno(mysql), + mysql_error(mysql)); - if (!(last_result = res = mysql_store_result(mysql))) - die("line %u: mysql_store_result() returned NULL for '%s'", start_lineno, - query_buf); - if (!(row = mysql_fetch_row(res))) - die("line %u: empty result in %s", start_lineno, query_buf); + if (!(last_result= res= mysql_store_result(mysql))) + die("mysql_store_result() returned NULL for '%s'", query_buf); + if (!(row= mysql_fetch_row(res))) + die("empty result in %s", query_buf); if (!row[0]) { /* @@ -1255,10 +1412,7 @@ wait_for_position: SLAVE has been issued ? */ if (tries++ == 3) - { - die("line %u: could not sync with master ('%s' returned NULL)", - start_lineno, query_buf); - } + die("could not sync with master ('%s' returned NULL)", query_buf); sleep(1); /* So at most we will wait 3 seconds and make 4 tries */ mysql_free_result(res); goto wait_for_position; @@ -1271,9 +1425,21 @@ wait_for_position: return 0; } -int do_sync_with_master(struct st_query* q) +int do_sync_with_master(struct st_query *query) { - return do_sync_with_master2(q->first_argument); + long offset= 0; + char *p= query->first_argument; + const char *offset_start= p; + if (*offset_start) + { + for (; my_isdigit(charset_info, *p); p++) + offset = offset * 10 + *p - '0'; + + if(*p && !my_isspace(charset_info, *p)) + die("Invalid integer argument \"%s\"", offset_start); + query->last_argument= p; + } + return do_sync_with_master2(offset); } int do_save_master_pos() @@ -1288,14 +1454,13 @@ int do_save_master_pos() mysql_disable_rpl_parse(mysql); if (mysql_query(mysql, query= "show master status")) - die("At line %u: failed in show master status: %d: %s", start_lineno, + die("failed in show master status: %d: %s", mysql_errno(mysql), mysql_error(mysql)); if (!(last_result =res = mysql_store_result(mysql))) - die("line %u: mysql_store_result() retuned NULL for '%s'", start_lineno, - query); + die("mysql_store_result() retuned NULL for '%s'", query); if (!(row = mysql_fetch_row(res))) - die("line %u: empty result in show master status", start_lineno); + die("empty result in show master status"); strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1); master_pos.pos = strtoul(row[1], (char**) 0, 10); mysql_free_result(res); last_result=0; @@ -1307,21 +1472,51 @@ int do_save_master_pos() } -int do_let(struct st_query* q) +/* + Assign the variable with + + SYNOPSIS + do_let() + query called command + + DESCRIPTION + let $= + + - is the string string found between the $ and = + - is the content between the = and , it may span + multiple line and contain any characters except + - is a string containing of one or more chars, default is ; + + RETURN VALUES + Program will die if error detected +*/ + +int do_let(struct st_query *query) { - char* p=q->first_argument; + char *p= query->first_argument; char *var_name, *var_name_end, *var_val_start; + + /* Find */ if (!*p) - die("Missing variable name in let\n"); - var_name = p; - while (*p && (*p != '=' || my_isspace(charset_info,*p))) + die("Missing arguments to let"); + var_name= p; + while (*p && (*p != '=') && !my_isspace(charset_info,*p)) p++; - var_name_end = p; - if (*p == '=') p++; + var_name_end= p; + if (var_name+1 == var_name_end) + die("Missing variable name in let"); + while (my_isspace(charset_info,*p)) + p++; + if (*p++ != '=') + die("Missing assignment operator in let"); + + /* Find start of */ while (*p && my_isspace(charset_info,*p)) p++; - var_val_start = p; - return var_set(var_name, var_name_end, var_val_start, q->end); + var_val_start= p; + query->last_argument= query->end; + /* Assign var_val to var_name */ + return var_set(var_name, var_name_end, var_val_start, query->end); } @@ -1340,7 +1535,7 @@ int var_set_errno(int sql_errno) } -int do_rpl_probe(struct st_query* q __attribute__((unused))) +int do_rpl_probe(struct st_query *query __attribute__((unused))) { DBUG_ENTER("do_rpl_probe"); if (mysql_rpl_probe(&cur_con->mysql)) @@ -1349,71 +1544,104 @@ int do_rpl_probe(struct st_query* q __attribute__((unused))) } -int do_enable_rpl_parse(struct st_query* q __attribute__((unused))) +int do_enable_rpl_parse(struct st_query *query __attribute__((unused))) { mysql_enable_rpl_parse(&cur_con->mysql); return 0; } -int do_disable_rpl_parse(struct st_query* q __attribute__((unused))) +int do_disable_rpl_parse(struct st_query *query __attribute__((unused))) { mysql_disable_rpl_parse(&cur_con->mysql); return 0; } -int do_sleep(struct st_query* q, my_bool real_sleep) +/* + Sleep the number of specifed seconds + + SYNOPSIS + do_sleep() + q called command + real_sleep use the value from opt_sleep as number of seconds to sleep + + DESCRIPTION + sleep + real_sleep + +*/ + +int do_sleep(struct st_query *query, my_bool real_sleep) { - char *p=q->first_argument; - while (*p && my_isspace(charset_info,*p)) + int error= 0; + char *p= query->first_argument; + char *sleep_start, *sleep_end= query->end; + double sleep_val; + + while (my_isspace(charset_info, *p)) p++; if (!*p) - die("Missing argument in sleep\n"); + die("Missing argument to sleep"); + sleep_start= p; + /* Check that arg starts with a digit, not handled by my_strtod */ + if (!my_isdigit(charset_info, *sleep_start)) + die("Invalid argument to sleep \"%s\"", query->first_argument); + sleep_val= my_strtod(sleep_start, &sleep_end, &error); + if (error) + die("Invalid argument to sleep \"%s\"", query->first_argument); + + /* Fixed sleep time selected by --sleep option */ if (opt_sleep && !real_sleep) - my_sleep(opt_sleep * 1000000L); - else - my_sleep((ulong) (atof(p) * 1000000L)); + sleep_val= opt_sleep; + + my_sleep((ulong) (sleep_val * 1000000L)); + query->last_argument= sleep_end; return 0; } -static void get_file_name(char *filename, struct st_query* q) +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 && my_isspace(charset_info,p[-1])) - p--; - p[0]=0; + char *p= q->first_argument, *name; + if (!*p) + die("Missing file name argument"); + name= p; + while (*p && !my_isspace(charset_info,*p)) + p++; + if (*p) + *p++= 0; + q->last_argument= p; + strmake(filename, name, FN_REFLEN); } -static void set_charset(struct st_query* q) +static void set_charset(struct st_query *q) { - char* charset_name= q->first_argument; - char* tmp; + char *charset_name= q->first_argument; + char *p; if (!charset_name || !*charset_name) - die("Missing charset name in 'character_set'\n"); + die("Missing charset name in 'character_set'"); /* Remove end space */ - tmp= charset_name; - while (*tmp && !my_isspace(charset_info,*tmp)) - tmp++; - *tmp= 0; - + p= charset_name; + while (*p && !my_isspace(charset_info,*p)) + p++; + if(*p) + *p++= 0; + q->last_argument= p; charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME)); if (!charset_info) abort_not_supported_test(); } -static uint get_errcodes(match_err *to,struct st_query* q) +static uint get_errcodes(match_err *to,struct st_query *q) { - char* p= q->first_argument; + char *p= q->first_argument; uint count= 0; DBUG_ENTER("get_errcodes"); if (!*p) - die("Missing argument in %s\n", q->query); + die("Missing argument in %s", q->query); do { @@ -1447,20 +1675,20 @@ static uint get_errcodes(match_err *to,struct st_query* q) } } if (!e->name) - die("Unknown SQL error '%s'\n", start); + die("Unknown SQL error '%s'", start); } else { long val; if (!(p= str2int(p,10,(long) INT_MIN, (long) INT_MAX, &val))) - die("Invalid argument in %s\n", q->query); + die("Invalid argument in %s", q->query); to[count].code.errnum= (uint) val; to[count].type= ERR_ERRNO; } count++; } while (*(p++) == ','); - + q->last_argument= (p - 1); to[count].type= ERR_EMPTY; /* End of data */ DBUG_RETURN(count); } @@ -1474,7 +1702,7 @@ static uint get_errcodes(match_err *to,struct st_query* q) static char *get_string(char **to_ptr, char **from_ptr, - struct st_query* q) + struct st_query *q) { reg1 char c,sep; char *to= *to_ptr, *from= *from_ptr, *start=to; @@ -1522,7 +1750,7 @@ static char *get_string(char **to_ptr, char **from_ptr, *to++=c; } if (*from != ' ' && *from) - die("Wrong string argument in %s\n", q->query); + die("Wrong string argument in %s", q->query); while (my_isspace(charset_info,*from)) /* Point to next string */ from++; @@ -1557,7 +1785,7 @@ static char *get_string(char **to_ptr, char **from_ptr, static void get_replace(struct st_query *q) { uint i; - char *from=q->first_argument; + char *from= q->first_argument; char *buff,*start; char word_end_chars[256],*pos; POINTER_ARRAY to_array,from_array; @@ -1568,14 +1796,14 @@ static void get_replace(struct st_query *q) bzero((char*) &to_array,sizeof(to_array)); bzero((char*) &from_array,sizeof(from_array)); if (!*from) - die("Missing argument in %s\n", q->query); + die("Missing argument in %s", q->query); start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE)); while (*from) { char *to=buff; to=get_string(&buff, &from, q); if (!*from) - die("Wrong number of arguments to replace in %s\n", q->query); + die("Wrong number of arguments to replace_result in '%s'", q->query); insert_pointer_name(&from_array,to); to=get_string(&buff, &from, q); insert_pointer_name(&to_array,to); @@ -1589,10 +1817,11 @@ static void get_replace(struct st_query *q) (uint) from_array.typelib.count, word_end_chars)) || initialize_replace_buffer()) - die("Can't initialize replace from %s\n", q->query); + die("Can't initialize replace from '%s'", q->query); free_pointer_array(&from_array); free_pointer_array(&to_array); my_free(start, MYF(0)); + q->last_argument= q->end; DBUG_VOID_RETURN; } @@ -1608,25 +1837,18 @@ void free_replace() DBUG_VOID_RETURN; } -int select_connection(char *p) + +int select_connection_name(const char *name) { - char* name; struct connection *con; - DBUG_ENTER("select_connection"); - DBUG_PRINT("enter",("name: '%s'",p)); + DBUG_ENTER("select_connection2"); + DBUG_PRINT("enter",("name: '%s'", name)); - if (!*p) - die("Missing connection name in connect\n"); - name = p; - while (*p && !my_isspace(charset_info,*p)) - p++; - *p = 0; - - for (con = cons; con < next_con; con++) + for (con= cons; con < next_con; con++) { if (!strcmp(con->name, name)) { - cur_con = con; + cur_con= con; DBUG_RETURN(0); } } @@ -1634,21 +1856,42 @@ int select_connection(char *p) DBUG_RETURN(1); /* Never reached */ } -int close_connection(struct st_query* q) + +int select_connection(struct st_query *query) { - char* p=q->first_argument, *name; + char *name; + char *p= query->first_argument; + DBUG_ENTER("select_connection"); + + if (!*p) + die("Missing connection name in connect"); + name= p; + while (*p && !my_isspace(charset_info,*p)) + p++; + if (*p) + *p++= 0; + query->last_argument= p; + return select_connection_name(name); +} + + +int close_connection(struct st_query *q) +{ + char *p= q->first_argument, *name; struct connection *con; DBUG_ENTER("close_connection"); DBUG_PRINT("enter",("name: '%s'",p)); if (!*p) - die("Missing connection name in connect\n"); - name = p; + die("Missing connection name in connect"); + name= p; while (*p && !my_isspace(charset_info,*p)) p++; - *p = 0; - for (con = cons; con < next_con; con++) + if (*p) + *p++= 0; + q->last_argument= p; + for (con= cons; con < next_con; con++) { if (!strcmp(con->name, name)) { @@ -1678,21 +1921,21 @@ int close_connection(struct st_query* q) ) are delimiters/terminators */ -char* safe_get_param(char* str, char** arg, const char* msg) +char* safe_get_param(char *str, char** arg, const char *msg) { DBUG_ENTER("safe_get_param"); while (*str && my_isspace(charset_info,*str)) str++; - *arg = str; + *arg= str; for (; *str && *str != ',' && *str != ')' ; str++) { if (my_isspace(charset_info,*str)) - *str = 0; + *str= 0; } if (!*str) die(msg); - *str++ = 0; + *str++= 0; DBUG_RETURN(str); } @@ -1732,18 +1975,19 @@ void init_manager() 0 - success, non-0 - failure */ -int safe_connect(MYSQL* con, const char* host, const char* user, - const char* pass, - const char* db, int port, const char* sock) +int safe_connect(MYSQL* con, const char *host, const char *user, + const char *pass, + const char *db, int port, const char *sock) { - int con_error = 1; + int con_error= 1; + my_bool reconnect= 1; int i; - for (i = 0; i < MAX_CON_TRIES; ++i) + for (i= 0; i < MAX_CON_TRIES; ++i) { if (mysql_real_connect(con, host,user, pass, db, port, sock, - CLIENT_MULTI_STATEMENTS)) + CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS)) { - con_error = 0; + con_error= 0; break; } sleep(CON_RETRY_SLEEP); @@ -1752,7 +1996,7 @@ int safe_connect(MYSQL* con, const char* host, const char* user, TODO: change this to 0 in future versions, but the 'kill' test relies on existing behavior */ - con->reconnect= 1; + mysql_options(con, MYSQL_OPT_RECONNECT, (char *)&reconnect); return con_error; } @@ -1786,6 +2030,7 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host, int* create_conn) { DYNAMIC_STRING ds_tmp, *ds; + my_bool reconnect= 1; int error= 0; /* @@ -1831,11 +2076,12 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host, if (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0, CLIENT_MULTI_STATEMENTS)) { - error= normal_handle_error("connect", q, con, ds); + error= handle_error("connect", q, mysql_errno(con), mysql_error(con), + mysql_sqlstate(con), ds); *create_conn= 0; goto err; } - else if (normal_handle_no_error(q)) + else if (handle_no_error(q)) { /* Fail if there was no error but we expected it. @@ -1851,12 +2097,12 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host, TODO: change this to 0 in future versions, but the 'kill' test relies on existing behavior */ - con->reconnect= 1; + mysql_options(con, MYSQL_OPT_RECONNECT, (char *)&reconnect); if (record) { if (!q->record_file[0] && !result_file) - die("At line %u: Missing result file", start_lineno); + die("Missing result file"); if (!result_file) str_to_file(q->record_file, ds->str, ds->length); } @@ -1871,14 +2117,14 @@ err: } -int do_connect(struct st_query* q) +int do_connect(struct st_query *q) { - char* con_name, *con_user,*con_pass, *con_host, *con_port_str, + char *con_name, *con_user,*con_pass, *con_host, *con_port_str, *con_db, *con_sock; - char* p=q->first_argument; + char *p= q->first_argument; char buff[FN_REFLEN]; int con_port; - int free_con_sock = 0; + int free_con_sock= 0; int error= 0; int create_conn= 1; @@ -1888,40 +2134,41 @@ int do_connect(struct st_query* q) if (*p != '(') die("Syntax error in connect - expected '(' found '%c'", *p); p++; - p = safe_get_param(p, &con_name, "missing connection name"); - p = safe_get_param(p, &con_host, "missing connection host"); - p = safe_get_param(p, &con_user, "missing connection user"); - p = safe_get_param(p, &con_pass, "missing connection password"); - p = safe_get_param(p, &con_db, "missing connection db"); + p= safe_get_param(p, &con_name, "missing connection name"); + p= safe_get_param(p, &con_host, "missing connection host"); + p= safe_get_param(p, &con_user, "missing connection user"); + p= safe_get_param(p, &con_pass, "missing connection password"); + p= safe_get_param(p, &con_db, "missing connection db"); if (!*p || *p == ';') /* Default port and sock */ { - con_port=port; - con_sock=(char*) unix_sock; + con_port= port; + con_sock= (char*) unix_sock; } else { VAR* var_port, *var_sock; - p = safe_get_param(p, &con_port_str, "missing connection port"); + p= safe_get_param(p, &con_port_str, "missing connection port"); if (*con_port_str == '$') { - if (!(var_port = var_get(con_port_str, 0, 0, 0))) + if (!(var_port= var_get(con_port_str, 0, 0, 0))) die("Unknown variable '%s'", con_port_str+1); - con_port = var_port->int_val; + con_port= var_port->int_val; } else - con_port=atoi(con_port_str); - p = safe_get_param(p, &con_sock, "missing connection socket"); + con_port= atoi(con_port_str); + p= safe_get_param(p, &con_sock, "missing connection socket"); if (*con_sock == '$') { - if (!(var_sock = var_get(con_sock, 0, 0, 0))) + if (!(var_sock= var_get(con_sock, 0, 0, 0))) die("Unknown variable '%s'", con_sock+1); - if (!(con_sock = (char*)my_malloc(var_sock->str_val_len+1, MYF(0)))) + if (!(con_sock= (char*)my_malloc(var_sock->str_val_len+1, MYF(0)))) die("Out of memory"); - free_con_sock = 1; + free_con_sock= 1; memcpy(con_sock, var_sock->str_val, var_sock->str_val_len); - con_sock[var_sock->str_val_len] = 0; + con_sock[var_sock->str_val_len]= 0; } } + q->last_argument= p; if (next_con == cons_end) die("Connection limit exhausted - increase MAX_CONS in mysqltest.c"); @@ -1941,11 +2188,10 @@ int do_connect(struct st_query* q) if (con_sock && !free_con_sock && *con_sock && *con_sock != FN_LIBCHAR) con_sock=fn_format(buff, con_sock, TMPDIR, "",0); if (!con_db[0]) - con_db=db; + con_db= db; /* Special database to allow one to connect without a database name */ if (con_db && !strcmp(con_db,"*NO-ONE*")) - con_db=0; - + con_db= 0; if (q->abort_on_error) { if ((safe_connect(&next_con->mysql, con_host, con_user, con_pass, @@ -1970,14 +2216,15 @@ int do_connect(struct st_query* q) } -int do_done(struct st_query* q) +int do_done(struct st_query *q) { - /* Dummy statement to eliminate compiler warning */ - q->type = Q_END_BLOCK; - /* Check if empty block stack */ if (cur_block == block_stack) + { + if (*q->query != '}') + die("Stray 'end' command - end of block before beginning"); die("Stray '}' - end of block before beginning"); + } /* Test if inner block has been executed */ if (cur_block->ok && cur_block->cmd == cmd_while) @@ -1998,9 +2245,10 @@ int do_done(struct st_query* q) int do_block(enum block_cmd cmd, struct st_query* q) { - char* p=q->first_argument; - const char* expr_start, *expr_end; + char *p= q->first_argument; + const char *expr_start, *expr_end; VAR v; + const char *cmd_name= (cmd == cmd_while ? "while" : "if"); /* Check stack overflow */ if (cur_block == block_stack_end) @@ -2020,12 +2268,21 @@ int do_block(enum block_cmd cmd, struct st_query* q) } /* Parse and evaluate test expression */ - expr_start = strchr(p, '('); + expr_start= strchr(p, '('); if (!expr_start) - die("missing '(' in while"); - expr_end = strrchr(expr_start, ')'); + die("missing '(' in %s", cmd_name); + expr_end= strrchr(expr_start, ')'); if (!expr_end) - die("missing ')' in while"); + die("missing ')' in %s", cmd_name); + p= (char*)expr_end+1; + + while (*p && my_isspace(charset_info, *p)) + p++; + if (*p == '{') + die("Missing newline between %s and '{'", cmd_name); + if (*p) + die("Missing '{' after %s. Found \"%s\"", cmd_name, p); + var_init(&v,0,0,0,0); eval_expr(&v, ++expr_start, &expr_end); @@ -2071,7 +2328,7 @@ my_bool end_of_query(int c) return 0; for (i= 1; i < delimiter_length && - (c= my_getc(*cur_file)) == *(delimiter + i); + (c= my_getc(cur_file->file)) == *(delimiter + i); i++) tmp[i]= c; @@ -2086,33 +2343,72 @@ my_bool end_of_query(int c) } -int read_line(char* buf, int size) +/* + Read one "line" from the file + + SYNOPSIS + read_line + buf buffer for the read line + size size of the buffer i.e max size to read + + DESCRIPTION + This function actually reads several lines an adds them to the + buffer buf. It will continue to read until it finds what it believes + is a complete query. + + Normally that means it will read lines until it reaches the + "delimiter" that marks end of query. Default delimiter is ';' + The function should be smart enough not to detect delimiter's + found inside strings sorrounded with '"' and '\'' escaped strings. + + If the first line in a query starts with '#' or '-' this line is treated + as a comment. A comment is always terminated when end of line '\n' is + reached. + +*/ + +int read_line(char *buf, int size) { int c; char quote; - char* p= buf, *buf_end= buf + size - 1; + char *p= buf, *buf_end= buf + size - 1; int no_save= 0; enum {R_NORMAL, R_Q, R_Q_IN_Q, R_SLASH_IN_Q, R_COMMENT, R_LINE_START} state= R_LINE_START; DBUG_ENTER("read_line"); + LINT_INIT(quote); start_lineno= *lineno; for (; p < buf_end ;) { no_save= 0; - c= my_getc(*cur_file); - if (feof(*cur_file)) + c= my_getc(cur_file->file); + if (feof(cur_file->file)) { found_eof: - if ((*cur_file) != stdin) - my_fclose(*cur_file, MYF(0)); - cur_file--; + if (cur_file->file != stdin) + { + my_fclose(cur_file->file, MYF(0)); + cur_file->file= 0; + } + my_free((gptr)cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR)); + cur_file->file_name= 0; lineno--; + start_lineno= *lineno; if (cur_file == file_stack) { + /* We're back at the first file, check if + all { have matching } + */ + if (cur_block != block_stack) + { + start_lineno= *(lineno+1); + die("Missing end of block"); + } DBUG_PRINT("info", ("end of file")); DBUG_RETURN(1); } + cur_file--; continue; } @@ -2146,7 +2442,8 @@ int read_line(char* buf, int size) } break; case R_LINE_START: - if (c == '#' || c == '-' || parsing_disabled) + /* Only accept start of comment if this is the first line in query */ + if ((*lineno == start_lineno) && (c == '#' || c == '-' || parsing_disabled)) { state = R_COMMENT; } @@ -2216,9 +2513,9 @@ int read_line(char* buf, int size) for (i= 1; i < charlen; i++) { - if (feof(*cur_file)) + if (feof(cur_file->file)) goto found_eof; /* FIXME: could we just break here?! */ - c= my_getc(*cur_file); + c= my_getc(cur_file->file); *p++ = c; } if (! my_ismbchar(charset_info, mb_start, p)) @@ -2235,15 +2532,34 @@ int read_line(char* buf, int size) } } *p= 0; /* Always end with \0 */ - DBUG_RETURN(feof(*cur_file)); + DBUG_RETURN(feof(cur_file->file)); } +/* + Create a query from a set of lines + + SYNOPSIS + read_query() + q_ptr pointer where to return the new query + + DESCRIPTION + Converts lines returned by read_line into a query, this involves + parsing the first word in the read line to find the query type. + + + A -- comment may contain a valid query as the first word after the + comment start. Thus it's always checked to see if that is the case. + The advantage with this approach is to be able to execute commands + terminated by new line '\n' regardless how many "delimiter" it contain. + + If query starts with @ this will specify a file to .... +*/ static char read_query_buf[MAX_QUERY]; int read_query(struct st_query** q_ptr) { - char *p = read_query_buf, * p1 ; + char *p= read_query_buf, *p1; struct st_query* q; DBUG_ENTER("read_query"); @@ -2260,16 +2576,16 @@ int read_query(struct st_query** q_ptr) q->require_file= 0; q->first_word_len= 0; - q->type = Q_UNKNOWN; + q->type= Q_UNKNOWN; q->query_buf= q->query= 0; if (read_line(read_query_buf, sizeof(read_query_buf))) { DBUG_RETURN(1); } - DBUG_PRINT("info", ("query: %s", read_query_buf)); + DBUG_PRINT("info", ("query: %s", read_query_buf)); if (*p == '#') { - q->type = Q_COMMENT; + q->type= Q_COMMENT; /* This goto is to avoid losing the "expected error" info. */ goto end; } @@ -2279,8 +2595,6 @@ int read_query(struct st_query** q_ptr) sizeof(global_expected_errno)); q->expected_errors= global_expected_errors; q->abort_on_error= (global_expected_errors == 0 && abort_on_error); - bzero((gptr) global_expected_errno, sizeof(global_expected_errno)); - global_expected_errors=0; } if (p[0] == '-' && p[1] == '-') @@ -2290,34 +2604,6 @@ int read_query(struct st_query** q_ptr) } else if (!parsing_disabled) { - if (*p == '!') - { - q->abort_on_error= 0; - p++; - if (*p == '$') - { - int expected_errno= 0; - p++; - for (; my_isdigit(charset_info, *p); p++) - expected_errno = expected_errno * 10 + *p - '0'; - q->expected_errno[0].code.errnum = expected_errno; - q->expected_errno[0].type= ERR_ERRNO; - q->expected_errno[1].type= ERR_EMPTY; - q->expected_errors=1; - } - else if (*p == 'S') /* SQLSTATE */ - { - int i; - p++; - for (i = 0; my_isalnum(charset_info, *p) && i < SQLSTATE_LENGTH; p++, i++) - q->expected_errno[0].code.sqlstate[i]= *p; - q->expected_errno[0].code.sqlstate[i]= '\0'; - q->expected_errno[0].type= ERR_SQLSTATE; - q->expected_errno[1].type= ERR_EMPTY; - q->expected_errors=1; - } - } - while (*p && my_isspace(charset_info, *p)) p++ ; if (*p == '@') @@ -2478,8 +2764,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), argument= buff; } fn_format(buff, argument, "", "", 4); - if (!(*++cur_file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME)))) - die("Could not open %s: errno = %d", argument, errno); + DBUG_ASSERT(cur_file == file_stack && cur_file->file == 0); + if (!(cur_file->file= + my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0)))) + die("Could not open %s: errno = %d", buff, errno); + cur_file->file_name= my_strdup(buff, MYF(MY_FAE)); break; } case 'm': @@ -2564,7 +2853,7 @@ int parse_args(int argc, char **argv) return 0; } -char* safe_str_append(char* buf, const char* str, int size) +char* safe_str_append(char *buf, const char *str, int size) { int i,c ; for (i = 0; (c = *str++) && i < size - 1; i++) @@ -2573,7 +2862,7 @@ char* safe_str_append(char* buf, const char* str, int size) return buf; } -void str_to_file(const char* fname, char* str, int size) +void str_to_file(const char *fname, char *str, int size) { int fd; char buff[FN_REFLEN]; @@ -2583,7 +2872,7 @@ void str_to_file(const char* fname, char* str, int size) fname=buff; } fn_format(buff,fname,"","",4); - + if ((fd = my_open(buff, O_WRONLY | O_CREAT | O_TRUNC, MYF(MY_WME | MY_FFNF))) < 0) die("Could not open %s: errno = %d", buff, errno); @@ -2592,7 +2881,7 @@ void str_to_file(const char* fname, char* str, int size) my_close(fd, MYF(0)); } -void reject_dump(const char* record_file, char* buf, int size) +void reject_dump(const char *record_file, char *buf, int size) { char reject_file[FN_REFLEN]; str_to_file(fn_format(reject_file, record_file,"",".reject",2), buf, size); @@ -2608,7 +2897,7 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, { len=(int) replace_strings(glob_replace, &out_buff, &out_length, val); if (len == -1) - die("Out of memory in replace\n"); + die("Out of memory in replace"); val=out_buff; } dynstr_append_mem(ds, val, len); @@ -2682,8 +2971,6 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res) static int run_query_normal(MYSQL *mysql, struct st_query *q, int flags); static int run_query_stmt (MYSQL *mysql, struct st_query *q, int flags); static void run_query_stmt_handle_warnings(MYSQL *mysql, DYNAMIC_STRING *ds); -static int run_query_stmt_handle_error(char *query, struct st_query *q, - MYSQL_STMT *stmt, DYNAMIC_STRING *ds); static void run_query_display_metadata(MYSQL_FIELD *field, uint num_fields, DYNAMIC_STRING *ds); @@ -2747,8 +3034,8 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) { got_error_on_send= mysql_send_query(mysql, query, query_len); if (got_error_on_send && q->expected_errno[0].type == ERR_EMPTY) - die("At line %u: unable to send query '%s' (mysql_errno=%d , errno=%d)", - start_lineno, query, mysql_errno(mysql), errno); + die("unable to send query '%s' (mysql_errno=%d , errno=%d)", + query, mysql_errno(mysql), errno); } do @@ -2767,17 +3054,12 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) (!(last_result= res= mysql_store_result(mysql)) && mysql_field_count(mysql))) { - if (normal_handle_error(query, q, mysql, ds)) + if (handle_error(query, q, mysql_errno(mysql), mysql_error(mysql), + mysql_sqlstate(mysql), ds)) error= 1; goto end; } - if (normal_handle_no_error(q)) - { - error= 1; - goto end; - } - if (!disable_result_log) { ulong affected_rows; /* Ok to be undef if 'disable_info' is set */ @@ -2822,12 +3104,9 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) MYSQL_RES *warn_res=0; uint count= mysql_warning_count(mysql); if (!mysql_real_query(mysql, "SHOW WARNINGS", 13)) - { warn_res= mysql_store_result(mysql); - } if (!warn_res) - verbose_msg("Warning count is %u but didn't get any warnings\n", - count); + die("Warning count is %u but didn't get any warnings", count); else { dynstr_append_mem(ds, "Warnings:\n", 10); @@ -2852,21 +3131,34 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) if (record) { if (!q->record_file[0] && !result_file) - die("At line %u: Missing result file", start_lineno); + die("Missing result file"); if (!result_file) str_to_file(q->record_file, ds->str, ds->length); } else if (q->record_file[0]) { - error = check_result(ds, q->record_file, q->require_file); + error= check_result(ds, q->record_file, q->require_file); } if (res) mysql_free_result(res); last_result= 0; counter++; } while (!(err= mysql_next_result(mysql))); - if (err >= 1) - mysql_error(mysql); + if (err > 0) + { + /* We got an error from mysql_next_result, maybe expected */ + if (handle_error(query, q, mysql_errno(mysql), mysql_error(mysql), + mysql_sqlstate(mysql), ds)) + error= 1; + goto end; + } + + /* If we come here the query is both executed and read successfully */ + if (handle_no_error(q)) + { + error= 1; + goto end; + } end: free_replace(); @@ -2887,14 +3179,15 @@ end: /* - Handle errors which occurred after execution of conventional (non-prepared) - statement. + Handle errors which occurred after execution SYNOPSIS - normal_handle_error() + handle_error() query - query string q - query context - mysql - connection through which query was sent to server + err_errno - error number + err_error - error message + err_sqlstate - sql state ds - dynamic string which is used for output buffer NOTE @@ -2906,85 +3199,80 @@ end: 1 - Some other error was expected. */ -static int normal_handle_error(const char *query, struct st_query *q, - MYSQL *mysql, DYNAMIC_STRING *ds) +static int handle_error(const char *query, struct st_query *q, + unsigned int err_errno, const char *err_error, + const char* err_sqlstate, DYNAMIC_STRING *ds) { uint i; - - DBUG_ENTER("normal_handle_error"); + + DBUG_ENTER("handle_error"); if (q->require_file) abort_not_supported_test(); - + if (q->abort_on_error) - die("At line %u: query '%s' failed: %d: %s", start_lineno, query, - mysql_errno(mysql), mysql_error(mysql)); - else + die("query '%s' failed: %d: %s", query, err_errno, err_error); + + for (i= 0 ; (uint) i < q->expected_errors ; i++) { - for (i= 0 ; (uint) i < q->expected_errors ; i++) + if (((q->expected_errno[i].type == ERR_ERRNO) && + (q->expected_errno[i].code.errnum == err_errno)) || + ((q->expected_errno[i].type == ERR_SQLSTATE) && + (strcmp(q->expected_errno[i].code.sqlstate, err_sqlstate) == 0))) { - if (((q->expected_errno[i].type == ERR_ERRNO) && - (q->expected_errno[i].code.errnum == mysql_errno(mysql))) || - ((q->expected_errno[i].type == ERR_SQLSTATE) && - (strcmp(q->expected_errno[i].code.sqlstate, mysql_sqlstate(mysql)) == 0))) + if (q->expected_errors == 1) { - if (q->expected_errors == 1) - { - /* Only log error if there is one possible error */ - dynstr_append_mem(ds, "ERROR ", 6); - replace_dynstr_append(ds, mysql_sqlstate(mysql)); - dynstr_append_mem(ds, ": ", 2); - replace_dynstr_append(ds, mysql_error(mysql)); - dynstr_append_mem(ds,"\n",1); - } - /* Don't log error if we may not get an error */ - else if (q->expected_errno[0].type == ERR_SQLSTATE || - (q->expected_errno[0].type == ERR_ERRNO && - q->expected_errno[0].code.errnum != 0)) - dynstr_append(ds,"Got one of the listed errors\n"); - /* OK */ - DBUG_RETURN(0); + /* Only log error if there is one possible error */ + dynstr_append_mem(ds, "ERROR ", 6); + replace_dynstr_append(ds, err_sqlstate); + dynstr_append_mem(ds, ": ", 2); + replace_dynstr_append(ds, err_error); + dynstr_append_mem(ds,"\n",1); } + /* Don't log error if we may not get an error */ + else if (q->expected_errno[0].type == ERR_SQLSTATE || + (q->expected_errno[0].type == ERR_ERRNO && + q->expected_errno[0].code.errnum != 0)) + dynstr_append(ds,"Got one of the listed errors\n"); + /* OK */ + DBUG_RETURN(0); } - - DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors)); - - dynstr_append_mem(ds, "ERROR ",6); - replace_dynstr_append(ds, mysql_sqlstate(mysql)); - dynstr_append_mem(ds, ": ", 2); - replace_dynstr_append(ds, mysql_error(mysql)); - dynstr_append_mem(ds, "\n", 1); - - if (i) - { - if (q->expected_errno[0].type == ERR_ERRNO) - verbose_msg("query '%s' failed with wrong errno %d instead of %d...", - q->query, mysql_errno(mysql), - q->expected_errno[0].code.errnum); - else - verbose_msg("query '%s' failed with wrong sqlstate %s instead of %s...", - q->query, mysql_sqlstate(mysql), - q->expected_errno[0].code.sqlstate); - DBUG_RETURN(1); - } - - /* - If we do not abort on error, failure to run the query does not fail the - whole test case. - */ - verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql), - mysql_error(mysql)); - DBUG_RETURN(0); } - return 0; /* Keep compiler happy */ + + DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors)); + + dynstr_append_mem(ds, "ERROR ",6); + replace_dynstr_append(ds, err_sqlstate); + dynstr_append_mem(ds, ": ", 2); + replace_dynstr_append(ds, err_error); + dynstr_append_mem(ds, "\n", 1); + + if (i) + { + if (q->expected_errno[0].type == ERR_ERRNO) + die("query '%s' failed with wrong errno %d instead of %d...", + q->query, err_errno, q->expected_errno[0].code.errnum); + else + die("query '%s' failed with wrong sqlstate %s instead of %s...", + q->query, err_sqlstate, q->expected_errno[0].code.sqlstate); + DBUG_RETURN(1); + } + + /* + If we do not abort on error, failure to run the query does not fail the + whole test case. + */ + verbose_msg("query '%s' failed: %d: %s", q->query, err_errno, + err_error); + DBUG_RETURN(0); } /* - Handle absence of errors after execution of convetional statement. + Handle absence of errors after execution SYNOPSIS - normal_handle_error() + handle_no_error() q - context of query RETURN VALUE @@ -2992,24 +3280,24 @@ static int normal_handle_error(const char *query, struct st_query *q, 1 - Some error was expected from this query. */ -static int normal_handle_no_error(struct st_query *q) +static int handle_no_error(struct st_query *q) { - DBUG_ENTER("normal_handle_no_error"); + DBUG_ENTER("handle_no_error"); if (q->expected_errno[0].type == ERR_ERRNO && q->expected_errno[0].code.errnum != 0) { /* Error code we wanted was != 0, i.e. not an expected success */ - verbose_msg("query '%s' succeeded - should have failed with errno %d...", - q->query, q->expected_errno[0].code.errnum); + die("query '%s' succeeded - should have failed with errno %d...", + q->query, q->expected_errno[0].code.errnum); DBUG_RETURN(1); } else if (q->expected_errno[0].type == ERR_SQLSTATE && strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0) { /* SQLSTATE we wanted was != "00000", i.e. not an expected success */ - verbose_msg("query '%s' succeeded - should have failed with sqlstate %s...", - q->query, q->expected_errno[0].code.sqlstate); + die("query '%s' succeeded - should have failed with sqlstate %s...", + q->query, q->expected_errno[0].code.sqlstate); DBUG_RETURN(1); } @@ -3029,7 +3317,7 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) { int error= 0; /* Function return code if "goto end;" */ int err; /* Temporary storage of return code from calls */ - int query_len, got_error_on_execute; + int query_len; ulonglong num_rows; char *query; MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */ @@ -3044,8 +3332,8 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) may be a new connection. */ if (!(stmt= mysql_stmt_init(mysql))) - die("At line %u: unable init stmt structure"); - + die("unable init stmt structure"); + if (q->type != Q_EVAL) { query= q->query; @@ -3086,30 +3374,21 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) if (err != 0) { - if (q->abort_on_error) - { - die("At line %u: unable to prepare statement '%s': " - "%s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, - mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); - } - else - { - /* - Preparing is part of normal execution and some errors may be expected - */ - error= run_query_stmt_handle_error(query, q, stmt, ds); - goto end; - } + /* + Preparing is part of normal execution and some errors may be expected + */ + if (handle_error(query, q, mysql_stmt_errno(stmt), + mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds)) + error= 1; + goto end; } /* We may have got warnings already, collect them if any */ - /* FIXME we only want this if the statement succeeds I think */ if (!disable_ps_warnings) run_query_stmt_handle_warnings(mysql, ds); /* - No need to call mysql_stmt_bind_param() because we have no + No need to call mysql_stmt_bind_param() because we have no parameter markers. To optimize performance we use a global 'stmt' that is initiated @@ -3118,22 +3397,13 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) prepared statement. */ - if ((got_error_on_execute= mysql_stmt_execute(stmt)) != 0) /* 0 == Success */ + if (mysql_stmt_execute(stmt) != 0) /* 0 == Success */ { - if (q->abort_on_error) - { - /* We got an error, unexpected */ - die("At line %u: unable to execute statement '%s': " - "%s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, mysql_stmt_error(stmt), - mysql_stmt_errno(stmt), got_error_on_execute); - } - else - { - /* We got an error, maybe expected */ - error= run_query_stmt_handle_error(query, q, stmt, ds); - goto end; - } + /* We got an error, maybe expected */ + if (handle_error(query, q, mysql_stmt_errno(stmt), + mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds)) + error= 1; + goto end; } /* @@ -3143,11 +3413,10 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) */ { my_bool one= 1; - if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, - (void*) &one) != 0) - die("At line %u: unable to set stmt attribute " - "'STMT_ATTR_UPDATE_MAX_LENGTH': %s (returned=%d)", - start_lineno, query, err); + if ((err= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, + (void*) &one)) != 0) + die("unable to set stmt attribute " + "'STMT_ATTR_UPDATE_MAX_LENGTH' err: %d", err); } /* @@ -3156,29 +3425,16 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) */ if ((err= mysql_stmt_store_result(stmt)) != 0) { - if (q->abort_on_error) - { - /* We got an error, unexpected */ - die("At line %u: unable to execute statement '%s': " - "%s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, mysql_stmt_error(stmt), - mysql_stmt_errno(stmt), got_error_on_execute); - } - else - { - /* We got an error, maybe expected */ - error= run_query_stmt_handle_error(query, q, stmt, ds); - goto end; - } + /* We got an error, maybe expected */ + if(handle_error(query, q, mysql_stmt_errno(stmt), + mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds)) + error = 1; + goto end; } /* If we got here the statement was both executed and read succeesfully */ - - if (q->expected_errno[0].type == ERR_ERRNO && - q->expected_errno[0].code.errnum != 0) + if (handle_no_error(q)) { - verbose_msg("query '%s' succeeded - should have failed with errno %d...", - q->query, q->expected_errno[0].code.errnum); error= 1; goto end; } @@ -3197,8 +3453,6 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) MYSQL_FIELD *field= mysql_fetch_fields(res); uint num_fields= mysql_num_fields(res); - /* FIXME check error from the above? */ - if (display_metadata) run_query_display_metadata(field, num_fields, ds); @@ -3251,18 +3505,18 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) /* Fill in the data into the structures created above */ if ((err= mysql_stmt_bind_result(stmt, bind)) != 0) - die("At line %u: unable to bind result to statement '%s': " + die("unable to bind result to statement '%s': " "%s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, + query, mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); /* Read result from each row */ for (row_idx= 0; row_idx < num_rows; row_idx++) { if ((err= mysql_stmt_fetch(stmt)) != 0) - die("At line %u: unable to fetch all rows from statement '%s': " + die("unable to fetch all rows from statement '%s': " "%s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, + query, mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); /* Read result from each column */ @@ -3300,9 +3554,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) } if ((err= mysql_stmt_fetch(stmt)) != MYSQL_NO_DATA) - die("At line %u: fetch didn't end with MYSQL_NO_DATA from statement " + die("fetch didn't end with MYSQL_NO_DATA from statement " "'%s': %s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, + query, mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); free_replace_column(); @@ -3339,7 +3593,7 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) if (record) { if (!q->record_file[0] && !result_file) - die("At line %u: Missing result file", start_lineno); + die("Missing result file"); if (!result_file) str_to_file(q->record_file, ds->str, ds->length); } @@ -3351,9 +3605,6 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) mysql_free_result(res); /* Free normal result set with meta data */ last_result= 0; /* FIXME have no idea what this is about... */ - if (err >= 1) - mysql_error(mysql); /* FIXME strange, has no effect... */ - end: free_replace(); last_result=0; @@ -3444,8 +3695,8 @@ static void run_query_stmt_handle_warnings(MYSQL *mysql, DYNAMIC_STRING *ds) { MYSQL_RES *warn_res= mysql_store_result(mysql); if (!warn_res) - verbose_msg("Warning count is %u but didn't get any warnings\n", - count); + die("Warning count is %u but didn't get any warnings", + count); else { dynstr_append_mem(ds, "Warnings:\n", 10); @@ -3458,71 +3709,6 @@ static void run_query_stmt_handle_warnings(MYSQL *mysql, DYNAMIC_STRING *ds) } -static int run_query_stmt_handle_error(char *query, struct st_query *q, - MYSQL_STMT *stmt, DYNAMIC_STRING *ds) -{ - if (q->require_file) /* FIXME don't understand this one */ - { - abort_not_supported_test(); - } - - if (q->abort_on_error) - die("At line %u: query '%s' failed: %d: %s", start_lineno, query, - mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); - else - { - int i; - - for (i=0 ; (uint) i < q->expected_errors ; i++) - { - if (((q->expected_errno[i].type == ERR_ERRNO) && - (q->expected_errno[i].code.errnum == mysql_stmt_errno(stmt))) || - ((q->expected_errno[i].type == ERR_SQLSTATE) && - (strcmp(q->expected_errno[i].code.sqlstate, - mysql_stmt_sqlstate(stmt)) == 0))) - { - if (i == 0 && q->expected_errors == 1) - { - /* Only log error if there is one possible error */ - dynstr_append_mem(ds,"ERROR ",6); - replace_dynstr_append(ds, mysql_stmt_sqlstate(stmt)); - dynstr_append_mem(ds, ": ", 2); - replace_dynstr_append(ds,mysql_stmt_error(stmt)); - dynstr_append_mem(ds,"\n",1); - } - /* Don't log error if we may not get an error */ - else if (q->expected_errno[0].type == ERR_SQLSTATE || - (q->expected_errno[0].type == ERR_ERRNO && - q->expected_errno[0].code.errnum != 0)) - dynstr_append(ds,"Got one of the listed errors\n"); - return 0; /* Ok */ - } - } - DBUG_PRINT("info",("i: %d expected_errors: %d", i, - q->expected_errors)); - dynstr_append_mem(ds, "ERROR ",6); - replace_dynstr_append(ds, mysql_stmt_sqlstate(stmt)); - dynstr_append_mem(ds,": ",2); - replace_dynstr_append(ds, mysql_stmt_error(stmt)); - dynstr_append_mem(ds,"\n",1); - if (i) - { - verbose_msg("query '%s' failed with wrong errno %d instead of %d...", - q->query, mysql_stmt_errno(stmt), q->expected_errno[0]); - return 1; /* Error */ - } - verbose_msg("query '%s' failed: %d: %s", q->query, mysql_stmt_errno(stmt), - mysql_stmt_error(stmt)); - /* - if we do not abort on error, failure to run the query does - not fail the whole test case - */ - return 0; - } - - return 0; -} - /****************************************************************************\ * Functions to match SQL statements that can be prepared \****************************************************************************/ @@ -3543,12 +3729,13 @@ static void ps_init_re(void) "[[:space:]]*UPDATE[[:space:]]+MULTI[[:space:]]|" "[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])"; - int err= regcomp(&ps_re, ps_re_str, (REG_EXTENDED | REG_ICASE | REG_NOSUB), - &my_charset_latin1); + int err= my_regcomp(&ps_re, ps_re_str, + (REG_EXTENDED | REG_ICASE | REG_NOSUB), + &my_charset_latin1); if (err) { char erbuf[100]; - int len= regerror(err, &ps_re, erbuf, sizeof(erbuf)); + int len= my_regerror(err, &ps_re, erbuf, sizeof(erbuf)); fprintf(stderr, "error %s, %d/%d `%s'\n", ps_eprint(err), len, (int)sizeof(erbuf), erbuf); exit(1); @@ -3558,7 +3745,7 @@ static void ps_init_re(void) static int ps_match_re(char *stmt_str) { - int err= regexec(&ps_re, stmt_str, (size_t)0, NULL, 0); + int err= my_regexec(&ps_re, stmt_str, (size_t)0, NULL, 0); if (err == 0) return 1; @@ -3567,7 +3754,7 @@ static int ps_match_re(char *stmt_str) else { char erbuf[100]; - int len= regerror(err, &ps_re, erbuf, sizeof(erbuf)); + int len= my_regerror(err, &ps_re, erbuf, sizeof(erbuf)); fprintf(stderr, "error %s, %d/%d `%s'\n", ps_eprint(err), len, (int)sizeof(erbuf), erbuf); exit(1); @@ -3577,7 +3764,7 @@ static int ps_match_re(char *stmt_str) static char *ps_eprint(int err) { static char epbuf[100]; - size_t len= regerror(REG_ITOA|err, (regex_t *)NULL, epbuf, sizeof(epbuf)); + size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf)); assert(len <= sizeof(epbuf)); return(epbuf); } @@ -3585,7 +3772,7 @@ static char *ps_eprint(int err) static void ps_free_reg(void) { - regfree(&ps_re); + my_regfree(&ps_re); } /****************************************************************************/ @@ -3619,6 +3806,22 @@ void get_query_type(struct st_query* q) q->type != Q_DISABLE_PARSING) q->type= Q_COMMENT; } + else if (q->type == Q_COMMENT_WITH_COMMAND && + q->query[q->first_word_len-1] == ';') + { + /* + Detect comment with command using extra delimiter + Ex --disable_query_log; + ^ Extra delimiter causing the command + to be skipped + */ + save= q->query[q->first_word_len-1]; + q->query[q->first_word_len-1]= 0; + type= find_type(q->query, &command_typelib, 1+2); + q->query[q->first_word_len-1]= save; + if (type > 0) + die("Extra delimiter \";\" found"); + } DBUG_VOID_RETURN; } @@ -3710,8 +3913,10 @@ int main(int argc, char **argv) { int error = 0; struct st_query *q; - my_bool require_file=0, q_send_flag=0, abort_flag= 0; + my_bool require_file=0, q_send_flag=0, abort_flag= 0, + query_executed= 0; char save_file[FN_REFLEN]; + MY_STAT res_info; MY_INIT(argv[0]); /* Use all time until exit if no explicit 'start_timer' */ @@ -3726,14 +3931,14 @@ int main(int argc, char **argv) memset(file_stack, 0, sizeof(file_stack)); memset(&master_pos, 0, sizeof(master_pos)); - file_stack_end = file_stack + MAX_INCLUDE_DEPTH; - cur_file = file_stack; + file_stack_end= file_stack + MAX_INCLUDE_DEPTH - 1; + cur_file= file_stack; lineno = lineno_stack; my_init_dynamic_array(&q_lines, sizeof(struct st_query*), INIT_Q_LINES, INIT_Q_LINES); memset(block_stack, 0, sizeof(block_stack)); - block_stack_end= block_stack + BLOCK_STACK_DEPTH; + block_stack_end= block_stack + BLOCK_STACK_DEPTH - 1; cur_block= block_stack; cur_block->ok= TRUE; /* Outer block should always be executed */ cur_block->cmd= cmd_none; @@ -3746,8 +3951,11 @@ int main(int argc, char **argv) embedded_server_args, (char**) embedded_server_groups)) die("Can't initialize MySQL server"); - if (cur_file == file_stack) - *++cur_file = stdin; + if (cur_file == file_stack && cur_file->file == 0) + { + cur_file->file= stdin; + cur_file->file_name= my_strdup("", MYF(MY_WME)); + } *lineno=1; #ifndef EMBEDDED_LIBRARY if (manager_host) @@ -3793,19 +4001,20 @@ int main(int argc, char **argv) get_query_type(q); if (cur_block->ok) { + q->last_argument= q->first_argument; processed = 1; switch (q->type) { case Q_CONNECT: error|= do_connect(q); break; - case Q_CONNECTION: select_connection(q->first_argument); break; + case Q_CONNECTION: select_connection(q); break; case Q_DISCONNECT: case Q_DIRTY_CLOSE: close_connection(q); break; case Q_RPL_PROBE: do_rpl_probe(q); break; case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(q); break; case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break; - case Q_ENABLE_QUERY_LOG: disable_query_log=0; break; + case Q_ENABLE_QUERY_LOG: disable_query_log=0; break; case Q_DISABLE_QUERY_LOG: disable_query_log=1; break; case Q_ENABLE_ABORT_ON_ERROR: abort_on_error=1; break; case Q_DISABLE_ABORT_ON_ERROR: abort_on_error=0; break; @@ -3828,19 +4037,24 @@ int main(int argc, char **argv) case Q_SERVER_START: do_server_start(q); break; case Q_SERVER_STOP: do_server_stop(q); break; #endif - case Q_INC: do_inc(q); break; - case Q_DEC: do_dec(q); break; + case Q_INC: do_modify_var(q, "inc", DO_INC); break; + case Q_DEC: do_modify_var(q, "dec", DO_DEC); break; case Q_ECHO: do_echo(q); break; case Q_SYSTEM: do_system(q); break; case Q_DELIMITER: strmake(delimiter, q->first_argument, sizeof(delimiter) - 1); delimiter_length= strlen(delimiter); + q->last_argument= q->first_argument+delimiter_length; break; - case Q_DISPLAY_VERTICAL_RESULTS: display_result_vertically= TRUE; break; - case Q_DISPLAY_HORIZONTAL_RESULTS: - display_result_vertically= FALSE; break; + case Q_DISPLAY_VERTICAL_RESULTS: + display_result_vertically= TRUE; + break; + case Q_DISPLAY_HORIZONTAL_RESULTS: + display_result_vertically= FALSE; + break; case Q_LET: do_let(q); break; - case Q_EVAL_RESULT: eval_result = 1; break; + case Q_EVAL_RESULT: + eval_result = 1; break; case Q_EVAL: if (q->query == q->query_buf) { @@ -3873,6 +4087,8 @@ int main(int argc, char **argv) } error|= run_query(&cur_con->mysql, q, QUERY_REAP|QUERY_SEND); display_result_vertically= old_display_result_vertically; + q->last_argument= q->end; + query_executed= 1; break; } case Q_QUERY: @@ -3897,6 +4113,8 @@ int main(int argc, char **argv) save_file[0]=0; } error |= run_query(&cur_con->mysql, q, flags); + query_executed= 1; + q->last_argument= q->end; break; } case Q_SEND: @@ -3916,6 +4134,8 @@ int main(int argc, char **argv) is given on this connection. */ error |= run_query(&cur_con->mysql, q, QUERY_SEND); + query_executed= 1; + q->last_argument= q->end; break; case Q_RESULT: get_file_name(save_file,q); @@ -3940,23 +4160,22 @@ int main(int argc, char **argv) { do_save_master_pos(); if (*q->first_argument) - select_connection(q->first_argument); + select_connection(q); else - { - char buf[] = "slave"; - select_connection(buf); - } - do_sync_with_master2(""); + select_connection_name("slave"); + do_sync_with_master2(0); break; } case Q_COMMENT: /* Ignore row */ case Q_COMMENT_WITH_COMMAND: + q->last_argument= q->end; break; case Q_PING: (void) mysql_ping(&cur_con->mysql); break; - case Q_EXEC: + case Q_EXEC: do_exec(q); + query_executed= 1; break; case Q_START_TIMER: /* Overwrite possible earlier start of timer */ @@ -3967,7 +4186,7 @@ int main(int argc, char **argv) timer_output(); got_end_timer= TRUE; break; - case Q_CHARACTER_SET: + case Q_CHARACTER_SET: set_charset(q); break; case Q_DISABLE_PS_PROTOCOL: @@ -3977,11 +4196,17 @@ int main(int argc, char **argv) ps_protocol_enabled= ps_protocol; break; case Q_DISABLE_RECONNECT: - cur_con->mysql.reconnect= 0; + { + my_bool reconnect= 0; + mysql_options(&cur_con->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect); break; + } case Q_ENABLE_RECONNECT: - cur_con->mysql.reconnect= 1; + { + my_bool reconnect= 1; + mysql_options(&cur_con->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect); break; + } case Q_DISABLE_PARSING: parsing_disabled++; break; @@ -3997,13 +4222,16 @@ int main(int argc, char **argv) case Q_EXIT: abort_flag= 1; break; - default: processed = 0; break; + + default: + processed= 0; + break; } } if (!processed) { - current_line_inc = 0; + current_line_inc= 0; switch (q->type) { case Q_WHILE: do_block(cmd_while, q); break; case Q_IF: do_block(cmd_if, q); break; @@ -4011,16 +4239,48 @@ int main(int argc, char **argv) default: current_line_inc = 1; break; } } + else + check_eol_junk(q->last_argument); + + if (q->type != Q_ERROR) + { + /* + As soon as any non "error" command has been executed, + the array with expected errors should be cleared + */ + global_expected_errors= 0; + bzero((gptr) global_expected_errno, sizeof(global_expected_errno)); + } parser.current_line += current_line_inc; } - if (result_file && ds_res.length) + if (!query_executed && result_file && my_stat(result_file, &res_info, 0)) { - if (!record) - error |= check_result(&ds_res, result_file, q->require_file); + /* + my_stat() successful on result file. Check if we have not run a + single query, but we do have a result file that contains data. + Note that we don't care, if my_stat() fails. For example for + non-existing or non-readable file we assume it's fine to have + no query output from the test file, e.g. regarded as no error. + */ + if (res_info.st_size) + error|= (RESULT_CONTENT_MISMATCH | RESULT_LENGTH_MISMATCH); + } + if (ds_res.length && !error) + { + if (result_file) + { + if (!record) + error |= check_result(&ds_res, result_file, q->require_file); + else + str_to_file(result_file, ds_res.str, ds_res.length); + } else - str_to_file(result_file, ds_res.str, ds_res.length); + { + /* Print the result to stdout */ + printf("%s", ds_res.str); + } } dynstr_free(&ds_res); @@ -4874,7 +5134,7 @@ static void get_replace_column(struct st_query *q) free_replace_column(); if (!*from) - die("Missing argument in %s\n", q->query); + die("Missing argument in %s", q->query); /* Allocate a buffer for results */ start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE)); @@ -4885,15 +5145,16 @@ static void get_replace_column(struct st_query *q) to= get_string(&buff, &from, q); if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS) - die("Wrong column number to replace_columns in %s\n", q->query); + die("Wrong column number to replace_column in '%s'", q->query); if (!*from) - die("Wrong number of arguments to replace in %s\n", q->query); + die("Wrong number of arguments to replace_column in '%s'", q->query); to= get_string(&buff, &from, q); my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR); replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE)); set_if_bigger(max_replace_column, column_number); } my_free(start, MYF(0)); + q->last_argument= q->end; } #if defined(__NETWARE__) || defined(__WIN__) @@ -4944,7 +5205,7 @@ static char *subst_env_var(const char *str) if (!(subst= getenv(env_var))) { my_free(result, MYF(0)); - die("MYSQLTEST.NLM: Environment variable %s is not defined\n", + die("MYSQLTEST.NLM: Environment variable %s is not defined", env_var); } diff --git a/cmd-line-utils/readline/complete.c b/cmd-line-utils/readline/complete.c index 2196c66a54c..df0a698b81f 100644 --- a/cmd-line-utils/readline/complete.c +++ b/cmd-line-utils/readline/complete.c @@ -21,10 +21,18 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY +#if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) +#define _XOPEN_SOURCE 500 +#endif + #include "config_readline.h" #include + +/* To get SuSE 9.3 to define wcwidth() (in wchar.h) */ + #include + #if defined (HAVE_SYS_FILE_H) # include #endif @@ -1149,7 +1157,8 @@ compute_lcd_of_matches (match_list, matches, text) rl_completion_found_quote && rl_filename_quoting_desired) { - dtext = (*rl_filename_dequoting_function) (text, rl_completion_quote_character); + dtext = (*rl_filename_dequoting_function) + ((char*) text, rl_completion_quote_character); text = dtext; } diff --git a/cmd-line-utils/readline/display.c b/cmd-line-utils/readline/display.c index cab76c0da81..06eaa5e4be2 100644 --- a/cmd-line-utils/readline/display.c +++ b/cmd-line-utils/readline/display.c @@ -21,10 +21,16 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 500 +#endif + #include "config_readline.h" #include +/* To get SuSE 9.3 to define wcwidth() (in wchar.h) */ + #if defined (HAVE_UNISTD_H) # include #endif /* HAVE_UNISTD_H */ diff --git a/cmd-line-utils/readline/mbutil.c b/cmd-line-utils/readline/mbutil.c index c88e9485f39..284ea63aae4 100644 --- a/cmd-line-utils/readline/mbutil.c +++ b/cmd-line-utils/readline/mbutil.c @@ -21,9 +21,16 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 500 +#endif + #include "config_readline.h" #include + +/* To get SuSE 9.3 to define wcwidth() (in wchar.h) */ + #include #include "posixjmp.h" diff --git a/config/ac-macros/character_sets.m4 b/config/ac-macros/character_sets.m4 index 3ecc4bb5a03..1ab6e7dd780 100644 --- a/config/ac-macros/character_sets.m4 +++ b/config/ac-macros/character_sets.m4 @@ -343,7 +343,7 @@ case $default_charset in default_charset_default_collation="ucs2_general_ci" define(UCSC1, ucs2_general_ci ucs2_bin) define(UCSC2, ucs2_czech_ci ucs2_danish_ci) - define(UCSC3, ucs2_estonian_ci ucs2_icelandic_ci) + define(UCSC3, ucs2_esperanto_ci ucs2_estonian_ci ucs2_icelandic_ci) define(UCSC4, ucs2_latvian_ci ucs2_lithuanian_ci) define(UCSC5, ucs2_persian_ci ucs2_polish_ci ucs2_romanian_ci) define(UCSC6, ucs2_slovak_ci ucs2_slovenian_ci) @@ -367,7 +367,7 @@ case $default_charset in else define(UTFC1, utf8_general_ci utf8_bin) define(UTFC2, utf8_czech_ci utf8_danish_ci) - define(UTFC3, utf8_estonian_ci utf8_icelandic_ci) + define(UTFC3, utf8_esperanto_ci utf8_estonian_ci utf8_icelandic_ci) define(UTFC4, utf8_latvian_ci utf8_lithuanian_ci) define(UTFC5, utf8_persian_ci utf8_polish_ci utf8_romanian_ci) define(UTFC6, utf8_slovak_ci utf8_slovenian_ci) diff --git a/config/ac-macros/ha_federated.m4 b/config/ac-macros/ha_federated.m4 index 4383a9d8d55..5c991f31666 100644 --- a/config/ac-macros/ha_federated.m4 +++ b/config/ac-macros/ha_federated.m4 @@ -6,7 +6,7 @@ AC_DEFUN([MYSQL_CHECK_FEDERATED], [ AC_ARG_WITH([federated-storage-engine], [ --with-federated-storage-engine - Enable the MySQL Storage Engine], + Enable the MySQL Federated Storage Engine], [federateddb="$withval"], [federateddb=no]) AC_MSG_CHECKING([for MySQL federated storage engine]) diff --git a/config/ac-macros/ha_ndbcluster.m4 b/config/ac-macros/ha_ndbcluster.m4 index 509cd868909..2ff598242e4 100644 --- a/config/ac-macros/ha_ndbcluster.m4 +++ b/config/ac-macros/ha_ndbcluster.m4 @@ -140,7 +140,7 @@ AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [ AC_MSG_RESULT([Using NDB Cluster]) AC_DEFINE([HAVE_NDBCLUSTER_DB], [1], [Using Ndb Cluster DB]) have_ndbcluster="yes" - ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi" + ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi -I../ndb/include/mgmapi" ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a" ndbcluster_system_libs="" ndb_mgmclient_libs="\$(top_builddir)/ndb/src/mgmclient/libndbmgmclient.la" diff --git a/config/ac-macros/readline.m4 b/config/ac-macros/readline.m4 index 79c6479d15d..e47d0a44483 100644 --- a/config/ac-macros/readline.m4 +++ b/config/ac-macros/readline.m4 @@ -59,3 +59,42 @@ AC_DEFUN([MYSQL_CHECK_NEW_RL_INTERFACE], [ ) ) ]) + +dnl +dnl check for availability of multibyte characters and functions +dnl (Based on BASH_CHECK_MULTIBYTE in aclocal.m4 of readline-5.0) +dnl +AC_DEFUN([MYSQL_CHECK_MULTIBYTE], +[ +AC_CHECK_HEADERS(wctype.h) +AC_CHECK_HEADERS(wchar.h) +AC_CHECK_HEADERS(langinfo.h) + +AC_CHECK_FUNC(mbsrtowcs, AC_DEFINE([HAVE_MBSRTOWCS],[],[Define if you have mbsrtowcs])) +AC_CHECK_FUNC(mbrtowc, AC_DEFINE([HAVE_MBRTOWC],[],[Define if you have mbrtowc])) +AC_CHECK_FUNC(mbrlen, AC_DEFINE([HAVE_MBRLEN],[],[Define if you have mbrlen])) +AC_CHECK_FUNC(wctomb, AC_DEFINE([HAVE_WCTOMB],[],[Define if you have wctomb])) +AC_CHECK_FUNC(wcwidth, AC_DEFINE([HAVE_WCWIDTH],[],[Define if you have wcwidth])) +AC_CHECK_FUNC(wcsdup, AC_DEFINE([HAVE_WCSDUP],[],[Define if you check wcsdup])) + +AC_CACHE_CHECK([for mbstate_t], mysql_cv_have_mbstate_t, +[AC_TRY_COMPILE([ +#include ], [ + mbstate_t ps; + mbstate_t *psp; + psp = (mbstate_t *)0; +], mysql_cv_have_mbstate_t=yes, mysql_cv_have_mbstate_t=no)]) +if test $mysql_cv_have_mbstate_t = yes; then + AC_DEFINE([HAVE_MBSTATE_T],[],[Define if mysql_cv_have_mbstate_t=yes]) +fi + +AC_CACHE_CHECK([for nl_langinfo and CODESET], mysql_cv_langinfo_codeset, +[AC_TRY_LINK( +[#include ], +[char* cs = nl_langinfo(CODESET);], +mysql_cv_langinfo_codeset=yes, mysql_cv_langinfo_codeset=no)]) +if test $mysql_cv_langinfo_codeset = yes; then + AC_DEFINE([HAVE_LANGINFO_CODESET],[],[Define if mysql_cv_langinfo_codeset=yes]) +fi + +]) diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4 index 92133339343..dcd72cb14f1 100644 --- a/config/ac-macros/yassl.m4 +++ b/config/ac-macros/yassl.m4 @@ -20,6 +20,18 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ -L\$(top_builddir)/extra/yassl/taocrypt/src -ltaocrypt" openssl_includes="-I\$(top_srcdir)/extra/yassl/include" AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) + AC_DEFINE([HAVE_YASSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) + # System specific checks + yassl_integer_extra_cxxflags="" + case $host_cpu--$CXX_VERSION in + sparc*--*Sun*C++*5.6*) + # Disable inlining when compiling taocrypt/src/integer.cpp + yassl_integer_extra_cxxflags="+d" + AC_MSG_NOTICE([disabling inlining for yassl/taocrypt/src/integer.cpp]) + ;; + esac + AC_SUBST([yassl_integer_extra_cxxflags]) + else yassl_dir="" AC_MSG_RESULT(no) diff --git a/configure.in b/configure.in index 97e07baffd4..40ff480bb94 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.13-beta) +AM_INIT_AUTOMAKE(mysql, 5.0.16) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -18,8 +18,8 @@ SHARED_LIB_VERSION=15:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=13 -NDB_VERSION_STATUS="beta" +NDB_VERSION_BUILD=16 +NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? # Remember that regexps needs to quote [ and ] since this is run through m4 @@ -322,19 +322,19 @@ case "$target_os" in ;; esac ;; - sysv5UnixWare*) + sysv5UnixWare* | sysv5OpenUNIX8*) if test "$GCC" != "yes"; then - # We are using built-in inline function + # Use the built-in alloca() CFLAGS="$CFLAGS -Kalloca" fi CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA" ;; - sysv5OpenUNIX8*) + sysv5SCO_SV6.0.0*) if test "$GCC" != "yes"; then - # We are using built-in inline function + # Use the built-in alloca() CFLAGS="$CFLAGS -Kalloca" + CXXFLAGS="$CFLAGS -Kalloca" fi - CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA" ;; esac AC_SUBST(CC) @@ -1021,7 +1021,7 @@ case $SYSTEM_TYPE in *darwin5*) if test "$ac_cv_prog_gcc" = "yes" then - FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH" + FLAGS="-traditional-cpp -DHAVE_DARWIN5_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH" CFLAGS="$CFLAGS $FLAGS" CXXFLAGS="$CXXFLAGS $FLAGS" MAX_C_OPTIMIZE="-O" @@ -1031,17 +1031,16 @@ case $SYSTEM_TYPE in *darwin6*) if test "$ac_cv_prog_gcc" = "yes" then - FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH" + FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH" CFLAGS="$CFLAGS $FLAGS" CXXFLAGS="$CXXFLAGS $FLAGS" MAX_C_OPTIMIZE="-O" fi ;; - *darwin[[7-8]]*) - # don't forget to escape [] like above + *darwin*) if test "$ac_cv_prog_gcc" = "yes" then - FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT" + FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT" CFLAGS="$CFLAGS $FLAGS" CXXFLAGS="$CXXFLAGS $FLAGS" MAX_C_OPTIMIZE="-O" @@ -1359,8 +1358,6 @@ then if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null then AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1]) - else - AC_DEFINE(HAVE_UNIXWARE7_POSIX, [1]) fi AC_MSG_RESULT("yes") # We must have cc @@ -1386,87 +1383,40 @@ then AC_MSG_RESULT("no") fi fi -# Hack for SCO UnixWare7 -# -if test "$with_named_thread" = "no" -then - AC_MSG_CHECKING("SCO UnixWare7 native threads") - if expr "$SYSTEM_TYPE" : ".*UnixWare*" > /dev/null - then - if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so - then - MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK - if expr "$CC" : ".*gcc.*" - then - with_named_thread="-pthread -lsocket -lnsl" - else - with_named_thread="-Kthread -lsocket -lnsl" - fi - if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null - then - AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1]) - else - AC_DEFINE(HAVE_UNIXWARE7_POSIX, [1]) - fi - # We must have cc - AC_MSG_CHECKING("for gcc") - if expr "$CC" : ".*gcc.*" - then - CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" - CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" - else - CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" - CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" - fi - AC_MSG_RESULT("yes") - else - AC_MSG_ERROR([configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual.]) - fi - else - AC_MSG_RESULT("no") - fi -fi -# Hack for Caldera OpenUNIX8 +# +# Check for SCO threading libraries # if test "$with_named_thread" = "no" then - AC_MSG_CHECKING("OpenUNIX8 native threads") - if expr "$SYSTEM_TYPE" : ".*OpenUNIX*" > /dev/null + AC_MSG_CHECKING([SCO OpenServer 6, UnixWare 7 or OpenUNIX 8 native threads]) + if expr "$SYSTEM_TYPE" : ".*UnixWare.*" > /dev/null || \ + expr "$SYSTEM_TYPE" : ".*SCO_SV6.*" > /dev/null || \ + expr "$SYSTEM_TYPE" : ".*OpenUNIX.*" > /dev/null then if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so then MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK - if expr "$CC" : ".*gcc.*" + if expr "$CC" : ".*gcc.*" > /dev/null then - with_named_thread="-pthread -lsocket -lnsl" + with_named_thread="-pthread -lsocket -lnsl" + CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; + CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; else with_named_thread="-Kthread -lsocket -lnsl" + CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; + CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; fi if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null then - AC_DEFINE([HAVE_UNIXWARE7_THREADS], [1], - [UNIXWARE7 threads are not posix]) - else - AC_DEFINE([HAVE_UNIXWARE7_POSIX], [1], - [new UNIXWARE7 threads that are not yet posix]) + AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1], [Have UnixWare 7 (or similar) almost-POSIX threading library]) fi - # We must have cc - AC_MSG_CHECKING("for gcc") - if expr "$CC" : ".*gcc.*" - then - CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" - CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" - else - CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" - CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" - fi - AC_MSG_RESULT("yes") + AC_MSG_RESULT(yes) else - AC_MSG_ERROR([configure: error: Can't find thread libs on Caldera OpenUNIX 8. See the Installation chapter in the Reference Manual.]) + AC_MSG_ERROR([configure: error: Can't find thread library on SCO/Caldera system. See the Installation chapter in the Reference Manual.]) fi else - AC_MSG_RESULT("no") + AC_MSG_RESULT(no) fi fi @@ -1860,6 +1810,7 @@ MYSQL_HAVE_TIOCSTAT MYSQL_STRUCT_DIRENT_D_INO MYSQL_STRUCT_DIRENT_D_NAMLEN MYSQL_TYPE_SIGHANDLER +MYSQL_CHECK_MULTIBYTE if test "$with_named_curses" = "no" then MYSQL_CHECK_LIB_TERMCAP @@ -1911,7 +1862,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \ realpath rename rint rwlock_init setupterm \ shmget shmat shmdt shmctl sigaction sigemptyset sigaddset \ sighold sigset sigthreadmask \ - snprintf socket stpcpy strcasecmp strerror strnlen strpbrk strstr strtol \ + snprintf socket stpcpy strcasecmp strerror strsignal strnlen strpbrk strstr strtol \ strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr) # @@ -2508,7 +2459,7 @@ then AC_CONFIG_FILES(bdb/Makefile) echo "CONFIGURING FOR BERKELEY DB" - bdb_conf_flags="--disable-shared" + bdb_conf_flags="--disable-shared --build=$build_alias" if test $with_debug = "yes" then bdb_conf_flags="$bdb_conf_flags --enable-debug --enable-diagnostic" diff --git a/dbug/my_main.c b/dbug/my_main.c index ed1c9329235..31c15aa67aa 100644 --- a/dbug/my_main.c +++ b/dbug/my_main.c @@ -8,6 +8,7 @@ #endif #include /* This includes dbug.h */ +#include int main (argc, argv) int argc; diff --git a/extra/Makefile.am b/extra/Makefile.am index cb06e7495f9..457fddce673 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -38,7 +38,7 @@ $(top_builddir)/include/mysqld_ername.h: $(top_builddir)/include/mysqld_error.h $(top_builddir)/include/sql_state.h: $(top_builddir)/include/mysqld_error.h bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \ - resolve_stack_dump mysql_waitpid + resolve_stack_dump mysql_waitpid innochecksum noinst_PROGRAMS = charset2html # Don't update the files from bitkeeper diff --git a/extra/comp_err.c b/extra/comp_err.c index 85833999d5c..d0e387dcd35 100644 --- a/extra/comp_err.c +++ b/extra/comp_err.c @@ -51,7 +51,7 @@ uint file_pos[MAX_ROWS]; const char *empty_string= ""; /* For empty states */ /* - Default values for command line options. See getopt structure for defintions + Default values for command line options. See getopt structure for definitions for these. */ @@ -131,7 +131,8 @@ static struct languages *parse_charset_string(char *str); static struct errors *parse_error_string(char *ptr, int er_count); static struct message *parse_message_string(struct message *new_message, char *str); -static struct message *find_message(struct errors *err, const char *lang); +static struct message *find_message(struct errors *err, const char *lang, + my_bool no_default); static int parse_input_file(const char *file_name, struct errors **top_error, struct languages **top_language); static int get_options(int *argc, char ***argv); @@ -227,7 +228,7 @@ static int create_header_files(struct errors *error_head) { /* generating mysqld_error.h - fprintf() will automaticly add \r on windows + fprintf() will automatically add \r on windows */ fprintf(er_definef, "#define %s %d\n", tmp_error->er_name, tmp_error->d_code); @@ -305,7 +306,7 @@ static int create_sys_files(struct languages *lang_head, for (tmp_error= error_head; tmp_error; tmp_error= tmp_error->next_error) { /* dealing with messages */ - tmp= find_message(tmp_error, tmp_lang->lang_short_name); + tmp= find_message(tmp_error, tmp_lang->lang_short_name, FALSE); if (!tmp) { @@ -450,6 +451,13 @@ static int parse_input_file(const char *file_name, struct errors **top_error, current_error->er_name); DBUG_RETURN(0); } + if (find_message(current_error, current_message.lang_short_name, TRUE)) + { + fprintf(stderr, "Duplicate message string for error '%s'" + " in language '%s'\n", + current_error->er_name, current_message.lang_short_name); + DBUG_RETURN(0); + } if (insert_dynamic(¤t_error->msg, (byte *) & current_message)) DBUG_RETURN(0); continue; @@ -518,14 +526,14 @@ static uint parse_error_offset(char *str) } -/* Parsing of the default language line. e.g. "default-lanuage eng" */ +/* Parsing of the default language line. e.g. "default-language eng" */ static char *parse_default_language(char *str) { char *slang; DBUG_ENTER("parse_default_language"); - /* skipping the "default_language" keyword */ + /* skipping the "default-language" keyword */ str= find_end_of_word(str); /* skipping space(s) and/or tabs after the keyword */ str= skip_delimiters(str); @@ -556,11 +564,19 @@ static char *parse_default_language(char *str) /* - For given error finds message on given language, if does not exist, - returns english. -*/ + Find the message in a particular language -static struct message *find_message(struct errors *err, const char *lang) + SYNOPSIS + find_message() + err Error to find message for + lang Language of message to find + no_default Don't return default (English) if does not exit + + RETURN VALUE + Returns the message structure if one is found, or NULL if not. +*/ +static struct message *find_message(struct errors *err, const char *lang, + my_bool no_default) { struct message *tmp, *return_val= 0; uint i, count; @@ -579,7 +595,7 @@ static struct message *find_message(struct errors *err, const char *lang) return_val= tmp; } } - DBUG_RETURN(return_val); + DBUG_RETURN(no_default ? NULL : return_val); } @@ -697,7 +713,7 @@ static struct errors *parse_error_string(char *str, int er_count) DBUG_ENTER("parse_error_string"); DBUG_PRINT("enter", ("str: %s", str)); - /* create a new a element */ + /* create a new element */ new_error= (struct errors *) my_malloc(sizeof(*new_error), MYF(MY_WME)); if (my_init_dynamic_array(&new_error->msg, sizeof(struct message), 0, 0)) @@ -762,7 +778,7 @@ static struct errors *parse_error_string(char *str, int er_count) /* - Parsing the string with charset/full lang name/short lang name; + Parsing the string with full lang name/short lang name/charset; returns pointer to the language structure */ @@ -814,7 +830,7 @@ static struct languages *parse_charset_string(char *str) DBUG_RETURN(0); /* Fatal error */ DBUG_PRINT("info", ("charset: %s", new_lang->charset)); - /* skipping space, tub or "," */ + /* skipping space, tab or "," */ str= skip_delimiters(str); } while (*str != ';' && *str); diff --git a/extra/innochecksum.c b/extra/innochecksum.c new file mode 100644 index 00000000000..739953298af --- /dev/null +++ b/extra/innochecksum.c @@ -0,0 +1,328 @@ +/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + InnoDB offline file checksum utility. 85% of the code in this file + was taken wholesale fron the InnoDB codebase. + + The final 15% was originally written by Mark Smith of Danga + Interactive, Inc. + + Published with a permission. +*/ + +/* needed to have access to 64 bit file functions */ +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#include +#include +#include +#include +#include +#include + +/* all of these ripped from InnoDB code from MySQL 4.0.22 */ +#define UT_HASH_RANDOM_MASK 1463735687 +#define UT_HASH_RANDOM_MASK2 1653893711 +#define FIL_PAGE_LSN 16 +#define FIL_PAGE_FILE_FLUSH_LSN 26 +#define FIL_PAGE_OFFSET 4 +#define FIL_PAGE_DATA 38 +#define FIL_PAGE_END_LSN_OLD_CHKSUM 8 +#define FIL_PAGE_SPACE_OR_CHKSUM 0 +#define UNIV_PAGE_SIZE (2 * 8192) + +/* command line argument to do page checks (that's it) */ +/* another argument to specify page ranges... seek to right spot and go from there */ + +typedef unsigned long int ulint; +typedef unsigned char byte; + +/* innodb function in name; modified slightly to not have the ASM version (lots of #ifs that didn't apply) */ +ulint mach_read_from_4(byte *b) +{ + return( ((ulint)(b[0]) << 24) + + ((ulint)(b[1]) << 16) + + ((ulint)(b[2]) << 8) + + (ulint)(b[3]) + ); +} + +ulint +ut_fold_ulint_pair( +/*===============*/ + /* out: folded value */ + ulint n1, /* in: ulint */ + ulint n2) /* in: ulint */ +{ + return(((((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1) + ^ UT_HASH_RANDOM_MASK) + n2); +} + +ulint +ut_fold_binary( +/*===========*/ + /* out: folded value */ + byte* str, /* in: string of bytes */ + ulint len) /* in: length */ +{ + ulint i; + ulint fold= 0; + + for (i= 0; i < len; i++) + { + fold= ut_fold_ulint_pair(fold, (ulint)(*str)); + + str++; + } + + return(fold); +} + +ulint +buf_calc_page_new_checksum( +/*=======================*/ + /* out: checksum */ + byte* page) /* in: buffer page */ +{ + ulint checksum; + + /* Since the fields FIL_PAGE_FILE_FLUSH_LSN and ..._ARCH_LOG_NO + are written outside the buffer pool to the first pages of data + files, we have to skip them in the page checksum calculation. + We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the + checksum is stored, and also the last 8 bytes of page because + there we store the old formula checksum. */ + + checksum= ut_fold_binary(page + FIL_PAGE_OFFSET, + FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET) + + ut_fold_binary(page + FIL_PAGE_DATA, + UNIV_PAGE_SIZE - FIL_PAGE_DATA + - FIL_PAGE_END_LSN_OLD_CHKSUM); + checksum= checksum & 0xFFFFFFFF; + + return(checksum); +} + +ulint +buf_calc_page_old_checksum( +/*=======================*/ + /* out: checksum */ + byte* page) /* in: buffer page */ +{ + ulint checksum; + + checksum= ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN); + + checksum= checksum & 0xFFFFFFFF; + + return(checksum); +} + + +int main(int argc, char **argv) +{ + FILE *f; /* our input file */ + byte *p; /* storage of pages read */ + int bytes; /* bytes read count */ + ulint ct; /* current page number (0 based) */ + int now; /* current time */ + int lastt; /* last time */ + ulint oldcsum, oldcsumfield, csum, csumfield, logseq, logseqfield; /* ulints for checksum storage */ + struct stat st; /* for stat, if you couldn't guess */ + unsigned long long int size; /* size of file (has to be 64 bits) */ + ulint pages; /* number of pages in file */ + ulint start_page= 0, end_page= 0, use_end_page= 0; /* for starting and ending at certain pages */ + off_t offset= 0; + int just_count= 0; /* if true, just print page count */ + int verbose= 0; + int debug= 0; + int c; + int fd; + + /* remove arguments */ + while ((c= getopt(argc, argv, "cvds:e:p:")) != -1) + { + switch (c) + { + case 'v': + verbose= 1; + break; + case 'c': + just_count= 1; + break; + case 's': + start_page= atoi(optarg); + break; + case 'e': + end_page= atoi(optarg); + use_end_page= 1; + break; + case 'p': + start_page= atoi(optarg); + end_page= atoi(optarg); + use_end_page= 1; + break; + case 'd': + debug= 1; + break; + case ':': + fprintf(stderr, "option -%c requires an argument\n", optopt); + return 1; + break; + case '?': + fprintf(stderr, "unrecognized option: -%c\n", optopt); + return 1; + break; + } + } + + /* debug implies verbose... */ + if (debug) verbose= 1; + + /* make sure we have the right arguments */ + if (optind >= argc) + { + printf("InnoDB offline file checksum utility.\n"); + printf("usage: %s [-c] [-s ] [-e ] [-p ] [-v] [-d] \n", argv[0]); + printf("\t-c\tprint the count of pages in the file\n"); + printf("\t-s n\tstart on this page number (0 based)\n"); + printf("\t-e n\tend at this page number (0 based)\n"); + printf("\t-p n\tcheck only this page (0 based)\n"); + printf("\t-v\tverbose (prints progress every 5 seconds)\n"); + printf("\t-d\tdebug mode (prints checksums for each page)\n"); + return 1; + } + + /* stat the file to get size and page count */ + if (stat(argv[optind], &st)) + { + perror("error statting file"); + return 1; + } + size= st.st_size; + pages= size / UNIV_PAGE_SIZE; + if (just_count) + { + printf("%lu\n", pages); + return 0; + } + else if (verbose) + { + printf("file %s= %llu bytes (%lu pages)...\n", argv[1], size, pages); + printf("checking pages in range %lu to %lu\n", start_page, use_end_page ? end_page : (pages - 1)); + } + + /* open the file for reading */ + f= fopen(argv[optind], "r"); + if (!f) + { + perror("error opening file"); + return 1; + } + + /* seek to the necessary position */ + if (start_page) + { + fd= fileno(f); + if (!fd) + { + perror("unable to obtain file descriptor number"); + return 1; + } + + offset= (off_t)start_page * (off_t)UNIV_PAGE_SIZE; + + if (lseek(fd, offset, SEEK_SET) != offset) + { + perror("unable to seek to necessary offset"); + return 1; + } + } + + /* allocate buffer for reading (so we don't realloc every time) */ + p= (byte *)malloc(UNIV_PAGE_SIZE); + + /* main checksumming loop */ + ct= start_page; + lastt= 0; + while (!feof(f)) + { + bytes= fread(p, 1, UNIV_PAGE_SIZE, f); + if (!bytes && feof(f)) return 0; + if (bytes != UNIV_PAGE_SIZE) + { + fprintf(stderr, "bytes read (%d) doesn't match universal page size (%d)\n", bytes, UNIV_PAGE_SIZE); + return 1; + } + + /* check the "stored log sequence numbers" */ + logseq= mach_read_from_4(p + FIL_PAGE_LSN + 4); + logseqfield= mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + 4); + if (debug) + printf("page %lu: log sequence number: first = %lu; second = %lu\n", ct, logseq, logseqfield); + if (logseq != logseqfield) + { + fprintf(stderr, "page %lu invalid (fails log sequence number check)\n", ct); + return 1; + } + + /* check old method of checksumming */ + oldcsum= buf_calc_page_old_checksum(p); + oldcsumfield= mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM); + if (debug) + printf("page %lu: old style: calculated = %lu; recorded = %lu\n", ct, oldcsum, oldcsumfield); + if (oldcsumfield != mach_read_from_4(p + FIL_PAGE_LSN) && oldcsumfield != oldcsum) + { + fprintf(stderr, "page %lu invalid (fails old style checksum)\n", ct); + return 1; + } + + /* now check the new method */ + csum= buf_calc_page_new_checksum(p); + csumfield= mach_read_from_4(p + FIL_PAGE_SPACE_OR_CHKSUM); + if (debug) + printf("page %lu: new style: calculated = %lu; recorded = %lu\n", ct, csum, csumfield); + if (csumfield != 0 && csum != csumfield) + { + fprintf(stderr, "page %lu invalid (fails new style checksum)\n", ct); + return 1; + } + + /* end if this was the last page we were supposed to check */ + if (use_end_page && (ct >= end_page)) + return 0; + + /* do counter increase and progress printing */ + ct++; + if (verbose) + { + if (ct % 64 == 0) + { + now= time(0); + if (!lastt) lastt= now; + if (now - lastt >= 1) + { + printf("page %lu okay: %.3f%% done\n", (ct - 1), (float) ct / pages * 100); + lastt= now; + } + } + } + } + return 0; +} + diff --git a/extra/perror.c b/extra/perror.c index dedd558e4cf..919088ba42e 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -25,6 +25,7 @@ #include #ifdef HAVE_NDBCLUSTER_DB #include "../ndb/src/ndbapi/ndberror.c" +#include "../ndb/src/kernel/error/ndbd_exit_codes.c" #endif static my_bool verbose, print_all_codes; @@ -235,8 +236,11 @@ int main(int argc,char *argv[]) #ifdef HAVE_NDBCLUSTER_DB if (ndb_code) { - if (ndb_error_string(code, ndb_string, sizeof(ndb_string)) < 0) - msg= 0; + if ((ndb_error_string(code, ndb_string, sizeof(ndb_string)) < 0) && + (ndbd_exit_string(code, ndb_string, sizeof(ndb_string)) < 0)) + { + msg= 0; + } else msg= ndb_string; } diff --git a/extra/yassl/mySTL/helpers.hpp b/extra/yassl/mySTL/helpers.hpp index 8d2061fc4f1..de825c23fec 100644 --- a/extra/yassl/mySTL/helpers.hpp +++ b/extra/yassl/mySTL/helpers.hpp @@ -28,14 +28,11 @@ #define mySTL_HELPERS_HPP #include -#include // placement new - - -#ifdef __IBMCPP__ /* Workaround for the lack of operator new(size_t, void*) in IBM VA C++ 6.0 + Also used as a workaround to avoid including */ struct Dummy {}; @@ -45,9 +42,6 @@ } typedef Dummy* yassl_pointer; -#else - typedef void* yassl_pointer; -#endif namespace mySTL { diff --git a/extra/yassl/mySTL/list.hpp b/extra/yassl/mySTL/list.hpp index 8aaeefaafe8..dd8485f48a7 100644 --- a/extra/yassl/mySTL/list.hpp +++ b/extra/yassl/mySTL/list.hpp @@ -164,7 +164,7 @@ void list::push_front(T t) { void* mem = malloc(sizeof(node)); if (!mem) abort(); - node* add = new (mem) node(t); + node* add = new (reinterpret_cast(mem)) node(t); if (head_) { add->next_ = head_; @@ -210,7 +210,7 @@ void list::push_back(T t) { void* mem = malloc(sizeof(node)); if (!mem) abort(); - node* add = new (mem) node(t); + node* add = new (reinterpret_cast(mem)) node(t); if (tail_) { tail_->next_ = add; diff --git a/extra/yassl/mySTL/vector.hpp b/extra/yassl/mySTL/vector.hpp index e7f63c37c7c..9eab91cfda8 100644 --- a/extra/yassl/mySTL/vector.hpp +++ b/extra/yassl/mySTL/vector.hpp @@ -45,7 +45,8 @@ struct vector_base { vector_base() : start_(0), finish_(0), end_of_storage_(0) {} vector_base(size_t n) { - start_ = static_cast(malloc(n * sizeof(T))); + // Don't allow malloc(0), if n is 0 use 1 + start_ = static_cast(malloc((n ? n : 1) * sizeof(T))); if (!start_) abort(); finish_ = start_; end_of_storage_ = start_ + n; diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp index 2252dfafdc5..91cea1f9753 100644 --- a/extra/yassl/src/socket_wrapper.cpp +++ b/extra/yassl/src/socket_wrapper.cpp @@ -93,11 +93,15 @@ void Socket::closeSocket() uint Socket::get_ready() const { - unsigned long ready = 0; - #ifdef _WIN32 + unsigned long ready = 0; ioctlsocket(socket_, FIONREAD, &ready); #else + /* + 64-bit Solaris requires the variable passed to + FIONREAD be a 32-bit value. + */ + int ready = 0; ioctl(socket_, FIONREAD, &ready); #endif diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index d37c44049b2..8cea205377e 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -171,13 +171,25 @@ int SSL_accept(SSL* ssl) sendServerHelloDone(*ssl); ssl->flushBuffer(); - processReply(*ssl); + // Java Client sends fragmented response + while (ssl->getStates().getServer() < + clientFinishedComplete) { + if (ssl->GetError()) break; + processReply(*ssl); + } } sendChangeCipher(*ssl); sendFinished(*ssl, server_end); ssl->flushBuffer(); - if (ssl->getSecurity().get_resuming()) - processReply(*ssl); + if (ssl->getSecurity().get_resuming()) { + + // Java Client sends fragmented response + while (ssl->getStates().getServer() < + clientFinishedComplete) { + if (ssl->GetError()) break; + processReply(*ssl); + } + } ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); diff --git a/extra/yassl/taocrypt/include/hmac.hpp b/extra/yassl/taocrypt/include/hmac.hpp index 543366afc3a..cf029812ce2 100644 --- a/extra/yassl/taocrypt/include/hmac.hpp +++ b/extra/yassl/taocrypt/include/hmac.hpp @@ -56,12 +56,12 @@ private: T mac_; // MSVC 6 HACK, gives compiler error if calculated in array - enum { BSIZE = T::BLOCK_SIZE / sizeof(word32), - DSIZE = T::DIGEST_SIZE / sizeof(word32) }; + enum { HMAC_BSIZE = T::BLOCK_SIZE / sizeof(word32), + HMAC_DSIZE = T::DIGEST_SIZE / sizeof(word32) }; - word32 ip_[BSIZE]; // align ipad_ on word32 - word32 op_[BSIZE]; // align opad_ on word32 - word32 innerH_[DSIZE]; // align innerHash_ on word32 + word32 ip_[HMAC_BSIZE]; // align ipad_ on word32 + word32 op_[HMAC_BSIZE]; // align opad_ on word32 + word32 innerH_[HMAC_DSIZE]; // align innerHash_ on word32 void KeyInnerHash(); diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp index 187d5cc6769..f705cc99970 100644 --- a/extra/yassl/taocrypt/include/misc.hpp +++ b/extra/yassl/taocrypt/include/misc.hpp @@ -91,7 +91,14 @@ public: // no gas on these systems ?, disable for now -#if defined(__sun__) || defined (__QNX__) +#if defined(__sun__) || defined (__QNX__) || defined (__APPLE__) + #define TAOCRYPT_DISABLE_X86ASM +#endif + + +// Disable assmebler when compiling with icc +// Temporary workaround for bug12717 +#if defined(__INTEL_COMPILER) #define TAOCRYPT_DISABLE_X86ASM #endif diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp index f506040f0d8..254e67a7f64 100644 --- a/extra/yassl/taocrypt/include/runtime.hpp +++ b/extra/yassl/taocrypt/include/runtime.hpp @@ -25,7 +25,8 @@ -#if !defined(yaSSL_NEW_HPP) && defined(__GNUC__) && !defined(__ICC) +#if !defined(yaSSL_NEW_HPP) && defined(__GNUC__) +#if !(defined(__ICC) || defined(__INTEL_COMPILER)) #define yaSSL_NEW_HPP @@ -46,5 +47,6 @@ static int __cxa_pure_virtual() } // extern "C" #endif // __GNUC__ > 2 +#endif // ! _ICC #endif // yaSSL_NEW_HPP && __GNUC__ diff --git a/extra/yassl/taocrypt/include/types.hpp b/extra/yassl/taocrypt/include/types.hpp index 92164eaaab4..db9c3792bbd 100644 --- a/extra/yassl/taocrypt/include/types.hpp +++ b/extra/yassl/taocrypt/include/types.hpp @@ -61,9 +61,10 @@ typedef unsigned int word32; // compilers we've found 64-bit multiply insructions for #if defined(__GNUC__) || defined(_MSC_VER) || defined(__DECCXX) +#if !(defined(__ICC) || defined(__INTEL_COMPILER)) #define HAVE_64_MULTIPLY #endif - +#endif #if defined(HAVE_64_MULTIPLY) && (defined(__alpha__) || defined(__ia64__) \ || defined(_ARCH_PPC64) || defined(__mips64) || defined(__x86_64__)) diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am index 4549c218d87..c4fc4607622 100644 --- a/extra/yassl/taocrypt/src/Makefile.am +++ b/extra/yassl/taocrypt/src/Makefile.am @@ -1,9 +1,12 @@ INCLUDES = -I../include -I../../mySTL -noinst_LTLIBRARIES = libtaocrypt.la +noinst_LTLIBRARIES = libtaocrypt.la libtaoint.la libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \ - coding.cpp dh.cpp des.cpp dsa.cpp file.cpp hash.cpp integer.cpp \ + coding.cpp dh.cpp des.cpp dsa.cpp file.cpp hash.cpp \ md2.cpp md5.cpp misc.cpp random.cpp ripemd.cpp rsa.cpp sha.cpp \ template_instnt.cpp +libtaocrypt_la_LIBADD = libtaoint.la +libtaoint_la_SOURCES = integer.cpp +libtaoint_la_CXXFLAGS = @yassl_integer_extra_cxxflags@ EXTRA_DIST = ../include/*.hpp AM_CXXFLAGS = -DYASSL_PURE_C diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp index ef051332098..0b33bb38aea 100644 --- a/extra/yassl/taocrypt/src/misc.cpp +++ b/extra/yassl/taocrypt/src/misc.cpp @@ -24,7 +24,6 @@ #include "runtime.hpp" #include "misc.hpp" -#include // for NewHandler void* operator new(size_t sz, TaoCrypt::new_t) diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp index e1e6416eb00..cf0720b11d8 100644 --- a/extra/yassl/taocrypt/src/random.cpp +++ b/extra/yassl/taocrypt/src/random.cpp @@ -95,7 +95,11 @@ OS_Seed::OS_Seed() { fd_ = open("/dev/urandom",O_RDONLY); if (fd_ == -1) + { + fd_ = open("/dev/random",O_RDONLY); + if (fd_ == -1) error_.SetError(OPEN_RAN_E); + } } diff --git a/heap/hp_hash.c b/heap/hp_hash.c index d643f776731..77f3cf6d80b 100644 --- a/heap/hp_hash.c +++ b/heap/hp_hash.c @@ -551,11 +551,13 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2, } if (cs->mbmaxlen > 1) { + uint safe_length1= char_length1; + uint safe_length2= char_length2; uint char_length= seg->length / cs->mbmaxlen; - char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length1); - set_if_smaller(char_length1, seg->length); - char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length2); - set_if_smaller(char_length2, seg->length); + char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length); + set_if_smaller(char_length1, safe_length1); + char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length); + set_if_smaller(char_length2, safe_length2); } if (cs->coll->strnncollsp(seg->charset, diff --git a/include/config-win.h b/include/config-win.h index 4eaf97cd4f5..fe099c11a2f 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -193,7 +193,7 @@ typedef uint rf_SetTimer; /* Convert some simple functions to Posix */ -#define sigset(A,B) signal((A),(B)) +#define my_sigset(A,B) signal((A),(B)) #define finite(A) _finite(A) #define sleep(A) Sleep((A)*1000) #define popen(A) popen(A,B) _popen((A),(B)) diff --git a/include/keycache.h b/include/keycache.h index a292a69b0a3..9fe1cce5da5 100644 --- a/include/keycache.h +++ b/include/keycache.h @@ -90,10 +90,10 @@ typedef struct st_key_cache /* Statistics variables. These are reset in reset_key_cache_counters(). */ ulong global_blocks_changed; /* number of currently dirty blocks */ - ulong global_cache_w_requests;/* number of write requests (write hits) */ - ulong global_cache_write; /* number of writes from the cache to files */ - ulong global_cache_r_requests;/* number of read requests (read hits) */ - ulong global_cache_read; /* number of reads from files to the cache */ + ulonglong global_cache_w_requests;/* number of write requests (write hits) */ + ulonglong global_cache_write; /* number of writes from cache to files */ + ulonglong global_cache_r_requests;/* number of read requests (read hits) */ + ulonglong global_cache_read; /* number of reads from files to cache */ int blocks; /* max number of blocks in the cache */ my_bool in_init; /* Set to 1 in MySQL during init/resize */ diff --git a/include/m_ctype.h b/include/m_ctype.h index e0a26c4ce56..b7361cb7d7b 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -231,6 +231,7 @@ typedef struct charset_info_st uint mbmaxlen; uint16 min_sort_char; uint16 max_sort_char; /* For LIKE optimization */ + uchar pad_char; my_bool escape_with_backslash_is_dangerous; MY_CHARSET_HANDLER *cset; diff --git a/include/m_string.h b/include/m_string.h index 33ba9c155c2..c02ce92cd88 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -129,15 +129,6 @@ extern void bmove_align(gptr dst,const gptr src,uint len); #define bmove512(A,B,C) memcpy(A,B,C) #endif -#ifdef HAVE_purify -#define memcpy_overlap(A,B,C) \ -DBUG_ASSERT((A) <= (B) || ((B)+(C)) <= (A)); \ -bmove((byte*) (A),(byte*) (B),(size_t) (C)); -#else -#define memcpy_overlap(A,B,C) memcpy((A), (B), (C)) -#endif /* HAVE_purify */ - - /* Prototypes for string functions */ #if !defined(bfill) && !defined(HAVE_BFILL) diff --git a/include/my_global.h b/include/my_global.h index a4177f8ea7c..b32a8fe6baa 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -107,6 +107,14 @@ #define _GNU_SOURCE 1 #endif +/* + Temporary solution to solve bug#7156. Include "sys/types.h" before + the thread headers, else the function madvise() will not be defined +*/ +#if defined(HAVE_SYS_TYPES_H) && ( defined(sun) || defined(__sun) ) +#include +#endif + /* The client defines this to avoid all thread code */ #if defined(UNDEF_THREADS_HACK) #undef THREAD @@ -230,7 +238,7 @@ C_MODE_END /* Fix a bug in gcc 2.8.0 on IRIX 6.2 */ -#if SIZEOF_LONG == 4 && defined(__LONG_MAX__) +#if SIZEOF_LONG == 4 && defined(__LONG_MAX__) && (__GNUC__ == 2 && __GNUC_MINOR__ == 8) #undef __LONG_MAX__ /* Is a longlong value in gcc 2.8.0 ??? */ #define __LONG_MAX__ 2147483647 #endif @@ -344,7 +352,9 @@ extern "C" int madvise(void *addr, size_t len, int behav); #undef LONGLONG_MIN /* These get wrongly defined in QNX 6.2 */ #undef LONGLONG_MAX /* standard system library 'limits.h' */ #ifdef __cplusplus -#define HAVE_RINT /* rint() and isnan() functions are not */ +#ifndef HAVE_RINT +#define HAVE_RINT +#endif /* rint() and isnan() functions are not */ #define rint(a) std::rint(a) /* visible in C++ scope due to an error */ #define isnan(a) std::isnan(a) /* in the usr/include/math.h on QNX */ #endif @@ -834,6 +844,7 @@ typedef off_t os_off_t; #define socket_errno WSAGetLastError() #define SOCKET_EINTR WSAEINTR #define SOCKET_EAGAIN WSAEINPROGRESS +#define SOCKET_ETIMEDOUT WSAETIMEDOUT #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK #define SOCKET_ENFILE ENFILE #define SOCKET_EMFILE EMFILE @@ -841,6 +852,7 @@ typedef off_t os_off_t; #define socket_errno sock_errno() #define SOCKET_EINTR SOCEINTR #define SOCKET_EAGAIN SOCEINPROGRESS +#define SOCKET_ETIMEDOUT SOCKET_EINTR #define SOCKET_EWOULDBLOCK SOCEWOULDBLOCK #define SOCKET_ENFILE SOCENFILE #define SOCKET_EMFILE SOCEMFILE @@ -850,6 +862,7 @@ typedef off_t os_off_t; #define closesocket(A) close(A) #define SOCKET_EINTR EINTR #define SOCKET_EAGAIN EAGAIN +#define SOCKET_ETIMEDOUT SOCKET_EINTR #define SOCKET_EWOULDBLOCK EWOULDBLOCK #define SOCKET_ENFILE ENFILE #define SOCKET_EMFILE EMFILE diff --git a/include/my_pthread.h b/include/my_pthread.h index 47a38d1a642..3d9056541d7 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -25,7 +25,10 @@ #endif #ifdef __cplusplus +#define EXTERN_C extern "C" extern "C" { +#else +#define EXTERN_C #endif /* __cplusplus */ #if defined(__WIN__) || defined(OS2) @@ -77,10 +80,10 @@ struct timespec { /* For pthread_cond_timedwait() */ typedef int pthread_mutexattr_t; #define win_pthread_self my_thread_var->pthread_self #ifdef OS2 -#define pthread_handler_decl(A,B) void * _Optlink A(void *B) +#define pthread_handler_t EXTERN_C void * _Optlink typedef void * (_Optlink *pthread_handler)(void *); #else -#define pthread_handler_decl(A,B) void * __cdecl A(void *B) +#define pthread_handler_t EXTERN_C void * __cdecl typedef void * (__cdecl *pthread_handler)(void *); #endif @@ -144,7 +147,7 @@ extern int pthread_mutex_destroy (pthread_mutex_t *); #define pthread_kill(A,B) raise(B) #define pthread_exit(A) pthread_dummy() #else -#define pthread_mutex_init(A,B) InitializeCriticalSection(A) +#define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0) #define pthread_mutex_lock(A) (EnterCriticalSection(A),0) #define pthread_mutex_trylock(A) (WaitForSingleObject((A), 0) == WAIT_TIMEOUT) #define pthread_mutex_unlock(A) LeaveCriticalSection(A) @@ -184,7 +187,7 @@ typedef int pthread_attr_t; /* Needed by Unixware 7.0.0 */ #define pthread_key_create(A,B) thr_keycreate((A),(B)) #define pthread_key_delete(A) thr_keydelete(A) -#define pthread_handler_decl(A,B) void *A(void *B) +#define pthread_handler_t EXTERN_C void * #define pthread_key(T,V) pthread_key_t V void * my_pthread_getspecific_imp(pthread_key_t key); @@ -262,7 +265,7 @@ extern int my_pthread_getprio(pthread_t thread_id); #define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V)) #define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V)) #define pthread_detach_this_thread() -#define pthread_handler_decl(A,B) void *A(void *B) +#define pthread_handler_t EXTERN_C void * typedef void *(* pthread_handler)(void *); /* Test first for RTS or FSU threads */ @@ -289,8 +292,6 @@ extern int my_pthread_create_detached; #undef HAVE_PTHREAD_RWLOCK_RDLOCK #undef HAVE_SNPRINTF -#define sigset(A,B) pthread_signal((A),(void (*)(int)) (B)) -#define signal(A,B) pthread_signal((A),(void (*)(int)) (B)) #define my_pthread_attr_setprio(A,B) #endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */ @@ -298,11 +299,6 @@ extern int my_pthread_create_detached; int sigwait(sigset_t *set, int *sig); #endif -#if defined(HAVE_UNIXWARE7_POSIX) -#undef HAVE_NONPOSIX_SIGWAIT -#define HAVE_NONPOSIX_SIGWAIT /* sigwait takes only 1 argument */ -#endif - #ifndef HAVE_NONPOSIX_SIGWAIT #define my_sigwait(A,B) sigwait((A),(B)) #else @@ -327,14 +323,26 @@ extern int my_pthread_cond_init(pthread_cond_t *mp, #if !defined(HAVE_SIGWAIT) && !defined(HAVE_mit_thread) && !defined(HAVE_rts_threads) && !defined(sigwait) && !defined(alpha_linux_port) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) && !defined(_AIX) int sigwait(sigset_t *setp, int *sigp); /* Use our implemention */ #endif -#if !defined(HAVE_SIGSET) && !defined(HAVE_mit_thread) && !defined(sigset) -#define sigset(A,B) do { struct sigaction s; sigset_t set; \ - sigemptyset(&set); \ - s.sa_handler = (B); \ - s.sa_mask = set; \ - s.sa_flags = 0; \ - sigaction((A), &s, (struct sigaction *) NULL); \ - } while (0) + + +/* + We define my_sigset() and use that instead of the system sigset() so that + we can favor an implementation based on sigaction(). On some systems, such + as Mac OS X, sigset() results in flags such as SA_RESTART being set, and + we want to make sure that no such flags are set. +*/ +#if defined(HAVE_SIGACTION) && !defined(my_sigset) +#define my_sigset(A,B) do { struct sigaction s; sigset_t set; \ + sigemptyset(&set); \ + s.sa_handler = (B); \ + s.sa_mask = set; \ + s.sa_flags = 0; \ + sigaction((A), &s, (struct sigaction *) NULL); \ + } while (0) +#elif defined(HAVE_SIGSET) && !defined(my_sigset) +#define my_sigset(A,B) sigset((A),(B)) +#elif !defined(my_sigset) +#define my_sigset(A,B) signal((A),(B)) #endif #ifndef my_pthread_setprio @@ -414,16 +422,13 @@ struct tm *gmtime_r(const time_t *clock, struct tm *res); #define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); } #endif -#ifdef HAVE_DARWIN_THREADS +#ifdef HAVE_DARWIN5_THREADS #define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C)) #define pthread_kill(A,B) pthread_dummy(0) #define pthread_condattr_init(A) pthread_dummy(0) #define pthread_condattr_destroy(A) pthread_dummy(0) -#define pthread_signal(A,B) pthread_dummy(0) #undef pthread_detach_this_thread #define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(tmp); } -#undef sigset -#define sigset(A,B) pthread_signal((A),(void (*)(int)) (B)) #endif #if ((defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT)) || defined(HAVE_DEC_3_2_THREADS)) && !defined(HAVE_CTHREADS_WRAPPER) diff --git a/include/my_sys.h b/include/my_sys.h index c46da655fa4..76031806b82 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -98,7 +98,6 @@ extern int NEAR my_errno; /* Last error in mysys */ #define MY_RETURN_REAL_PATH 32 /* return full path for file */ #define MY_SAFE_PATH 64 /* Return NULL if too long path */ #define MY_RELATIVE_PATH 128 /* name is relative to 'dir' */ -#define MY_UNIX_PATH 256 /* convert path to UNIX format */ /* My seek flags */ #define MY_SEEK_SET 0 @@ -159,7 +158,8 @@ extern gptr my_memdup(const byte *from,uint length,myf MyFlags); extern char *my_strdup(const char *from,myf MyFlags); extern char *my_strdup_with_length(const byte *from, uint length, myf MyFlags); -#define my_free(PTR,FG) my_no_flags_free(PTR) +/* we do use FG (as a no-op) in below so that a typo on FG is caught */ +#define my_free(PTR,FG) ((void)FG,my_no_flags_free(PTR)) #define CALLER_INFO_PROTO /* nothing */ #define CALLER_INFO /* nothing */ #define ORIG_CALLER_INFO /* nothing */ @@ -237,9 +237,6 @@ extern CHARSET_INFO *all_charsets[256]; extern CHARSET_INFO compiled_charsets[]; /* statistics */ -extern ulong my_cache_w_requests, my_cache_write, my_cache_r_requests, - my_cache_read; -extern ulong my_blocks_used, my_blocks_changed; extern ulong my_file_opened,my_stream_opened, my_tmp_file_created; extern uint mysys_usage_id; extern my_bool my_init_done; @@ -265,6 +262,7 @@ extern char wild_many,wild_one,wild_prefix; extern const char *charsets_dir; extern char *defaults_extra_file; extern const char *defaults_group_suffix; +extern const char *defaults_file; extern my_bool timed_mutexes; @@ -283,7 +281,7 @@ enum loglevel { enum cache_type { - READ_CACHE,WRITE_CACHE, + TYPE_NOT_SET= 0, READ_CACHE, WRITE_CACHE, SEQ_READ_APPEND /* sequential read or append */, READ_FIFO, READ_NET,WRITE_NET}; @@ -778,6 +776,7 @@ extern void my_free_lock(byte *ptr,myf flags); extern void init_alloc_root(MEM_ROOT *mem_root, uint block_size, uint pre_alloc_size); extern gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size); +extern gptr multi_alloc_root(MEM_ROOT *mem_root, ...); extern void free_root(MEM_ROOT *root, myf MyFLAGS); extern void set_prealloc_root(MEM_ROOT *root, char *ptr); extern void reset_root_defaults(MEM_ROOT *mem_root, uint block_size, @@ -890,6 +889,9 @@ int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror, void my_security_attr_free(SECURITY_ATTRIBUTES *sa); +/* implemented in my_conio.c */ +char* my_cgets(char *string, unsigned long clen, unsigned long* plen); + #endif #ifdef __NETWARE__ void netware_reg_user(const char *ip, const char *user, diff --git a/include/myisam.h b/include/myisam.h index 03194fe42ae..39cc61ad204 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -381,6 +381,20 @@ typedef struct st_sort_key_blocks /* Used when sorting */ } SORT_KEY_BLOCKS; +/* + MyISAM supports several statistics collection methods. Currently statistics + collection method is not stored in MyISAM file and has to be specified for + each table analyze/repair operation in MI_CHECK::stats_method. +*/ + +typedef enum +{ + /* Treat NULLs as inequal when collecting statistics (default for 4.1/5.0) */ + MI_STATS_METHOD_NULLS_NOT_EQUAL, + /* Treat NULLs as equal when collecting statistics (like 4.0 did) */ + MI_STATS_METHOD_NULLS_EQUAL +} enum_mi_stats_method; + typedef struct st_mi_check_param { ulonglong auto_increment_value; @@ -411,6 +425,7 @@ typedef struct st_mi_check_param void *thd; const char *db_name, *table_name; const char *op_name; + enum_mi_stats_method stats_method; } MI_CHECK; typedef struct st_sort_ft_buf diff --git a/include/mysql.h b/include/mysql.h index 2ba41e6d367..c4b4e026e5b 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -146,7 +146,7 @@ enum mysql_option MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT, MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION, MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, - MYSQL_REPORT_DATA_TRUNCATION + MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT }; struct st_mysql_options { diff --git a/include/mysql_com.h b/include/mysql_com.h index 969fba4a433..1e595cdbba3 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -409,6 +409,7 @@ my_bool check_scramble(const char *reply, const char *message, const unsigned char *hash_stage2); void get_salt_from_password(unsigned char *res, const char *password); void make_password_from_salt(char *to, const unsigned char *hash_stage2); +char *octet2hex(char *to, const char *str, unsigned int len); /* end of password.c */ diff --git a/include/violite.h b/include/violite.h index 48046346f8c..b48f3724f5b 100644 --- a/include/violite.h +++ b/include/violite.h @@ -74,6 +74,8 @@ int vio_fastsend(Vio *vio); int vio_keepalive(Vio *vio, my_bool onoff); /* Whenever we should retry the last read/write operation. */ my_bool vio_should_retry(Vio *vio); +/* Check that operation was timed out */ +my_bool vio_was_interrupted(Vio *vio); /* Short text description of the socket for those, who are curious.. */ const char* vio_description(Vio *vio); /* Return the type of the connection */ @@ -153,6 +155,7 @@ int vio_close_shared_memory(Vio * vio); #define vio_fastsend(vio) (vio)->fastsend(vio) #define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive) #define vio_should_retry(vio) (vio)->should_retry(vio) +#define vio_was_interrupted(vio) (vio)->was_interrupted(vio) #define vio_close(vio) ((vio)->vioclose)(vio) #define vio_peer_addr(vio, buf, prt) (vio)->peer_addr(vio, buf, prt) #define vio_in_addr(vio, in) (vio)->in_addr(vio, in) @@ -198,6 +201,7 @@ struct st_vio my_bool (*peer_addr)(Vio*, char *, uint16*); void (*in_addr)(Vio*, struct in_addr*); my_bool (*should_retry)(Vio*); + my_bool (*was_interrupted)(Vio*); int (*vioclose)(Vio*); void (*timeout)(Vio*, unsigned int which, unsigned int timeout); void *ssl_arg; diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index aa3aef7f97c..3a3b64dd51b 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -321,7 +321,9 @@ buf_page_is_corrupted( fprintf(stderr, " InnoDB: Error: page %lu log sequence number %lu %lu\n" "InnoDB: is in the future! Current system log sequence number %lu %lu.\n" -"InnoDB: Your database may be corrupt.\n", +"InnoDB: Your database may be corrupt or you may have copied the InnoDB\n" +"InnoDB: tablespace but not the InnoDB log files. See\n" +"http://dev.mysql.com/doc/mysql/en/backing-up.html for more information.\n", (ulong) mach_read_from_4(read_buf + FIL_PAGE_OFFSET), (ulong) ut_dulint_get_high( mach_read_from_8(read_buf + FIL_PAGE_LSN)), diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index ffb16790b2d..e39d1ae0a71 100644 --- a/innobase/buf/buf0flu.c +++ b/innobase/buf/buf0flu.c @@ -230,7 +230,7 @@ buf_flush_buffered_writes(void) ulint len2; ulint i; - if (trx_doublewrite == NULL) { + if (!srv_use_doublewrite_buf || trx_doublewrite == NULL) { os_aio_simulated_wake_handler_threads(); return; @@ -503,7 +503,7 @@ buf_flush_write_block_low( #endif buf_flush_init_for_writing(block->frame, block->newest_modification, block->space, block->offset); - if (!trx_doublewrite) { + if (!srv_use_doublewrite_buf || !trx_doublewrite) { fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, (void*)block->frame, (void*)block); diff --git a/innobase/data/data0data.c b/innobase/data/data0data.c index 194213a04e1..19304a7a8e1 100644 --- a/innobase/data/data0data.c +++ b/innobase/data/data0data.c @@ -561,12 +561,12 @@ dtuple_convert_big_rec( } /* We do not store externally fields which are smaller than - DICT_MAX_COL_PREFIX_LEN */ + DICT_MAX_INDEX_COL_LEN */ - ut_a(DICT_MAX_COL_PREFIX_LEN > REC_1BYTE_OFFS_LIMIT); + ut_a(DICT_MAX_INDEX_COL_LEN > REC_1BYTE_OFFS_LIMIT); if (longest < BTR_EXTERN_FIELD_REF_SIZE + 10 - + DICT_MAX_COL_PREFIX_LEN) { + + DICT_MAX_INDEX_COL_LEN) { /* Cannot shorten more */ mem_heap_free(heap); @@ -588,10 +588,10 @@ dtuple_convert_big_rec( dfield = dtuple_get_nth_field(entry, longest_i); vector->fields[n_fields].field_no = longest_i; - ut_a(dfield->len > DICT_MAX_COL_PREFIX_LEN); + ut_a(dfield->len > DICT_MAX_INDEX_COL_LEN); vector->fields[n_fields].len = dfield->len - - DICT_MAX_COL_PREFIX_LEN; + - DICT_MAX_INDEX_COL_LEN; vector->fields[n_fields].data = mem_heap_alloc(heap, vector->fields[n_fields].len); diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 9580a80e7e7..fb95ffbd80c 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -1625,7 +1625,7 @@ dict_index_add_col( variable-length fields, so that the extern flag can be embedded in the length word. */ - if (field->fixed_len > DICT_MAX_COL_PREFIX_LEN) { + if (field->fixed_len > DICT_MAX_INDEX_COL_LEN) { field->fixed_len = 0; } @@ -2189,7 +2189,7 @@ dict_foreign_error_report( dict_foreign_error_report_low(file, fk->foreign_table_name); fputs(msg, file); fputs(" Constraint:\n", file); - dict_print_info_on_foreign_key_in_create_format(file, NULL, fk); + dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE); if (fk->foreign_index) { fputs("\nThe index in the foreign key in table is ", file); ut_print_name(file, NULL, fk->foreign_index->name); @@ -2871,8 +2871,12 @@ dict_create_foreign_constraints_low( table2 can be written also with the database name before it: test.table2; the default database is the database of parameter name */ - const char* name) /* in: table full name in the normalized form + const char* name, /* in: table full name in the normalized form database_name/table_name */ + ibool reject_fks) + /* in: if TRUE, fail with error code + DB_CANNOT_ADD_CONSTRAINT if any foreign + keys are found. */ { dict_table_t* table; dict_table_t* referenced_table; @@ -2994,6 +2998,18 @@ loop: } if (*ptr == '\0') { + /* The proper way to reject foreign keys for temporary + tables would be to split the lexing and syntactical + analysis of foreign key clauses from the actual adding + of them, so that ha_innodb.cc could first parse the SQL + command, determine if there are any foreign keys, and + if so, immediately reject the command if the table is a + temporary one. For now, this kludge will work. */ + if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) + { + return DB_CANNOT_ADD_CONSTRAINT; + } + /**********************************************************/ /* The following call adds the foreign key constraints to the data dictionary system tables on disk */ @@ -3417,9 +3433,12 @@ dict_create_foreign_constraints( name before it: test.table2; the default database id the database of parameter name */ - const char* name) /* in: table full name in the + const char* name, /* in: table full name in the normalized form database_name/table_name */ + ibool reject_fks) /* in: if TRUE, fail with error + code DB_CANNOT_ADD_CONSTRAINT if + any foreign keys are found. */ { char* str; ulint err; @@ -3428,7 +3447,8 @@ dict_create_foreign_constraints( str = dict_strip_comments(sql_string); heap = mem_heap_create(10000); - err = dict_create_foreign_constraints_low(trx, heap, str, name); + err = dict_create_foreign_constraints_low(trx, heap, str, name, + reject_fks); mem_heap_free(heap); mem_free(str); @@ -4310,9 +4330,10 @@ CREATE TABLE. */ void dict_print_info_on_foreign_key_in_create_format( /*============================================*/ - FILE* file, /* in: file where to print */ - trx_t* trx, /* in: transaction */ - dict_foreign_t* foreign)/* in: foreign key constraint */ + FILE* file, /* in: file where to print */ + trx_t* trx, /* in: transaction */ + dict_foreign_t* foreign, /* in: foreign key constraint */ + ibool add_newline) /* in: whether to add a newline */ { const char* stripped_id; ulint i; @@ -4325,7 +4346,16 @@ dict_print_info_on_foreign_key_in_create_format( stripped_id = foreign->id; } - fputs(",\n CONSTRAINT ", file); + putc(',', file); + + if (add_newline) { + /* SHOW CREATE TABLE wants constraints each printed nicely + on its own line, while error messages want no newlines + inserted. */ + fputs("\n ", file); + } + + fputs(" CONSTRAINT ", file); ut_print_name(file, trx, stripped_id); fputs(" FOREIGN KEY (", file); @@ -4427,7 +4457,7 @@ dict_print_info_on_foreign_keys( while (foreign != NULL) { if (create_table_format) { dict_print_info_on_foreign_key_in_create_format( - file, trx, foreign); + file, trx, foreign, TRUE); } else { ulint i; fputs("; (", file); diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h index 1f3a32fa70c..d28b0b129a1 100644 --- a/innobase/include/btr0btr.h +++ b/innobase/include/btr0btr.h @@ -23,16 +23,6 @@ special big record storage structure */ #define BTR_PAGE_MAX_REC_SIZE (UNIV_PAGE_SIZE / 2 - 200) -/* Maximum key size in a B-tree: the records on non-leaf levels must be -shorter than this */ - -#define BTR_PAGE_MAX_KEY_SIZE 1024 - -/* If data in page drops below this limit, we try to compress it. -NOTE! The value has to be > 2 * BTR_MAX_KEY_SIZE */ - -#define BTR_COMPRESS_LIMIT (UNIV_PAGE_SIZE / 4 + 1); - /* Latching modes for the search function (in btr0cur.*) */ #define BTR_SEARCH_LEAF RW_S_LATCH #define BTR_MODIFY_LEAF RW_X_LATCH diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic index 06d45dd5501..d4a7b3c64b8 100644 --- a/innobase/include/data0type.ic +++ b/innobase/include/data0type.ic @@ -420,7 +420,7 @@ dtype_get_fixed_size( } /*************************************************************************** -Returns the size of a fixed size data type, 0 if not a fixed size type. */ +Returns the minimum size of a data type. */ UNIV_INLINE ulint dtype_get_min_size( diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h index d9cda402bac..5215d51cabe 100644 --- a/innobase/include/dict0dict.h +++ b/innobase/include/dict0dict.h @@ -228,9 +228,12 @@ dict_create_foreign_constraints( name before it: test.table2; the default database id the database of parameter name */ - const char* name); /* in: table full name in the + const char* name, /* in: table full name in the normalized form database_name/table_name */ + ibool reject_fks); /* in: if TRUE, fail with error + code DB_CANNOT_ADD_CONSTRAINT if + any foreign keys are found. */ /************************************************************************** Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */ @@ -372,9 +375,10 @@ CREATE TABLE. */ void dict_print_info_on_foreign_key_in_create_format( /*============================================*/ - FILE* file, /* in: file where to print */ - trx_t* trx, /* in: transaction */ - dict_foreign_t* foreign);/* in: foreign key constraint */ + FILE* file, /* in: file where to print */ + trx_t* trx, /* in: transaction */ + dict_foreign_t* foreign, /* in: foreign key constraint */ + ibool add_newline); /* in: whether to add a newline */ /************************************************************************ Displays the names of the index and the table. */ void diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h index ff6c4ec9b28..7eec86d0bcb 100644 --- a/innobase/include/dict0mem.h +++ b/innobase/include/dict0mem.h @@ -152,12 +152,12 @@ struct dict_col_struct{ in some of the functions below */ }; -/* DICT_MAX_COL_PREFIX_LEN is measured in bytes. Starting from 4.1.6, we -set max col prefix len to < 3 * 256, so that one can create a column prefix -index on 255 characters of a TEXT field also in the UTF-8 charset. In that -charset, a character may take at most 3 bytes. */ +/* DICT_MAX_INDEX_COL_LEN is measured in bytes and is the max index column +length + 1. Starting from 4.1.6, we set it to < 3 * 256, so that one can +create a column prefix index on 255 characters of a TEXT field also in the +UTF-8 charset. In that charset, a character may take at most 3 bytes. */ -#define DICT_MAX_COL_PREFIX_LEN 768 +#define DICT_MAX_INDEX_COL_LEN 768 /* Data structure for a field in an index */ struct dict_field_struct{ @@ -169,12 +169,12 @@ struct dict_field_struct{ prefix in bytes in a MySQL index of type, e.g., INDEX (textcol(25)); must be smaller than - DICT_MAX_COL_PREFIX_LEN; NOTE that + DICT_MAX_INDEX_COL_LEN; NOTE that in the UTF-8 charset, MySQL sets this to 3 * the prefix len in UTF-8 chars */ ulint fixed_len; /* 0 or the fixed length of the column if smaller than - DICT_MAX_COL_PREFIX_LEN */ + DICT_MAX_INDEX_COL_LEN */ ulint fixed_offs; /* offset to the field, or ULINT_UNDEFINED if it is not fixed within the record (due to preceding diff --git a/innobase/include/mem0mem.h b/innobase/include/mem0mem.h index 87afdb8f91c..3768e93c03e 100644 --- a/innobase/include/mem0mem.h +++ b/innobase/include/mem0mem.h @@ -99,8 +99,7 @@ heap freeing. */ /********************************************************************* NOTE: Use the corresponding macros instead of this function. Creates a memory heap which allocates memory from dynamic space. For debugging -purposes, takes also the file name and line as argument in the debug -version. */ +purposes, takes also the file name and line as argument. */ UNIV_INLINE mem_heap_t* mem_heap_create_func( diff --git a/innobase/include/mem0mem.ic b/innobase/include/mem0mem.ic index 8c87c884d78..28562f7c9f8 100644 --- a/innobase/include/mem0mem.ic +++ b/innobase/include/mem0mem.ic @@ -371,8 +371,7 @@ mem_heap_free_top( /********************************************************************* NOTE: Use the corresponding macros instead of this function. Creates a memory heap which allocates memory from dynamic space. For debugging -purposes, takes also the file name and line as argument in the debug -version. */ +purposes, takes also the file name and line as argument. */ UNIV_INLINE mem_heap_t* mem_heap_create_func( diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index adbc4afafd2..224fd59a76b 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -432,6 +432,17 @@ os_file_read( offset */ ulint n); /* in: number of bytes to read */ /*********************************************************************** +Rewind file to its start, read at most size - 1 bytes from it to str, and +NUL-terminate str. All errors are silently ignored. This function is +mostly meant to be used with temporary files. */ + +void +os_file_read_string( +/*================*/ + FILE* file, /* in: file to read from */ + char* str, /* in: buffer where to read */ + ulint size); /* in: size of buffer */ +/*********************************************************************** Requests a synchronous positioned read operation. This function does not do any error handling. In case of error it returns FALSE. */ diff --git a/innobase/include/page0page.ic b/innobase/include/page0page.ic index fd5281fdbec..655ff245aa8 100644 --- a/innobase/include/page0page.ic +++ b/innobase/include/page0page.ic @@ -175,6 +175,19 @@ page_rec_is_comp( /* out: nonzero if in compact format */ const rec_t* rec) /* in: record */ { +#ifdef UNIV_RELEASE_NOT_YET_STABLE + if (UNIV_UNLIKELY((ulint)rec < (ulint)(buf_pool->frame_zero)) + || UNIV_UNLIKELY((ulint)rec >= (ulint)(buf_pool->high_end))) { + + ut_print_timestamp(stderr); + fprintf(stderr, +"InnoDB: Error: trying to read a stray page rec %p\n" +"InnoDB: buf pool start is at %p, end at %p\n", + rec, buf_pool->frame_zero, + buf_pool->high_end); + ut_error; + } +#endif return(page_is_comp(ut_align_down((rec_t*) rec, UNIV_PAGE_SIZE))); } diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h index 1d15b8d1c77..69b397c9682 100644 --- a/innobase/include/rem0rec.h +++ b/innobase/include/rem0rec.h @@ -312,6 +312,15 @@ rec_offs_nth_extern( const ulint* offsets,/* in: array returned by rec_get_offsets() */ ulint n); /* in: nth field */ /********************************************************** +Returns nonzero if the SQL NULL bit is set in nth field of rec. */ +UNIV_INLINE +ulint +rec_offs_nth_sql_null( +/*==================*/ + /* out: nonzero if SQL NULL */ + const ulint* offsets,/* in: array returned by rec_get_offsets() */ + ulint n); /* in: nth field */ +/********************************************************** Gets the physical size of a field. */ UNIV_INLINE ulint diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index e2dceb6bae5..9c24f385f4f 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -954,6 +954,22 @@ rec_offs_nth_extern( & REC_OFFS_EXTERNAL)); } +/********************************************************** +Returns nonzero if the SQL NULL bit is set in nth field of rec. */ +UNIV_INLINE +ulint +rec_offs_nth_sql_null( +/*==================*/ + /* out: nonzero if SQL NULL */ + const ulint* offsets,/* in: array returned by rec_get_offsets() */ + ulint n) /* in: nth field */ +{ + ut_ad(rec_offs_validate(NULL, NULL, offsets)); + ut_ad(n < rec_offs_n_fields(offsets)); + return(UNIV_UNLIKELY(rec_offs_base(offsets)[1 + n] + & REC_OFFS_SQL_NULL)); +} + /********************************************************** Gets the physical size of a field. */ UNIV_INLINE diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 4e6ff73b0f8..b5da4634d98 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -335,8 +335,14 @@ int row_create_index_for_mysql( /*=======================*/ /* out: error number or DB_SUCCESS */ - dict_index_t* index, /* in: index defintion */ - trx_t* trx); /* in: transaction handle */ + dict_index_t* index, /* in: index definition */ + trx_t* trx, /* in: transaction handle */ + const ulint* field_lengths); /* in: if not NULL, must contain + dict_index_get_n_fields(index) + actual field lengths for the + index columns, which are + then checked for not being too + large. */ /************************************************************************* Scans a table create SQL string and adds to the data dictionary the foreign key constraints declared in the string. This function @@ -355,9 +361,13 @@ row_table_add_foreign_constraints( FOREIGN KEY (a, b) REFERENCES table2(c, d), table2 can be written also with the database name before it: test.table2 */ - const char* name); /* in: table full name in the + const char* name, /* in: table full name in the normalized form database_name/table_name */ + ibool reject_fks); /* in: if TRUE, fail with error + code DB_CANNOT_ADD_CONSTRAINT if + any foreign keys are found. */ + /************************************************************************* The master thread in srv0srv.c calls this regularly to drop tables which we must drop in background after queries to them have ended. Such lazy diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 5dbf003594f..0dc82893ad1 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -56,6 +56,22 @@ void trx_search_latch_release_if_reserved( /*=================================*/ trx_t* trx); /* in: transaction */ +/********************************************************************** +Set detailed error message for the transaction. */ +void +trx_set_detailed_error( +/*===================*/ + trx_t* trx, /* in: transaction struct */ + const char* msg); /* in: detailed error message */ +/***************************************************************** +Set detailed error message for the transaction from a file. Note that the +file is rewinded before reading from it. */ + +void +trx_set_detailed_error_from_file( +/*=============================*/ + trx_t* trx, /* in: transaction struct */ + FILE* file); /* in: file to read message from */ /******************************************************************** Retrieves the error_info field from a trx. */ @@ -205,7 +221,7 @@ trx_recover_for_mysql( XID* xid_list, /* in/out: prepared transactions */ ulint len); /* in: number of slots in xid_list */ /*********************************************************************** -This function is used to commit one X/Open XA distributed transaction +This function is used to find one X/Open XA distributed transaction which is in the prepared state */ trx_t * trx_get_trx_by_xid( @@ -649,6 +665,9 @@ struct trx_struct{ trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log records which are currently processed by a rollback operation */ + /*------------------------------*/ + char detailed_error[256]; /* detailed error message for last + error, or empty. */ }; #define TRX_MAX_N_THREADS 32 /* maximum number of concurrent diff --git a/innobase/include/univ.i b/innobase/include/univ.i index 6849dcd9c51..15650f22ed8 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -80,6 +80,10 @@ memory is read outside the allocated blocks. */ /* Make a non-inline debug version */ +/* You can remove this define when the release is stable. This define adds +some consistency checks to code. They use a little CPU time. */ +#define UNIV_RELEASE_NOT_YET_STABLE + /* #define UNIV_DEBUG #define UNIV_MEM_DEBUG diff --git a/innobase/include/ut0mem.h b/innobase/include/ut0mem.h index 74357f6bf13..b9bbe0b5c92 100644 --- a/innobase/include/ut0mem.h +++ b/innobase/include/ut0mem.h @@ -118,6 +118,31 @@ UNIV_INLINE int ut_strcmp(const void* str1, const void* str2); +/************************************************************************** +Copies up to size - 1 characters from the NUL-terminated string src to +dst, NUL-terminating the result. Returns strlen(src), so truncation +occurred if the return value >= size. */ + +ulint +ut_strlcpy( +/*=======*/ + /* out: strlen(src) */ + char* dst, /* in: destination buffer */ + const char* src, /* in: source buffer */ + ulint size); /* in: size of destination buffer */ + +/************************************************************************** +Like ut_strlcpy, but if src doesn't fit in dst completely, copies the last +(size - 1) bytes of src, not the first. */ + +ulint +ut_strlcpy_rev( +/*===========*/ + /* out: strlen(src) */ + char* dst, /* in: destination buffer */ + const char* src, /* in: source buffer */ + ulint size); /* in: size of destination buffer */ + /************************************************************************** Compute strlen(ut_strcpyq(str, q)). */ UNIV_INLINE diff --git a/innobase/mem/mem0mem.c b/innobase/mem/mem0mem.c index 85f0119d02a..daf78008d45 100644 --- a/innobase/mem/mem0mem.c +++ b/innobase/mem/mem0mem.c @@ -187,9 +187,7 @@ mem_heap_create_block( } block->magic_n = MEM_BLOCK_MAGIC_N; - ut_memcpy(&(block->file_name), file_name + ut_strlen(file_name) - 7, - 7); - block->file_name[7]='\0'; + ut_strlcpy_rev(block->file_name, file_name, sizeof(block->file_name)); block->line = line; #ifdef MEM_PERIODIC_CHECK diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 9c87b59f018..20a3303d12d 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -2248,6 +2248,29 @@ error_handling: return(FALSE); } +/*********************************************************************** +Rewind file to its start, read at most size - 1 bytes from it to str, and +NUL-terminate str. All errors are silently ignored. This function is +mostly meant to be used with temporary files. */ + +void +os_file_read_string( +/*================*/ + FILE* file, /* in: file to read from */ + char* str, /* in: buffer where to read */ + ulint size) /* in: size of buffer */ +{ + size_t flen; + + if (size == 0) { + return; + } + + rewind(file); + flen = fread(str, 1, size - 1, file); + str[flen] = '\0'; +} + /*********************************************************************** Requests a synchronous write operation. */ diff --git a/innobase/os/os0proc.c b/innobase/os/os0proc.c index 167aed93de7..24bb007e504 100644 --- a/innobase/os/os0proc.c +++ b/innobase/os/os0proc.c @@ -292,6 +292,9 @@ os_awe_allocate_physical_mem( return(TRUE); #else + UT_NOT_USED(n_megabytes); + UT_NOT_USED(page_info); + return(FALSE); #endif } @@ -349,6 +352,8 @@ os_awe_allocate_virtual_mem_window( return(ptr); #else + UT_NOT_USED(size); + return(NULL); #endif } @@ -476,6 +481,10 @@ os_awe_map_physical_mem_to_window( return(TRUE); #else + UT_NOT_USED(ptr); + UT_NOT_USED(n_mem_pages); + UT_NOT_USED(page_info); + return(FALSE); #endif } diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index 356d7c8c163..487e8f40a39 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -631,7 +631,21 @@ os_fast_mutex_free( DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); #else - ut_a(0 == pthread_mutex_destroy(fast_mutex)); + int ret; + + ret = pthread_mutex_destroy(fast_mutex); + + if (ret != 0) { + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: error: return value %lu when calling\n" +"InnoDB: pthread_mutex_destroy().\n", (ulint)ret); + fprintf(stderr, +"InnoDB: Byte contents of the pthread mutex at %p:\n", fast_mutex); + ut_print_buf(stderr, (const byte*)fast_mutex, + sizeof(os_fast_mutex_t)); + fprintf(stderr, "\n"); + } #endif if (os_sync_mutex_inited) { /* When freeing the last mutexes, we have diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c index fbc33aea669..9480c978755 100644 --- a/innobase/rem/rem0rec.c +++ b/innobase/rem/rem0rec.c @@ -621,7 +621,7 @@ rec_set_nth_field_extern_bit_new( if (field->fixed_len) { /* fixed-length fields cannot be external (Fixed-length fields longer than - DICT_MAX_COL_PREFIX_LEN will be treated as + DICT_MAX_INDEX_COL_LEN will be treated as variable-length ones in dict_index_add_col().) */ ut_ad(i != ith); continue; diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 75d8117a73e..5e833372299 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -578,6 +578,32 @@ row_ins_cascade_calc_update_vec( return(n_fields_updated); } +/************************************************************************* +Set detailed error message associated with foreign key errors for +the given transaction. */ +static +void +row_ins_set_detailed( +/*=================*/ + trx_t* trx, /* in: transaction */ + dict_foreign_t* foreign) /* in: foreign key constraint */ +{ + + FILE* tf = os_file_create_tmpfile(); + + if (tf) { + ut_print_name(tf, trx, foreign->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format(tf, trx, + foreign, FALSE); + + trx_set_detailed_error_from_file(trx, tf); + + fclose(tf); + } else { + trx_set_detailed_error(trx, "temp file creation failed"); + } +} + /************************************************************************* Reports a foreign key error associated with an update or a delete of a parent table index entry. */ @@ -598,6 +624,8 @@ row_ins_foreign_report_err( FILE* ef = dict_foreign_err_file; trx_t* trx = thr_get_trx(thr); + row_ins_set_detailed(trx, foreign); + mutex_enter(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); @@ -607,7 +635,8 @@ row_ins_foreign_report_err( fputs("Foreign key constraint fails for table ", ef); ut_print_name(ef, trx, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign); + dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, + TRUE); putc('\n', ef); fputs(errstr, ef); fputs(" in parent table, in index ", ef); @@ -648,7 +677,9 @@ row_ins_foreign_report_add_err( child table */ { FILE* ef = dict_foreign_err_file; - + + row_ins_set_detailed(trx, foreign); + mutex_enter(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); @@ -657,7 +688,8 @@ row_ins_foreign_report_add_err( fputs("Foreign key constraint fails for table ", ef); ut_print_name(ef, trx, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign); + dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, + TRUE); fputs("\nTrying to add in child table, in index ", ef); ut_print_name(ef, trx, foreign->foreign_index->name); if (entry) { @@ -1224,6 +1256,9 @@ run_again: if (check_table == NULL || check_table->ibd_file_missing) { if (check_ref) { FILE* ef = dict_foreign_err_file; + + row_ins_set_detailed(trx, foreign); + mutex_enter(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); @@ -1233,7 +1268,7 @@ run_again: ut_print_name(ef, trx, foreign->foreign_table_name); fputs(":\n", ef); dict_print_info_on_foreign_key_in_create_format(ef, - trx, foreign); + trx, foreign, TRUE); fputs("\nTrying to add to index ", ef); ut_print_name(ef, trx, foreign->foreign_index->name); fputs(" tuple:\n", ef); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 2ac0824b331..82f7daf2ed8 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -513,14 +513,15 @@ handle_new_error: return(TRUE); - } else if (err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT + } else if (err == DB_DEADLOCK || err == DB_LOCK_TABLE_FULL) { /* Roll back the whole transaction; this resolution was added to version 3.23.43 */ trx_general_rollback_for_mysql(trx, FALSE, NULL); - } else if (err == DB_OUT_OF_FILE_SPACE) { + } else if (err == DB_OUT_OF_FILE_SPACE + || err == DB_LOCK_WAIT_TIMEOUT) { if (savept) { /* Roll back the latest, possibly incomplete insertion or update */ @@ -1972,13 +1973,20 @@ row_create_index_for_mysql( /*=======================*/ /* out: error number or DB_SUCCESS */ dict_index_t* index, /* in: index definition */ - trx_t* trx) /* in: transaction handle */ + trx_t* trx, /* in: transaction handle */ + const ulint* field_lengths) /* in: if not NULL, must contain + dict_index_get_n_fields(index) + actual field lengths for the + index columns, which are + then checked for not being too + large. */ { ind_node_t* node; mem_heap_t* heap; que_thr_t* thr; ulint err; ulint i, j; + ulint len; #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); @@ -2017,10 +2025,16 @@ row_create_index_for_mysql( } } - /* Check also that prefix_len < DICT_MAX_COL_PREFIX_LEN */ + /* Check also that prefix_len and actual length + < DICT_MAX_INDEX_COL_LEN */ - if (dict_index_get_nth_field(index, i)->prefix_len - >= DICT_MAX_COL_PREFIX_LEN) { + len = dict_index_get_nth_field(index, i)->prefix_len; + + if (field_lengths) { + len = ut_max(len, field_lengths[i]); + } + + if (len >= DICT_MAX_INDEX_COL_LEN) { err = DB_TOO_BIG_RECORD; goto error_handling; @@ -2087,9 +2101,12 @@ row_table_add_foreign_constraints( FOREIGN KEY (a, b) REFERENCES table2(c, d), table2 can be written also with the database name before it: test.table2 */ - const char* name) /* in: table full name in the + const char* name, /* in: table full name in the normalized form database_name/table_name */ + ibool reject_fks) /* in: if TRUE, fail with error + code DB_CANNOT_ADD_CONSTRAINT if + any foreign keys are found. */ { ulint err; @@ -2110,7 +2127,8 @@ row_table_add_foreign_constraints( trx->dict_operation = TRUE; - err = dict_create_foreign_constraints(trx, sql_string, name); + err = dict_create_foreign_constraints(trx, sql_string, name, + reject_fks); if (err == DB_SUCCESS) { /* Check that also referencing constraints are ok */ diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index a77010d939b..1b66f14f5d7 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2724,7 +2724,9 @@ row_sel_get_clust_rec_for_mysql( if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED && !lock_clust_rec_cons_read_sees(clust_rec, clust_index, *offsets, trx->read_view)) { - + + /* The following call returns 'offsets' associated with + 'old_vers' */ err = row_sel_build_prev_vers_for_mysql( trx->read_view, clust_index, prebuilt, clust_rec, @@ -3055,13 +3057,14 @@ row_search_for_mysql( cursor 'direction' should be 0. */ { dict_index_t* index = prebuilt->index; + ibool comp = index->table->comp; dtuple_t* search_tuple = prebuilt->search_tuple; btr_pcur_t* pcur = prebuilt->pcur; trx_t* trx = prebuilt->trx; dict_index_t* clust_index; que_thr_t* thr; rec_t* rec; - rec_t* index_rec; + rec_t* result_rec; rec_t* clust_rec; rec_t* old_vers; ulint err = DB_SUCCESS; @@ -3491,7 +3494,7 @@ rec_loop: /* PHASE 4: Look for matching records in a loop */ rec = btr_pcur_get_rec(pcur); - ut_ad(!!page_rec_is_comp(rec) == index->table->comp); + ut_ad(!!page_rec_is_comp(rec) == comp); #ifdef UNIV_SEARCH_DEBUG /* fputs("Using ", stderr); @@ -3544,19 +3547,23 @@ rec_loop: /* Do sanity checks in case our cursor has bumped into page corruption */ - if (page_rec_is_comp(rec)) { + if (comp) { next_offs = rec_get_next_offs(rec, TRUE); if (UNIV_UNLIKELY(next_offs < PAGE_NEW_SUPREMUM)) { + goto wrong_offs; } } else { next_offs = rec_get_next_offs(rec, FALSE); if (UNIV_UNLIKELY(next_offs < PAGE_OLD_SUPREMUM)) { + goto wrong_offs; } } + if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) { - wrong_offs: + +wrong_offs: if (srv_force_recovery == 0 || moves_up == FALSE) { ut_print_timestamp(stderr); buf_page_print(buf_frame_align(rec)); @@ -3599,6 +3606,9 @@ rec_loop: goto next_rec; } } + /*-------------------------------------------------------------*/ + + /* Calculate the 'offsets' associated with 'rec' */ offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); @@ -3619,8 +3629,6 @@ rec_loop: } } - /*-------------------------------------------------------------*/ - /* Note that we cannot trust the up_match value in the cursor at this place because we can arrive here after moving the cursor! Thus we have to recompare rec and search_tuple to determine if they @@ -3711,7 +3719,7 @@ rec_loop: if (!set_also_gap_locks || srv_locks_unsafe_for_binlog || (unique_search && !UNIV_UNLIKELY(rec_get_deleted_flag( - rec, page_rec_is_comp(rec))))) { + rec, comp)))) { goto no_gap_lock; } else { @@ -3767,6 +3775,8 @@ no_gap_lock: && !lock_clust_rec_cons_read_sees(rec, index, offsets, trx->read_view)) { + /* The following call returns 'offsets' + associated with 'old_vers' */ err = row_sel_build_prev_vers_for_mysql( trx->read_view, clust_index, prebuilt, rec, @@ -3795,19 +3805,20 @@ no_gap_lock: is necessary, because we can only get the undo information via the clustered index record. */ - /* Get the clustered index record if needed */ - index_rec = rec; ut_ad(index != clust_index); goto requires_clust_rec; } } - if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, page_rec_is_comp(rec)))) { + /* NOTE that at this point rec can be an old version of a clustered + index record built for a consistent read. We cannot assume after this + point that rec is on a buffer pool page. Functions like + page_rec_is_comp() cannot be used! */ - /* The record is delete-marked: we can skip it if this is - not a consistent read which might see an earlier version - of a non-clustered index record */ + if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, comp))) { + + /* The record is delete-marked: we can skip it */ if (srv_locks_unsafe_for_binlog && prebuilt->select_lock_type != LOCK_NONE) { @@ -3823,25 +3834,26 @@ no_gap_lock: goto next_rec; } - /* Get the clustered index record if needed and if we did - not do the search using the clustered index */ - - index_rec = rec; + /* Get the clustered index record if needed, if we did not do the + search using the clustered index. */ if (index != clust_index && prebuilt->need_to_access_clustered) { requires_clust_rec: - /* Before and after this "if" block, "offsets" will be - related to "rec", which may be in a secondary index "index" or - the clustered index ("clust_index"). However, after this - "if" block, "rec" may be pointing to - "clust_rec" of "clust_index". */ + /* We use a 'goto' to the preceding label if a consistent + read of a secondary index record requires us to look up old + versions of the associated clustered index record. */ + ut_ad(rec_offs_validate(rec, index, offsets)); /* It was a non-clustered index and we must fetch also the clustered index record */ mtr_has_extra_clust_latch = TRUE; + + /* The following call returns 'offsets' associated with + 'clust_rec'. Note that 'clust_rec' can be an old version + built for a consistent read. */ err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec, thr, &clust_rec, @@ -3858,8 +3870,7 @@ requires_clust_rec: goto next_rec; } - if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, - page_rec_is_comp(clust_rec)))) { + if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) { /* The record is delete marked: we can skip it */ @@ -3879,17 +3890,27 @@ requires_clust_rec: } if (prebuilt->need_to_access_clustered) { - rec = clust_rec; - ut_ad(rec_offs_validate(rec, clust_index, offsets)); + + result_rec = clust_rec; + + ut_ad(rec_offs_validate(result_rec, clust_index, + offsets)); } else { + /* We used 'offsets' for the clust rec, recalculate + them for 'rec' */ offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); + result_rec = rec; } + } else { + result_rec = rec; } - /* We found a qualifying row */ - ut_ad(rec_offs_validate(rec, - rec == clust_rec ? clust_index : index, + /* We found a qualifying record 'result_rec'. At this point, + 'offsets' are associated with 'result_rec'. */ + + ut_ad(rec_offs_validate(result_rec, + result_rec != rec ? clust_index : index, offsets)); if ((match_mode == ROW_SEL_EXACT @@ -3910,8 +3931,8 @@ requires_clust_rec: not cache rows because there the cursor is a scrollable cursor. */ - row_sel_push_cache_row_for_mysql(prebuilt, rec, offsets); - + row_sel_push_cache_row_for_mysql(prebuilt, result_rec, + offsets); if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) { goto got_row; @@ -3920,13 +3941,14 @@ requires_clust_rec: goto next_rec; } else { if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) { - memcpy(buf + 4, rec - rec_offs_extra_size(offsets), + memcpy(buf + 4, result_rec + - rec_offs_extra_size(offsets), rec_offs_size(offsets)); mach_write_to_4(buf, rec_offs_extra_size(offsets) + 4); } else { if (!row_sel_store_mysql_rec(buf, prebuilt, - rec, offsets)) { + result_rec, offsets)) { err = DB_TOO_BIG_RECORD; goto lock_wait_or_error; @@ -3934,15 +3956,18 @@ requires_clust_rec: } if (prebuilt->clust_index_was_generated) { - if (rec != index_rec) { + if (result_rec != rec) { offsets = rec_get_offsets( - index_rec, index, offsets, + rec, index, offsets, ULINT_UNDEFINED, &heap); } - row_sel_store_row_id_to_prebuilt(prebuilt, index_rec, + row_sel_store_row_id_to_prebuilt(prebuilt, rec, index, offsets); } } + + /* From this point on, 'offsets' are invalid. */ + got_row: /* We have an optimization to save CPU time: if this is a consistent read on a unique condition on the clustered index, then we do not @@ -3993,7 +4018,7 @@ next_rec: if (moves_up) { if (UNIV_UNLIKELY(!btr_pcur_move_to_next(pcur, &mtr))) { - not_moved: +not_moved: btr_pcur_store_position(pcur, &mtr); if (match_mode != 0) { diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c index 4f44dbeae67..ff1ad1dfd05 100644 --- a/innobase/row/row0upd.c +++ b/innobase/row/row0upd.c @@ -395,6 +395,18 @@ row_upd_changes_field_size_or_external( old_len = rec_offs_nth_size(offsets, upd_field->field_no); + if (rec_offs_comp(offsets) + && rec_offs_nth_sql_null(offsets, upd_field->field_no)) { + /* Note that in the compact table format, for a + variable length field, an SQL NULL will use zero + bytes in the offset array at the start of the physical + record, but a zero-length value (empty string) will + use one byte! Thus, we cannot use update-in-place + if we update an SQL NULL varchar to an empty string! */ + + old_len = UNIV_SQL_NULL; + } + if (old_len != new_len) { return(TRUE); diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 325b0a109cf..e5151ebf631 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1540,7 +1540,7 @@ NetWare. */ #endif sync_order_checks_on = TRUE; - if (srv_use_doublewrite_buf && trx_doublewrite == NULL) { + if (trx_doublewrite == NULL) { /* Create the doublewrite buffer to a new tablespace */ trx_sys_create_doublewrite_buf(); diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c index bf48c30e942..23f1dc40d00 100644 --- a/innobase/trx/trx0sys.c +++ b/innobase/trx/trx0sys.c @@ -125,22 +125,6 @@ trx_doublewrite_init( * sizeof(void*)); } -/******************************************************************** -Frees the doublewrite buffer. */ -static -void -trx_doublewrite_free(void) -/*======================*/ -{ - mutex_free(&(trx_doublewrite->mutex)); - - mem_free(trx_doublewrite->buf_block_arr); - ut_free(trx_doublewrite->write_buf_unaligned); - - mem_free(trx_doublewrite); - trx_doublewrite = NULL; -} - /******************************************************************** Marks the trx sys header when we have successfully upgraded to the >= 4.1.x multiple tablespace format. */ @@ -529,9 +513,6 @@ trx_sys_doublewrite_init_or_restore_pages( fil_flush_file_spaces(FIL_TABLESPACE); - if (!srv_use_doublewrite_buf) - trx_doublewrite_free(); - leave_func: ut_free(unaligned_read_buf); } diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 078befb81d2..090057f5d46 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -52,6 +52,32 @@ trx_start_if_not_started_noninline( trx_start_if_not_started(trx); } +/***************************************************************** +Set detailed error message for the transaction. */ + +void +trx_set_detailed_error( +/*===================*/ + trx_t* trx, /* in: transaction struct */ + const char* msg) /* in: detailed error message */ +{ + ut_strlcpy(trx->detailed_error, msg, sizeof(trx->detailed_error)); +} + +/***************************************************************** +Set detailed error message for the transaction from a file. Note that the +file is rewinded before reading from it. */ + +void +trx_set_detailed_error_from_file( +/*=============================*/ + trx_t* trx, /* in: transaction struct */ + FILE* file) /* in: file to read message from */ +{ + os_file_read_string(file, trx->detailed_error, + sizeof(trx->detailed_error)); +} + /******************************************************************** Retrieves the error_info field from a trx. */ @@ -130,6 +156,7 @@ trx_create( trx->undo_no_arr = NULL; trx->error_state = DB_SUCCESS; + trx->detailed_error[0] = '\0'; trx->sess = sess; trx->que_state = TRX_QUE_RUNNING; diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c index 3e8fd79a739..47b1e24e5e1 100644 --- a/innobase/ut/ut0mem.c +++ b/innobase/ut/ut0mem.c @@ -342,6 +342,54 @@ ut_free_all_mem(void) } } +/************************************************************************** +Copies up to size - 1 characters from the NUL-terminated string src to +dst, NUL-terminating the result. Returns strlen(src), so truncation +occurred if the return value >= size. */ + +ulint +ut_strlcpy( +/*=======*/ + /* out: strlen(src) */ + char* dst, /* in: destination buffer */ + const char* src, /* in: source buffer */ + ulint size) /* in: size of destination buffer */ +{ + ulint src_size = strlen(src); + + if (size != 0) { + ulint n = ut_min(src_size, size - 1); + + memcpy(dst, src, n); + dst[n] = '\0'; + } + + return(src_size); +} + +/************************************************************************** +Like ut_strlcpy, but if src doesn't fit in dst completely, copies the last +(size - 1) bytes of src, not the first. */ + +ulint +ut_strlcpy_rev( +/*===========*/ + /* out: strlen(src) */ + char* dst, /* in: destination buffer */ + const char* src, /* in: source buffer */ + ulint size) /* in: size of destination buffer */ +{ + ulint src_size = strlen(src); + + if (size != 0) { + ulint n = ut_min(src_size, size - 1); + + memcpy(dst, src + src_size - n, n + 1); + } + + return(src_size); +} + /************************************************************************** Make a quoted copy of a NUL-terminated string. Leading and trailing quotes will not be included; only embedded quotes will be escaped. diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 9aef03f20d2..943b75f9973 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -37,7 +37,7 @@ SUBDIRS = . examples libmysqld_sources= libmysqld.c lib_sql.cc emb_qcache.cc libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \ my_time.c -sqlexamplessources = ha_example.cc ha_archive.cc ha_tina.cc +sqlexamplessources = ha_example.cc ha_tina.cc noinst_HEADERS = embedded_priv.h emb_qcache.h @@ -60,10 +60,10 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \ sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \ unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc \ - spatial.cc gstream.cc sql_help.cc tztime.cc protocol_cursor.cc \ + spatial.cc gstream.cc sql_help.cc tztime.cc sql_cursor.cc \ sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \ parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \ - ha_blackhole.cc + ha_blackhole.cc ha_archive.cc libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources) libmysqld_a_SOURCES= diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index a86d467299c..8552b1c2b8a 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -423,9 +423,9 @@ int init_embedded_server(int argc, char **argv, char **groups) acl_error= 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (!(acl_error= acl_init((THD *)0, opt_noacl)) && + if (!(acl_error= acl_init(opt_noacl)) && !opt_noacl) - (void) grant_init((THD *)0); + (void) grant_init(); #endif if (acl_error || my_tz_init((THD *)0, default_tz_name, opt_bootstrap)) { @@ -514,8 +514,8 @@ void *create_embedded_thd(int client_flag, char *db) thd->db= db; thd->db_length= db ? strip_sp(db) : 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS - thd->db_access= DB_ACLS; - thd->master_access= ~NO_ACCESS; + thd->security_ctx->db_access= DB_ACLS; + thd->security_ctx->master_access= ~NO_ACCESS; #endif thd->net.query_cache_query= 0; @@ -532,10 +532,9 @@ err: int check_embedded_connection(MYSQL *mysql) { THD *thd= (THD*)mysql->thd; - thd->host= (char*)my_localhost; - thd->host_or_ip= thd->host; - thd->user= my_strdup(mysql->user, MYF(0)); - thd->priv_user= thd->user; + Security_context *sctx= thd->security_ctx; + sctx->host_or_ip= sctx->host= (char*)my_localhost; + sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0)); return check_user(thd, COM_CONNECT, NULL, 0, thd->db, true); } @@ -543,26 +542,27 @@ int check_embedded_connection(MYSQL *mysql) int check_embedded_connection(MYSQL *mysql) { THD *thd= (THD*)mysql->thd; + Security_context *sctx= thd->security_ctx; int result; char scramble_buff[SCRAMBLE_LENGTH]; int passwd_len; if (mysql->options.client_ip) { - thd->host= my_strdup(mysql->options.client_ip, MYF(0)); - thd->ip= my_strdup(thd->host, MYF(0)); + sctx->host= my_strdup(mysql->options.client_ip, MYF(0)); + sctx->ip= my_strdup(sctx->host, MYF(0)); } else - thd->host= (char*)my_localhost; - thd->host_or_ip= thd->host; + sctx->host= (char*)my_localhost; + sctx->host_or_ip= sctx->host; - if (acl_check_host(thd->host,thd->ip)) + if (acl_check_host(sctx->host, sctx->ip)) { result= ER_HOST_NOT_PRIVILEGED; goto err; } - thd->user= my_strdup(mysql->user, MYF(0)); + sctx->user= my_strdup(mysql->user, MYF(0)); if (mysql->passwd && mysql->passwd[0]) { memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble diff --git a/man/which.2 b/man/which.2 deleted file mode 100644 index 30d5557ed01..00000000000 --- a/man/which.2 +++ /dev/null @@ -1,54 +0,0 @@ -.TH WHICH 1 "20 December 2000" -.SH NAME -which - Jani please supply one. -.SH USAGE -which [options] [--] programname [...] -.SH SYNOPSIS -.B which -.RB [ \-\-version | \-[vV] ] -.RB [ \-\-skip\-dot ] -.RB [ \-\-skip\-tilde ] -.RB [ \-\-show\-dot ] -.RB [ \-\-show\-tilde ] -.RB [ \-\-tty\-only ] -.RB [ \-\-all | \-a ] -.RB [ \-\-read\-alias | \-i ] -.RB [ \-\-skip\-alias ] -.SH DESCRIPTION -.TP -.BR which -supports by executing -.TP -.BR \-\-version | \-[vV] -Print version and exit successfully. -.TP -.BR \-\-skip\-dot -Skip directories in PATH that start with a dot. -.TP -.BR \-\-skip\-tilde -Skip directories in PATH that start with a tilde. -.TP -.BR \-\-show\-dot -Don\'t expand a dot to current directory in output. -.TP -.BR \-\-show\-tilde -Output a tilde for HOME directory for non-root. -.TP -.BR \-\-tty\-only -Stop processing options on the right if not on tty. -.TP -.BR \-\-all | \-a -Print all matches in PATH, not just the first -.TP -.BR \-\-read\-alias | \-i -Read list of aliases from stdin. -.TP -.BR \-\-skip\-alias -Ignore option -.BR --read-alias; -don\'t read stdin. -.SH "SEE ALSO" -isamchk (1), isamlog (1), mysqlaccess (1), mysqladmin (1), mysqlbug (1), mysqld (1), mysqldump (1), mysqlshow (1), msql2mysql (1), perror (1), replace (1), mysqld_safe (1), which1 (1), zap (1), -.SH AUTHOR -Ver 1.0, distribution 3.23.29a Michael (Monty) Widenius (monty@tcx.se), TCX Datakonsult AB (http://www.tcx.se). This software comes with no warranty. Manual page by L. (Kill-9) Pedersen (kill-9@kill-9.dk), Mercurmedia Data Model Architect / system developer (http://www.mercurmedia.com) -.\" end of man page \ No newline at end of file diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index c18984c7584..19f0ef77136 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -473,7 +473,8 @@ static int _ftb_check_phrase(const byte *s0, const byte *e0, for (;;) { n_word= (FT_WORD *)phrase_element->data; - if (my_strnncoll(cs, h_word.pos, h_word.len, n_word->pos, n_word->len)) + if (my_strnncoll(cs, (const uchar *) h_word.pos, h_word.len, + (const uchar *) n_word->pos, n_word->len)) break; if (! (phrase_element= phrase_element->next)) DBUG_RETURN(1); diff --git a/myisam/ft_nlq_search.c b/myisam/ft_nlq_search.c index 7a506fd11c6..8460db61a36 100644 --- a/myisam/ft_nlq_search.c +++ b/myisam/ft_nlq_search.c @@ -266,7 +266,8 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query, so if ndocs == 0, FT_INFO.doc[] must not be accessed. */ dlist=(FT_INFO *)my_malloc(sizeof(FT_INFO)+ - sizeof(FT_DOC)*(aio.dtree.elements_in_tree-1), + sizeof(FT_DOC)* + (int)(aio.dtree.elements_in_tree-1), MYF(0)); if (!dlist) goto err; diff --git a/myisam/mi_check.c b/myisam/mi_check.c index ffb7cdd503f..f5d46210944 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -80,6 +80,7 @@ void myisamchk_init(MI_CHECK *param) param->start_check_pos=0; param->max_record_length= LONGLONG_MAX; param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE; + param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL; } /* Check the status flags for the table */ @@ -559,10 +560,11 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, ha_checksum *key_checksum, uint level) { int flag; - uint used_length,comp_flag,nod_flag,key_length=0,not_used; + uint used_length,comp_flag,nod_flag,key_length=0; uchar key[MI_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos; my_off_t next_page,record; char llbuff[22]; + uint diff_pos; DBUG_ENTER("chk_index"); DBUG_DUMP("buff",(byte*) buff,mi_getint(buff)); @@ -620,7 +622,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, } if ((*keys)++ && (flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length, - comp_flag, ¬_used)) >=0) + comp_flag, &diff_pos)) >=0) { DBUG_DUMP("old",(byte*) info->lastkey, info->lastkey_length); DBUG_DUMP("new",(byte*) key, key_length); @@ -636,11 +638,11 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, { if (*keys != 1L) /* not first_key */ { - uint diff; - ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY, - SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, - &diff); - param->unique_count[diff-1]++; + if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL) + ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY, + SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, + &diff_pos); + param->unique_count[diff_pos-1]++; } } (*key_checksum)+= mi_byte_checksum((byte*) key, @@ -1045,9 +1047,12 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) /* We don't need to lock the key tree here as we don't allow concurrent threads when running myisamchk */ - int search_result= (keyinfo->flag & HA_SPATIAL) ? + int search_result= +#ifdef HAVE_RTREE_KEYS + (keyinfo->flag & HA_SPATIAL) ? rtree_find_first(info, key, info->lastkey, key_length, SEARCH_SAME) : +#endif _mi_search(info,keyinfo,info->lastkey,key_length, SEARCH_SAME, info->s->state.key_root[key]); if (search_result) @@ -1090,7 +1095,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) "Keypointers and record positions doesn't match"); error=1; } - else if (param->glob_crc != info->s->state.checksum && + else if (param->glob_crc != info->state->checksum && (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))) { @@ -1386,7 +1391,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, info->state->data_file_length=sort_param.max_pos; } if (param->testflag & T_CALC_CHECKSUM) - share->state.checksum=param->glob_crc; + info->state->checksum=param->glob_crc; if (!(param->testflag & T_SILENT)) { @@ -2014,7 +2019,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, sort_param.sort_info=&sort_info; sort_param.fix_datafile= (my_bool) (! rep_quick); sort_param.master =1; - + del=info->state->del; param->glob_crc=0; if (param->testflag & T_CALC_CHECKSUM) @@ -2154,7 +2159,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, my_errno); } if (param->testflag & T_CALC_CHECKSUM) - share->state.checksum=param->glob_crc; + info->state->checksum=param->glob_crc; if (my_chsize(share->kfile,info->state->key_file_length,0,MYF(0))) mi_check_print_warning(param, @@ -2575,7 +2580,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, my_errno); } if (param->testflag & T_CALC_CHECKSUM) - share->state.checksum=param->glob_crc; + info->state->checksum=param->glob_crc; if (my_chsize(share->kfile,info->state->key_file_length,0,MYF(0))) mi_check_print_warning(param, @@ -3194,9 +3199,11 @@ int sort_write_record(MI_SORT_PARAM *sort_param) break; case COMPRESSED_RECORD: reclength=info->packed_length; - length=save_pack_length(block_buff,reclength); + length= save_pack_length((uint) share->pack.version, block_buff, + reclength); if (info->s->base.blobs) - length+=save_pack_length(block_buff+length,info->blob_length); + length+= save_pack_length((uint) share->pack.version, + block_buff + length, info->blob_length); if (my_b_write(&info->rec_cache,block_buff,length) || my_b_write(&info->rec_cache,(byte*) sort_param->rec_buff,reclength)) { @@ -3248,9 +3255,10 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a) cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE, &diff_pos); - ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, - (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, - &diff_pos); + if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL) + ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, + (uchar*) a, USE_WHOLE_KEY, + SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, &diff_pos); sort_param->unique[diff_pos-1]++; } else @@ -3803,7 +3811,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename) (*org_info)->s->state.create_time=share.state.create_time; (*org_info)->s->state.unique=(*org_info)->this_unique= share.state.unique; - (*org_info)->s->state.checksum=share.state.checksum; + (*org_info)->state->checksum=info.state->checksum; (*org_info)->state->del=info.state->del; (*org_info)->s->state.dellink=share.state.dellink; (*org_info)->state->empty=info.state->empty; @@ -3987,9 +3995,10 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info, unique[0]= (#different values of {keypart1}) - 1 unique[1]= (#different values of {keypart2,keypart1} tuple) - unique[0] - 1 ... - Here we assume that NULL != NULL (see SEARCH_NULL_ARE_NOT_EQUAL). The - 'unique' array is collected in one sequential scan through the entire + The 'unique' array is collected in one sequential scan through the entire index. This is done in two places: in chk_index() and in sort_key_write(). + Statistics collection may consider NULLs as either equal or unequal (see + SEARCH_NULL_ARE_NOT_EQUAL, MI_STATS_METHOD_*). Output is an array: rec_per_key_part[k] = diff --git a/myisam/mi_dbug.c b/myisam/mi_dbug.c index e782d21afe7..ddc8a403a33 100644 --- a/myisam/mi_dbug.c +++ b/myisam/mi_dbug.c @@ -40,12 +40,12 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg, end= key+ keyseg->length; if (keyseg->flag & HA_NULL_PART) { - if (!*key) + /* A NULL value is encoded by a 1-byte flag. Zero means NULL. */ + if (! *(key++)) { fprintf(stream,"NULL"); continue; } - key++; } switch (keyseg->type) { diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index 60a07254e82..62ca7f8ff61 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -93,7 +93,7 @@ int mi_delete(MI_INFO *info,const byte *record) if ((*share->delete_record)(info)) goto err; /* Remove record from database */ - info->s->state.checksum-=info->checksum; + info->state->checksum-=info->checksum; info->update= HA_STATE_CHANGED+HA_STATE_DELETED+HA_STATE_ROW_CHANGED; info->state->records--; diff --git a/myisam/mi_delete_all.c b/myisam/mi_delete_all.c index 3033249886f..a30abb95070 100644 --- a/myisam/mi_delete_all.c +++ b/myisam/mi_delete_all.c @@ -41,7 +41,7 @@ int mi_delete_all_rows(MI_INFO *info) info->state->key_file_length=share->base.keystart; info->state->data_file_length=0; info->state->empty=info->state->key_empty=0; - state->checksum=0; + info->state->checksum=0; for (i=share->base.max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; ) state->key_del[i]= HA_OFFSET_ERROR; diff --git a/myisam/mi_key.c b/myisam/mi_key.c index ae50900a190..4cabfc91197 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -358,7 +358,7 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr, byte *blob_ptr; DBUG_ENTER("_mi_put_key_in_record"); - blob_ptr= info->lastkey2; /* Place to put blob parts */ + blob_ptr= (byte*) info->lastkey2; /* Place to put blob parts */ key=(byte*) info->lastkey; /* KEy that was read */ key_end=key+info->lastkey_length; for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++) diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 82663e0c318..955d55cf765 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -199,7 +199,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d", len,MI_BASE_INFO_SIZE)) } - disk_pos=my_n_base_info_read((uchar*) disk_cache + base_pos, &share->base); + disk_pos= (char*) + my_n_base_info_read((uchar*) disk_cache + base_pos, &share->base); share->state.state_length=base_pos; if (!(open_flags & HA_OPEN_FOR_REPAIR) && @@ -822,7 +823,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite) mi_sizestore(ptr,state->state.empty); ptr +=8; mi_sizestore(ptr,state->state.key_empty); ptr +=8; mi_int8store(ptr,state->auto_increment); ptr +=8; - mi_int8store(ptr,(ulonglong) state->checksum);ptr +=8; + mi_int8store(ptr,(ulonglong) state->state.checksum);ptr +=8; mi_int4store(ptr,state->process); ptr +=4; mi_int4store(ptr,state->unique); ptr +=4; mi_int4store(ptr,state->status); ptr +=4; @@ -863,7 +864,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite) } -char *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state) +uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state) { uint i,keys,key_parts,key_blocks; memcpy_fixed(&state->header,ptr, sizeof(state->header)); @@ -884,7 +885,7 @@ char *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state) state->state.empty = mi_sizekorr(ptr); ptr +=8; state->state.key_empty= mi_sizekorr(ptr); ptr +=8; state->auto_increment=mi_uint8korr(ptr); ptr +=8; - state->checksum=(ha_checksum) mi_uint8korr(ptr); ptr +=8; + state->state.checksum=(ha_checksum) mi_uint8korr(ptr); ptr +=8; state->process= mi_uint4korr(ptr); ptr +=4; state->unique = mi_uint4korr(ptr); ptr +=4; state->status = mi_uint4korr(ptr); ptr +=4; @@ -974,7 +975,7 @@ uint mi_base_info_write(File file, MI_BASE_INFO *base) } -char *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base) +uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base) { base->keystart = mi_sizekorr(ptr); ptr +=8; base->max_data_file_length = mi_sizekorr(ptr); ptr +=8; diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index c251e4dda4a..e242e9d506d 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -151,11 +151,12 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) my_errno=HA_ERR_END_OF_FILE; goto err0; } - if (memcmp((byte*) header,(byte*) myisam_pack_file_magic,4)) + if (memcmp((byte*) header, (byte*) myisam_pack_file_magic, 3)) { my_errno=HA_ERR_WRONG_IN_RECORD; goto err0; } + share->pack.version= header[3]; share->pack.header_length= uint4korr(header+4); share->min_pack_length=(uint) uint4korr(header+8); share->max_pack_length=(uint) uint4korr(header+12); @@ -1070,38 +1071,12 @@ uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BLOCK_INFO *info, File file, return BLOCK_FATAL_ERROR; DBUG_DUMP("header",(byte*) header,ref_length); } - if (header[0] < 254) - { - info->rec_len=header[0]; - head_length=1; - } - else if (header[0] == 254) - { - info->rec_len=uint2korr(header+1); - head_length=3; - } - else - { - info->rec_len=uint3korr(header+1); - head_length=4; - } + head_length= read_pack_length((uint) myisam->s->pack.version, header, + &info->rec_len); if (myisam->s->base.blobs) { - if (header[head_length] < 254) - { - info->blob_len=header[head_length]; - head_length++; - } - else if (header[head_length] == 254) - { - info->blob_len=uint2korr(header+head_length+1); - head_length+=3; - } - else - { - info->blob_len=uint3korr(header+head_length+1); - head_length+=4; - } + head_length+= read_pack_length((uint) myisam->s->pack.version, + header + head_length, &info->blob_len); if (!(mi_alloc_rec_buff(myisam,info->rec_len + info->blob_len, &myisam->rec_buff))) return BLOCK_FATAL_ERROR; /* not enough memory */ @@ -1251,34 +1226,12 @@ void _mi_unmap_file(MI_INFO *info) static uchar *_mi_mempack_get_block_info(MI_INFO *myisam,MI_BLOCK_INFO *info, uchar *header) { - if (header[0] < 254) - info->rec_len= *header++; - else if (header[0] == 254) - { - info->rec_len=uint2korr(header+1); - header+=3; - } - else - { - info->rec_len=uint3korr(header+1); - header+=4; - } + header+= read_pack_length((uint) myisam->s->pack.version, header, + &info->rec_len); if (myisam->s->base.blobs) { - if (header[0] < 254) - { - info->blob_len= *header++; - } - else if (header[0] == 254) - { - info->blob_len=uint2korr(header+1); - header+=3; - } - else - { - info->blob_len=uint3korr(header+1); - header+=4; - } + header+= read_pack_length((uint) myisam->s->pack.version, header, + &info->blob_len); /* mi_alloc_rec_buff sets my_errno on error */ if (!(mi_alloc_rec_buff(myisam, info->blob_len, &myisam->rec_buff))) @@ -1350,7 +1303,7 @@ static int _mi_read_rnd_mempack_record(MI_INFO *info, byte *buf, /* Save length of row */ -uint save_pack_length(byte *block_buff,ulong length) +uint save_pack_length(uint version, byte *block_buff, ulong length) { if (length < 254) { @@ -1364,6 +1317,46 @@ uint save_pack_length(byte *block_buff,ulong length) return 3; } *(uchar*) block_buff=255; - int3store(block_buff+1,(ulong) length); - return 4; + if (version == 1) /* old format */ + { + DBUG_ASSERT(length <= 0xFFFFFF); + int3store(block_buff + 1, (ulong) length); + return 4; + } + else + { + int4store(block_buff + 1, (ulong) length); + return 5; + } +} + + +uint read_pack_length(uint version, const uchar *buf, ulong *length) +{ + if (buf[0] < 254) + { + *length= buf[0]; + return 1; + } + else if (buf[0] == 254) + { + *length= uint2korr(buf + 1); + return 3; + } + if (version == 1) /* old format */ + { + *length= uint3korr(buf + 1); + return 4; + } + else + { + *length= uint4korr(buf + 1); + return 5; + } +} + + +uint calc_pack_length(uint version, ulong length) +{ + return (length < 254) ? 1 : (length < 65536) ? 3 : (version == 1) ? 4 : 5; } diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 635a7eb2c48..e6f4d39ab49 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -31,8 +31,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, HA_KEYSEG *last_used_keyseg; uint pack_key_length, use_key_length, nextflag; DBUG_ENTER("mi_rkey"); - DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d", - info,inx,search_flag)); + DBUG_PRINT("enter", ("base: %lx buf: %lx inx: %d search_flag: %d", + (long) info, (long) buf, inx, search_flag)); if ((inx = _mi_check_index(info,inx)) < 0) DBUG_RETURN(my_errno); @@ -56,9 +56,12 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, { if (key_len == 0) key_len=USE_WHOLE_KEY; + /* Save the packed key for later use in the second buffer of lastkey. */ key_buff=info->lastkey+info->s->base.max_key_length; pack_key_length=_mi_pack_key(info,(uint) inx, key_buff, (uchar*) key, key_len, &last_used_keyseg); + /* Save packed_key_length for use by the MERGE engine. */ + info->pack_key_length= pack_key_length; DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg, key_buff, pack_key_length);); } diff --git a/myisam/mi_search.c b/myisam/mi_search.c index b7360dba7f3..92efdfee457 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -259,15 +259,16 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, { mi_print_error(info->s, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; - DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p", - length, page, end)); + DBUG_PRINT("error",("Found wrong key: length: %u page: %lx end: %lx", + length, (long) page, (long) end)); DBUG_RETURN(MI_FOUND_WRONG_KEY); } if ((flag=ha_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag, ¬_used)) >= 0) break; #ifdef EXTRA_DEBUG - DBUG_PRINT("loop",("page: %p key: '%s' flag: %d", page, t_buff, flag)); + DBUG_PRINT("loop",("page: %lx key: '%s' flag: %d", (long) page, t_buff, + flag)); #endif memcpy(buff,t_buff,length); *ret_pos=page; @@ -275,7 +276,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, if (flag == 0) memcpy(buff,t_buff,length); /* Result is first key */ *last_key= page == end; - DBUG_PRINT("exit",("flag: %d ret_pos: %p", flag, *ret_pos)); + DBUG_PRINT("exit",("flag: %d ret_pos: %lx", flag, (long) *ret_pos)); DBUG_RETURN(flag); } /* _mi_seq_search */ @@ -415,8 +416,8 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, { mi_print_error(info->s, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; - DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p", - length, page, end)); + DBUG_PRINT("error",("Found wrong key: length: %u page: %lx end: %lx", + length, (long) page, (long) end)); DBUG_RETURN(MI_FOUND_WRONG_KEY); } @@ -550,7 +551,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, *last_key= page == end; - DBUG_PRINT("exit",("flag: %d ret_pos: %p", flag, *ret_pos)); + DBUG_PRINT("exit",("flag: %d ret_pos: %lx", flag, (long) *ret_pos)); DBUG_RETURN(flag); } /* _mi_prefix_search */ @@ -812,8 +813,8 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, if (length > keyseg->length) { DBUG_PRINT("error", - ("Found too long null packed key: %u of %u at %p", - length, keyseg->length, *page_pos)); + ("Found too long null packed key: %u of %u at %lx", + length, keyseg->length, (long) *page_pos)); DBUG_DUMP("key",(char*) *page_pos,16); mi_print_error(keyinfo->share, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; @@ -869,8 +870,8 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, } if (length > (uint) keyseg->length) { - DBUG_PRINT("error",("Found too long packed key: %u of %u at %p", - length, keyseg->length, *page_pos)); + DBUG_PRINT("error",("Found too long packed key: %u of %u at %lx", + length, keyseg->length, (long) *page_pos)); DBUG_DUMP("key",(char*) *page_pos,16); mi_print_error(keyinfo->share, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; @@ -915,22 +916,32 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, reg1 HA_KEYSEG *keyseg; uchar *start_key,*page,*page_end,*from,*from_end; uint length,tmp; + DBUG_ENTER("_mi_get_binary_pack_key"); page= *page_pos; page_end=page+MI_MAX_KEY_BUFF+1; start_key=key; + /* + Keys are compressed the following way: + + prefix length Packed length of prefix for the prev key. (1 or 3 bytes) + for each key segment: + [is null] Null indicator if can be null (1 byte, zero means null) + [length] Packed length if varlength (1 or 3 bytes) + pointer Reference to the data file (last_keyseg->length). + */ get_key_length(length,page); if (length) { if (length > keyinfo->maxlength) { - DBUG_PRINT("error",("Found too long binary packed key: %u of %u at %p", - length, keyinfo->maxlength, *page_pos)); + DBUG_PRINT("error",("Found too long binary packed key: %u of %u at %lx", + length, keyinfo->maxlength, (long) *page_pos)); DBUG_DUMP("key",(char*) *page_pos,16); mi_print_error(keyinfo->share, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; - return 0; /* Wrong key */ + DBUG_RETURN(0); /* Wrong key */ } from=key; from_end=key+length; } @@ -973,9 +984,9 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, length-=tmp; from=page; from_end=page_end; } - DBUG_PRINT("info",("key: %p from: %p length: %u", - key, from, length)); - memcpy_overlap((byte*) key, (byte*) from, (size_t) length); + DBUG_PRINT("info",("key: %lx from: %lx length: %u", + (long) key, (long) from, length)); + memmove((byte*) key, (byte*) from, (size_t) length); key+=length; from+=length; } @@ -992,12 +1003,12 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, DBUG_PRINT("error",("Error when unpacking key")); mi_print_error(keyinfo->share, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; - return 0; /* Error */ + DBUG_RETURN(0); /* Error */ } memcpy((byte*) key,(byte*) from,(size_t) length); *page_pos= from+length; } - return((uint) (key-start_key)+keyseg->length); + DBUG_RETURN((uint) (key-start_key)+keyseg->length); } @@ -1031,7 +1042,8 @@ uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, } } } - DBUG_PRINT("exit",("page: %p length: %u", page, *return_key_length)); + DBUG_PRINT("exit",("page: %lx length: %u", (long) page, + *return_key_length)); DBUG_RETURN(page); } /* _mi_get_key */ @@ -1083,7 +1095,7 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uint nod_flag; uchar *lastpos; DBUG_ENTER("_mi_get_last_key"); - DBUG_PRINT("enter",("page: %p endpos: %p", page, endpos)); + DBUG_PRINT("enter",("page: %lx endpos: %lx", (long) page, (long) endpos)); nod_flag=mi_test_if_nod(page); if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY))) @@ -1103,14 +1115,16 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,lastkey); if (*return_key_length == 0) { - DBUG_PRINT("error",("Couldn't find last key: page: %p", page)); + DBUG_PRINT("error",("Couldn't find last key: page: %lx", + (long) page)); mi_print_error(info->s, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; DBUG_RETURN(0); } } } - DBUG_PRINT("exit",("lastpos: %p length: %u", lastpos, *return_key_length)); + DBUG_PRINT("exit",("lastpos: %lx length: %u", (long) lastpos, + *return_key_length)); DBUG_RETURN(lastpos); } /* _mi_get_last_key */ @@ -1649,7 +1663,8 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, ref_length=0; next_length_pack=0; } - DBUG_PRINT("test",("length: %d next_key: %p", length, next_key)); + DBUG_PRINT("test",("length: %d next_key: %lx", length, + (long) next_key)); { uint tmp_length; diff --git a/myisam/mi_static.c b/myisam/mi_static.c index 4c9d814f7d6..fc585eb5543 100644 --- a/myisam/mi_static.c +++ b/myisam/mi_static.c @@ -27,7 +27,7 @@ LIST *myisam_open_list=0; uchar NEAR myisam_file_magic[]= { (uchar) 254, (uchar) 254,'\007', '\001', }; uchar NEAR myisam_pack_file_magic[]= -{ (uchar) 254, (uchar) 254,'\010', '\001', }; +{ (uchar) 254, (uchar) 254,'\010', '\002', }; my_string myisam_log_filename=(char*) "myisam.log"; File myisam_log_file= -1; uint myisam_quick_table_bits=9; diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c index 5727c699469..60225ccc7f3 100644 --- a/myisam/mi_test1.c +++ b/myisam/mi_test1.c @@ -237,7 +237,7 @@ static int run_test(const char *filename) pos=HA_OFFSET_ERROR; } if (found != row_count) - printf("Found %ld of %ld rows\n", found,row_count); + printf("Found %ld of %ld rows\n", (ulong) found, (ulong) row_count); } if (!silent) @@ -303,7 +303,8 @@ static int run_test(const char *filename) if ((error=mi_rrnd(file,read_record,i == 1 ? 0L : HA_OFFSET_ERROR)) == -1) { if (found != row_count-deleted) - printf("Found only %ld of %ld rows\n",found,row_count-deleted); + printf("Found only %ld of %ld rows\n", (ulong) found, + (ulong) (row_count - deleted)); break; } if (!error) diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c index 95c8ce56a13..6a6dcb971a2 100644 --- a/myisam/mi_test2.c +++ b/myisam/mi_test2.c @@ -831,17 +831,19 @@ end: puts("Locking used"); if (use_blob) puts("blobs used"); -#if 0 printf("key cache status: \n\ blocks used:%10lu\n\ +not flushed:%10lu\n\ w_requests: %10lu\n\ writes: %10lu\n\ r_requests: %10lu\n\ reads: %10lu\n", - my_blocks_used, - my_cache_w_requests, my_cache_write, - my_cache_r_requests, my_cache_read); -#endif + dflt_key_cache->blocks_used, + dflt_key_cache->global_blocks_changed, + (ulong) dflt_key_cache->global_cache_w_requests, + (ulong) dflt_key_cache->global_cache_write, + (ulong) dflt_key_cache->global_cache_r_requests, + (ulong) dflt_key_cache->global_cache_read); } end_key_cache(dflt_key_cache,1); if (blob_buffer) diff --git a/myisam/mi_update.c b/myisam/mi_update.c index ab23f2e6da9..86652996afe 100644 --- a/myisam/mi_update.c +++ b/myisam/mi_update.c @@ -162,7 +162,7 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec) if (auto_key_changed) update_auto_increment(info,newrec); if (share->calc_checksum) - share->state.checksum+=(info->checksum - old_checksum); + info->state->checksum+=(info->checksum - old_checksum); info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV | key_changed); diff --git a/myisam/mi_write.c b/myisam/mi_write.c index c8f9aa84a41..8785adae9a2 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -142,7 +142,7 @@ int mi_write(MI_INFO *info, byte *record) { if ((*share->write_record)(info,record)) goto err; - share->state.checksum+=info->checksum; + info->state->checksum+=info->checksum; } if (share->base.auto_key) update_auto_increment(info,record); diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 78ae756bf7c..a90495e5fcb 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -67,6 +67,7 @@ static const char *field_pack[]= "no zeros", "blob", "constant", "table-lockup", "always zero","varchar","unique-hash","?","?"}; +static const char *myisam_stats_method_str="nulls_unequal"; static void get_options(int *argc,char * * *argv); static void print_version(void); @@ -155,7 +156,7 @@ enum options_mc { OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE, OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN, OPT_FT_MAX_WORD_LEN, OPT_FT_STOPWORD_FILE, - OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE + OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE, OPT_STATS_METHOD }; static struct my_option my_long_options[] = @@ -336,6 +337,11 @@ static struct my_option my_long_options[] = "Use stopwords from this file instead of built-in list.", (gptr*) &ft_stopword_file, (gptr*) &ft_stopword_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"stats_method", OPT_STATS_METHOD, + "Specifies how index statistics collection code should threat NULLs. " + "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), and \"nulls_equal\" (emulate 4.0 behavior).", + (gptr*) &myisam_stats_method_str, (gptr*) &myisam_stats_method_str, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -465,6 +471,12 @@ static void usage(void) #include +const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal", + NullS}; +TYPELIB myisam_stats_method_typelib= { + array_elements(myisam_stats_method_names) - 1, "", + myisam_stats_method_names, NULL}; + /* Read options */ static my_bool @@ -684,6 +696,18 @@ get_one_option(int optid, else check_param.testflag|= T_CALC_CHECKSUM; break; + case OPT_STATS_METHOD: + { + int method; + myisam_stats_method_str= argument; + if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0) + { + fprintf(stderr, "Invalid value of stats_method: %s.\n", argument); + exit(1); + } + check_param.stats_method= (enum_mi_stats_method) (method-1); + break; + } #ifdef DEBUG /* Only useful if debugging */ case OPT_START_CHECK_POS: check_param.start_check_pos= strtoull(argument, NULL, 0); @@ -1237,7 +1261,7 @@ static void descript(MI_CHECK *param, register MI_INFO *info, my_string name) share->base.raid_chunksize); } if (share->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) - printf("Checksum: %23s\n",llstr(info->s->state.checksum,llbuff)); + printf("Checksum: %23s\n",llstr(info->state->checksum,llbuff)); ; if (share->options & HA_OPTION_DELAY_KEY_WRITE) printf("Keys are only flushed at close\n"); @@ -1552,7 +1576,7 @@ static int mi_sort_records(MI_CHECK *param, old_record_count=info->state->records; info->state->records=0; if (sort_info.new_data_file_type != COMPRESSED_RECORD) - share->state.checksum=0; + info->state->checksum=0; if (sort_record_index(&sort_param,info,keyinfo,share->state.key_root[sort_key], temp_buff, sort_key,new_file,update_index) || diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 74463ec065a..36328c9d9f1 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -38,6 +38,7 @@ typedef struct st_mi_status_info my_off_t key_empty; /* lost space in indexfile */ my_off_t key_file_length; my_off_t data_file_length; + ha_checksum checksum; } MI_STATUS_INFO; typedef struct st_mi_state_info @@ -75,7 +76,6 @@ typedef struct st_mi_state_info ulong sec_index_changed; /* Updated when new sec_index */ ulong sec_index_used; /* which extra index are in use */ ulonglong key_map; /* Which keys are in use */ - ha_checksum checksum; ulong version; /* timestamp of create */ time_t create_time; /* Time when created database */ time_t recover_time; /* Time for last recover */ @@ -149,6 +149,7 @@ typedef struct st_mi_blob /* Info of record */ typedef struct st_mi_isam_pack { ulong header_length; uint ref_length; + uchar version; } MI_PACK; @@ -260,6 +261,7 @@ struct st_myisam_info { uint last_rkey_length; /* Last length in mi_rkey() */ enum ha_rkey_function last_key_func; /* CONTAIN, OVERLAP, etc */ uint save_lastkey_length; + uint pack_key_length; /* For MYISAMMRG */ int errkey; /* Got last error on this key */ int lock_type; /* How database was locked */ int tmp_lock_type; /* When locked by readinfo */ @@ -673,13 +675,15 @@ extern void _myisam_log_record(enum myisam_log_commands command,MI_INFO *info, extern void mi_report_error(int errcode, const char *file_name); extern my_bool _mi_memmap_file(MI_INFO *info); extern void _mi_unmap_file(MI_INFO *info); -extern uint save_pack_length(byte *block_buff,ulong length); +extern uint save_pack_length(uint version, byte *block_buff, ulong length); +extern uint read_pack_length(uint version, const uchar *buf, ulong *length); +extern uint calc_pack_length(uint version, ulong length); uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite); -char *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state); +uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state); uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead); uint mi_base_info_write(File file, MI_BASE_INFO *base); -char *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base); +uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base); int mi_keyseg_write(File file, const HA_KEYSEG *keyseg); char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg); uint mi_keydef_write(File file, MI_KEYDEF *keydef); @@ -724,7 +728,7 @@ int flush_pending_blocks(MI_SORT_PARAM *param); int sort_ft_buf_flush(MI_SORT_PARAM *sort_param); int thr_write_keys(MI_SORT_PARAM *sort_param); #ifdef THREAD -pthread_handler_decl(thr_find_all_keys,arg); +pthread_handler_t thr_find_all_keys(void *arg); #endif int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, File file); diff --git a/myisam/myisampack.c b/myisam/myisampack.c index b8f21392f8a..114e80d8f1a 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -2008,7 +2008,7 @@ static char *hexdigits(ulonglong value) static int write_header(PACK_MRG_INFO *mrg,uint head_length,uint trees, my_off_t tot_elements,my_off_t filelength) { - byte *buff=file_buffer.pos; + byte *buff= (byte*) file_buffer.pos; bzero(buff,HEAD_LENGTH); memcpy_fixed(buff,myisam_pack_file_magic,4); @@ -2024,7 +2024,7 @@ static int write_header(PACK_MRG_INFO *mrg,uint head_length,uint trees, if (test_only) return 0; VOID(my_seek(file_buffer.file,0L,MY_SEEK_SET,MYF(0))); - return my_write(file_buffer.file,file_buffer.pos,HEAD_LENGTH, + return my_write(file_buffer.file,(const byte *) file_buffer.pos,HEAD_LENGTH, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0; } @@ -2417,6 +2417,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) HUFF_COUNTS *count,*end_count; HUFF_TREE *tree; MI_INFO *isam_file=mrg->file[0]; + uint pack_version= (uint) isam_file->s->pack.version; DBUG_ENTER("compress_isam_file"); /* Allocate a buffer for the records (excluding blobs). */ @@ -2455,25 +2456,11 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) huff_counts[i].tree->height+huff_counts[i].length_bits; } max_calc_length= (max_calc_length + 7) / 8; - if (max_calc_length < 254) - pack_ref_length=1; - else if (max_calc_length <= 65535) - pack_ref_length=3; - else - pack_ref_length=4; - + pack_ref_length= calc_pack_length(pack_version, max_calc_length); record_count=0; /* 'max_blob_length' is the max length of all blobs of a record. */ - pack_blob_length=0; - if (isam_file->s->base.blobs) - { - if (mrg->max_blob_length < 254) - pack_blob_length=1; - else if (mrg->max_blob_length <= 65535) - pack_blob_length=3; - else - pack_blob_length=4; - } + pack_blob_length= isam_file->s->base.blobs ? + calc_pack_length(pack_version, mrg->max_blob_length) : 0; max_pack_length=pack_ref_length+pack_blob_length; DBUG_PRINT("fields", ("===")); @@ -2485,7 +2472,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) { if (flush_buffer((ulong) max_calc_length + (ulong) max_pack_length)) break; - record_pos=file_buffer.pos; + record_pos= (byte*) file_buffer.pos; file_buffer.pos+=max_pack_length; for (start_pos=record, count= huff_counts; count < end_count ; count++) { @@ -2746,9 +2733,10 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) } flush_bits(); length=(ulong) ((byte*) file_buffer.pos - record_pos) - max_pack_length; - pack_length=save_pack_length(record_pos,length); + pack_length= save_pack_length(pack_version, record_pos, length); if (pack_blob_length) - pack_length+=save_pack_length(record_pos+pack_length,tot_blob_length); + pack_length+= save_pack_length(pack_version, record_pos + pack_length, + tot_blob_length); DBUG_PRINT("fields", ("record: %lu length: %lu blob-length: %lu " "length-bytes: %lu", (ulong) record_count, length, tot_blob_length, pack_length)); @@ -2807,7 +2795,8 @@ static char *make_old_name(char *new_name, char *old_name) static void init_file_buffer(File file, pbool read_buffer) { file_buffer.file=file; - file_buffer.buffer=my_malloc(ALIGN_SIZE(RECORD_CACHE_SIZE),MYF(MY_WME)); + file_buffer.buffer= (uchar*) my_malloc(ALIGN_SIZE(RECORD_CACHE_SIZE), + MYF(MY_WME)); file_buffer.end=file_buffer.buffer+ALIGN_SIZE(RECORD_CACHE_SIZE)-8; file_buffer.pos_in_file=0; error_on_write=0; @@ -2849,7 +2838,8 @@ static int flush_buffer(ulong neaded_length) file_buffer.pos_in_file+=length; if (test_only) return 0; - if (error_on_write|| my_write(file_buffer.file,file_buffer.buffer, + if (error_on_write|| my_write(file_buffer.file, + (const byte*) file_buffer.buffer, length, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL))) { @@ -2862,13 +2852,13 @@ static int flush_buffer(ulong neaded_length) { char *tmp; neaded_length+=256; /* some margin */ - tmp=my_realloc(file_buffer.buffer, neaded_length,MYF(MY_WME)); + tmp= my_realloc((char*) file_buffer.buffer, neaded_length,MYF(MY_WME)); if (!tmp) return 1; file_buffer.pos= ((uchar*) tmp + (ulong) (file_buffer.pos - file_buffer.buffer)); - file_buffer.buffer=tmp; - file_buffer.end=tmp+neaded_length-8; + file_buffer.buffer= (uchar*) tmp; + file_buffer.end= (uchar*) (tmp+neaded_length-8); } return 0; } @@ -2977,7 +2967,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length, share->state.key_root[key]= HA_OFFSET_ERROR; for (key=0 ; key < share->state.header.max_block_size ; key++) share->state.key_del[key]= HA_OFFSET_ERROR; - share->state.checksum=crc; /* Save crc here */ + isam_file->state->checksum=crc; /* Save crc here */ share->changed=1; /* Force write of header */ share->state.open_count=0; share->global_changed=0; @@ -3013,7 +3003,7 @@ static int save_state_mrg(File file,PACK_MRG_INFO *mrg,my_off_t new_length, state.dellink= HA_OFFSET_ERROR; state.version=(ulong) time((time_t*) 0); mi_clear_all_keys_active(state.key_map); - state.checksum=crc; + state.state.checksum=crc; if (isam_file->s->base.keys) isamchk_neaded=1; state.changed=STATE_CHANGED | STATE_NOT_ANALYZED; /* Force check of table */ diff --git a/myisam/sort.c b/myisam/sort.c index fabd713ef45..6c718a0d453 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -307,7 +307,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, #ifdef THREAD /* Search after all keys and place them in a temp. file */ -pthread_handler_decl(thr_find_all_keys,arg) +pthread_handler_t thr_find_all_keys(void *arg) { MI_SORT_PARAM *info= (MI_SORT_PARAM*) arg; int error; diff --git a/myisam/sp_key.c b/myisam/sp_key.c index 1d43f89cba9..77cecdc0931 100644 --- a/myisam/sp_key.c +++ b/myisam/sp_key.c @@ -142,7 +142,7 @@ static int sp_add_point_to_mbr(uchar *(*wkb), uchar *end, uint n_dims, { if ((*wkb) > end - 8) return -1; - get_double(&ord, *wkb); + get_double(&ord, (const byte*) *wkb); (*wkb)+= 8; if (ord < *mbr) float8store((char*) mbr, ord); diff --git a/myisammrg/myrg_rkey.c b/myisammrg/myrg_rkey.c index a85ef6a3b5e..f87b264081e 100644 --- a/myisammrg/myrg_rkey.c +++ b/myisammrg/myrg_rkey.c @@ -44,11 +44,12 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key, MYRG_TABLE *table; MI_INFO *mi; int err; + DBUG_ENTER("myrg_rkey"); LINT_INIT(key_buff); LINT_INIT(pack_key_length); if (_myrg_init_queue(info,inx,search_flag)) - return my_errno; + DBUG_RETURN(my_errno); for (table=info->open_tables ; table != info->end_table ; table++) { @@ -57,8 +58,9 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key, if (table == info->open_tables) { err=mi_rkey(mi,0,inx,key,key_len,search_flag); + /* Get the saved packed key and packed key length. */ key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length; - pack_key_length=mi->last_rkey_length; + pack_key_length=mi->pack_key_length; } else { @@ -71,17 +73,22 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key, { if (err == HA_ERR_KEY_NOT_FOUND) continue; - return err; + DBUG_PRINT("exit", ("err: %d", err)); + DBUG_RETURN(err); } /* adding to queue */ queue_insert(&(info->by_key),(byte *)table); } + DBUG_PRINT("info", ("tables with matches: %u", info->by_key.elements)); if (!info->by_key.elements) - return HA_ERR_KEY_NOT_FOUND; + DBUG_RETURN(HA_ERR_KEY_NOT_FOUND); mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; mi->once_flags|= RRND_PRESERVE_LASTINX; - return _myrg_mi_read_record(mi,buf); + DBUG_PRINT("info", ("using table no: %d", + info->current_table - info->open_tables + 1)); + DBUG_DUMP("result key", (byte*) mi->lastkey, mi->lastkey_length); + DBUG_RETURN(_myrg_mi_read_record(mi,buf)); } diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 9b0db5774f5..f1194d7fc2f 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -53,7 +53,8 @@ dist-hook: -$(INSTALL_DATA) $(srcdir)/t/*.imtest $(distdir)/t $(INSTALL_DATA) $(srcdir)/t/*.sql $(distdir)/t -$(INSTALL_DATA) $(srcdir)/t/*.disabled $(distdir)/t - $(INSTALL_DATA) $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t + $(INSTALL_DATA) $(srcdir)/t/*.opt $(srcdir)/t/*.slave-mi $(distdir)/t + $(INSTALL_SCRIPT) $(srcdir)/t/*.sh $(distdir)/t $(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include $(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(distdir)/std_data @@ -61,6 +62,7 @@ dist-hook: $(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.frm $(distdir)/std_data + $(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(distdir)/lib $(INSTALL_DATA) $(srcdir)/lib/*.pl $(distdir)/lib @@ -78,7 +80,7 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/t/*.sql $(DESTDIR)$(testdir)/t -$(INSTALL_DATA) $(srcdir)/t/*.disabled $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.opt $(DESTDIR)$(testdir)/t - $(INSTALL_DATA) $(srcdir)/t/*.sh $(DESTDIR)$(testdir)/t + $(INSTALL_SCRIPT) $(srcdir)/t/*.sh $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.slave-mi $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/r/*.result $(DESTDIR)$(testdir)/r $(INSTALL_DATA) $(srcdir)/r/*.require $(DESTDIR)$(testdir)/r @@ -89,6 +91,7 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.frm $(DESTDIR)$(testdir)/std_data + $(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(DESTDIR)$(testdir)/lib $(INSTALL_DATA) $(srcdir)/lib/*.pl $(DESTDIR)$(testdir)/lib diff --git a/mysql-test/README.stress b/mysql-test/README.stress new file mode 100644 index 00000000000..001ecceef1b --- /dev/null +++ b/mysql-test/README.stress @@ -0,0 +1,116 @@ + +Overview +-------- + +Stress script is designed to perform testsing of mysql server in +multi-thread environment. + +Stress script allows: + + - to use for stress testing mysqltest binary as test engine + - to use for stress testing both regular test suite and any + additional test suites (e.g. mysql-test-extra-5.0) + - to specify files with lists of tests both for initialization of + stress db and for further testing itself + - to define number of threads that will be concurrently used in testing + - to define limitations for test run. e.g. number of tests or loops + for execution or duration of testing, delay between test executions, etc. + - to get readable log file which can be used for identification of + errors arose during testing + +All functionality regarding stress testing was implemeted in +mysql-stress-test.pl script and there are two ways to run stress test: + + - for most cases it is enough to use options below for starting of + stress test from mysql-test-run wrapper. In this case server will + be run automatically, all preparation steps will be performed + and after that stress test will be started. + + - in advanced case one can run mysql-stress-test.pl script directly. + But it requires to perform some preparation steps and to specify a + bunch of options as well so this way may look a bit complicate. + +Usage +----- + +Below is list of stress test specific options for mysql-test-run: + +--stress + Enable stress mode + +--stress-suite= + Test suite name that will be used in stress testing. + We assume that all suites are located in mysql-test/suite directory + There is one special suite name - that corresponds + to regular test suite located in mysql-test directory. + +--stress-threads= + Number of threads that will be used in stress testing + +--stress-tests-file= + Filename with list of tests(without .test suffix) that will be used in + stress testing. Default filename is stress_tests.txt and default + location of this file is suite//stress_tests.txt + +--stress-init-file= + Filename with list of tests(without .test suffix) that will be used in + stress testing for initialization of stress db. These tests will be + executed only once before starting of test itself. Default filename + is stress_init.txt and default location of this file is + suite//stress_init.txt + +--stress-mode= + Possible values are: random(default), seq + + There are two possible modes which affect order of selecting of tests + from the list: + - in random mode tests will be selected in random order + - in seq mode each thread will execute tests in the loop one by one as + they specified in the list file. + +--stress-test-count= + Total number of tests that will be executed concurrently by all threads + +--stress-loop-count= + Total number of loops in seq mode that will be executed concurrently + by all threads + +--stress-test-duration= + Duration of stress testing in seconds + +Examples +-------- + +1. Example of simple command line to start stress test: + + mysql-test-run --stress alias + +Runs stress test with default values for number of threads and number of tests, +with test 'alias' from suite 'main'. + +2. Using in stress testing tests from other suites: + + - mysql-test-run --stress --stress-threads=10 --stress-test-count=1000 \ + --stress-suite=example --stress-tests-file=testslist.txt + + Will run stress test with 10 threads, will execute 1000 tests by all + threads, test will be used from suite 'example', list of test will be + taken from file 'testslist.txt' + + - mysql-test-run --stress --stress-threads=10 --stress-test-count=1000 \ + --stress-suite=example sum_distinct + + Will run stress test with 10 threads, will execute 1000 tests by all + threads, test will be used from suite 'example', list of test contains + only one test 'sum_distinct' + +3. Debugging of issues found with stress test + + Right now stress test is not fully integrated in mysql-test-run + and does not support --gdb option so to debug issue found with stress + test you have to start separately mysql server under debuger and then + run stress test as: + + - mysql-test-run --extern --stress --stress-threads=10 \ + --stress-test-count=1000 --stress-suite=example \ + sum_distinct diff --git a/mysql-test/include/ctype_like_escape.inc b/mysql-test/include/ctype_like_escape.inc new file mode 100644 index 00000000000..ac97fbaa1a0 --- /dev/null +++ b/mysql-test/include/ctype_like_escape.inc @@ -0,0 +1,18 @@ +# +# Bugs: #13046: +# LIKE pattern matching using prefix index doesn't return correct result +# +select @@collation_connection; +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +-- should return ab_def +select c1 as c1u from t1 where c1 like 'ab\_def'; +-- should return ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +drop table t1; diff --git a/mysql-test/include/have_lowercase0.inc b/mysql-test/include/have_lowercase0.inc index f967c18928b..8d3ae02f61e 100644 --- a/mysql-test/include/have_lowercase0.inc +++ b/mysql-test/include/have_lowercase0.inc @@ -1,4 +1,4 @@ --require r/lowercase0.require ---disable_query_log; +--disable_query_log show variables like "lower_case_%"; ---enable_query_log; +--enable_query_log diff --git a/mysql-test/include/im_check_os.inc b/mysql-test/include/im_check_os.inc new file mode 100644 index 00000000000..9465115feb5 --- /dev/null +++ b/mysql-test/include/im_check_os.inc @@ -0,0 +1,7 @@ +--connect (dflt_server_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK) +--connection dflt_server_con + +--source include/not_windows.inc + +--connection default +--disconnect dflt_server_con diff --git a/mysql-test/include/mysqltest-x.inc b/mysql-test/include/mysqltest-x.inc new file mode 100644 index 00000000000..dd1468aed07 --- /dev/null +++ b/mysql-test/include/mysqltest-x.inc @@ -0,0 +1,2 @@ +echo Output from mysqltest-x.inc; + diff --git a/mysql-test/include/mysqltest_while.inc b/mysql-test/include/mysqltest_while.inc new file mode 100644 index 00000000000..90b05ee2695 --- /dev/null +++ b/mysql-test/include/mysqltest_while.inc @@ -0,0 +1,137 @@ +let $1 = 10; +while ($1) +{ +while ($1) +{ +while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + echo $1; + dec $1; +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} diff --git a/mysql-test/lib/init_db.sql b/mysql-test/lib/init_db.sql index 37353e5974f..fd7b035e038 100644 --- a/mysql-test/lib/init_db.sql +++ b/mysql-test/lib/init_db.sql @@ -62,7 +62,7 @@ comment='Host privileges; Merged with database privileges'; CREATE TABLE user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, - Password char(41) binary DEFAULT '' NOT NULL, + Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 250c3562227..fb622f2bbb3 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -61,22 +61,6 @@ sub collect_test_cases ($) { $elem= $tname; $tname =~ s/\.imtest$//; $component_id= 'im'; - - if ( $::glob_use_embedded_server ) - { - mtr_report( - "Instance Manager's tests are not available in embedded mode." . - "Test case '$tname' is skipped."); - next; - } - - unless ( $::exe_im ) - { - mtr_report( - "Instance Manager executable is unavailable. " . - "Test case '$tname' is skipped."); - next; - } } # If target component is known, check that the specified test case @@ -84,7 +68,7 @@ sub collect_test_cases ($) { # # Otherwise, try to guess the target component. - if ( defined $component_id ) + if ( $component_id ) { if ( ! -f "$testdir/$elem") { @@ -96,11 +80,11 @@ sub collect_test_cases ($) { my $mysqld_test_exists = -f "$testdir/$tname.test"; my $im_test_exists = -f "$testdir/$tname.imtest"; - if ( $mysqld_test_exists && $im_test_exists ) + if ( $mysqld_test_exists and $im_test_exists ) { mtr_error("Ambiguos test case name ($tname)"); } - elsif ( ! $mysqld_test_exists && !$im_test_exists ) + elsif ( ! $mysqld_test_exists and ! $im_test_exists ) { mtr_error("Test case $tname is not found"); } @@ -115,7 +99,7 @@ sub collect_test_cases ($) { $component_id= 'im'; } } - + collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,{}, $component_id); } @@ -403,6 +387,34 @@ sub collect_one_test_case($$$$$$$) { $tinfo->{'comment'}= mtr_fromfile($disabled_file); } + if ( $component_id eq 'im' ) + { + if ( $::glob_use_embedded_server ) + { + $tinfo->{'skip'}= 1; + + mtr_report( + "Instance Manager tests are not available in embedded mode. " . + "Test case '$tname' is skipped."); + } + elsif ( $::opt_ps_protocol ) + { + $tinfo->{'skip'}= 1; + + mtr_report( + "Instance Manager tests are not run with --ps-protocol. " . + "Test case '$tname' is skipped."); + } + elsif ( $::opt_skip_im ) + { + $tinfo->{'skip'}= 1; + + mtr_report( + "Instance Manager executable is unavailable." . + "Test case '$tname' is skipped."); + } + } + # We can't restart a running server that may be in use if ( $::glob_use_running_server and diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index 1b6dcf0e7fc..b3a243444c1 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -166,7 +166,7 @@ sub spawn_impl ($$$$$$$$) { { if ( ! open(STDOUT,$log_file_open_mode,$output) ) { - mtr_error("can't redirect STDOUT to \"$output\": $!"); + mtr_child_error("can't redirect STDOUT to \"$output\": $!"); } } @@ -176,14 +176,14 @@ sub spawn_impl ($$$$$$$$) { { if ( ! open(STDERR,">&STDOUT") ) { - mtr_error("can't dup STDOUT: $!"); + mtr_child_error("can't dup STDOUT: $!"); } } else { if ( ! open(STDERR,$log_file_open_mode,$error) ) { - mtr_error("can't redirect STDERR to \"$output\": $!"); + mtr_child_error("can't redirect STDERR to \"$error\": $!"); } } } @@ -192,13 +192,13 @@ sub spawn_impl ($$$$$$$$) { { if ( ! open(STDIN,"<",$input) ) { - mtr_error("can't redirect STDIN to \"$input\": $!"); + mtr_child_error("can't redirect STDIN to \"$input\": $!"); } } if ( ! exec($path,@$arg_list_t) ) { - mtr_error("failed to execute \"$path\": $!"); + mtr_child_error("failed to execute \"$path\": $!"); } } } @@ -360,9 +360,20 @@ sub mtr_kill_leftovers () { # First, kill all masters and slaves that would conflict with # this run. Make sure to remove the PID file, if any. + # FIXME kill IM manager first, else it will restart the servers, how?! my @args; + for ( my $idx; $idx < 2; $idx++ ) + { + push(@args,{ + pid => 0, # We don't know the PID + pidfile => $::instance_manager->{'instances'}->[$idx]->{'path_pid'}, + sockfile => $::instance_manager->{'instances'}->[$idx]->{'path_sock'}, + port => $::instance_manager->{'instances'}->[$idx]->{'port'}, + }); + } + for ( my $idx; $idx < 2; $idx++ ) { push(@args,{ @@ -560,8 +571,8 @@ sub mtr_stop_mysqld_servers ($) { start_reap_all(); # Avoid zombies - SIGNAL: - mtr_kill_processes(\keys (%mysqld_pids)); + my @mysqld_pids= keys %mysqld_pids; + mtr_kill_processes(\@mysqld_pids); stop_reap_all(); # Get into control again @@ -680,7 +691,8 @@ sub mtr_mysqladmin_shutdown { mtr_add_arg($args, "shutdown"); # We don't wait for termination of mysqladmin my $pid= mtr_spawn($::exe_mysqladmin, $args, - "", $::path_manager_log, $::path_manager_log, ""); + "", $::path_manager_log, $::path_manager_log, "", + { append_log_file => 1 }); $mysql_admin_pids{$pid}= 1; } @@ -847,14 +859,16 @@ sub sleep_until_file_created ($$$) { sub mtr_kill_processes ($) { my $pids = shift; - foreach my $sig (15,9) + foreach my $sig (15, 9) { - my $retries= 20; # FIXME 20 seconds, this is silly! - kill($sig, @{$pids}); - while ( $retries-- and kill(0, @{$pids}) ) + my $retries= 10; + while (1) { - mtr_debug("Sleep 1 second waiting for processes to die"); - sleep(1) # Wait one second + kill($sig, @{$pids}); + last unless kill (0, @{$pids}) and $retries--; + + mtr_debug("Sleep 2 second waiting for processes to die"); + sleep(2); } } } diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index 868653afaa4..515988ee5c7 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -19,6 +19,7 @@ sub mtr_print_header (); sub mtr_report (@); sub mtr_warning (@); sub mtr_error (@); +sub mtr_child_error (@); sub mtr_debug (@); @@ -74,7 +75,7 @@ sub mtr_show_failed_diff ($) { sub mtr_report_test_name ($) { my $tinfo= shift; - printf "%-31s ", $tinfo->{'name'}; + printf "%-30s ", $tinfo->{'name'}; } sub mtr_report_test_skipped ($) { @@ -122,13 +123,13 @@ sub mtr_report_test_failed ($) { # we should write out into $::path_timefile when the error occurs. if ( -f $::path_timefile ) { - print "Errors are (from $::path_timefile) :\n"; + print "\nErrors are (from $::path_timefile) :\n"; print mtr_fromfile($::path_timefile); # FIXME print_file() instead print "\n(the last lines may be the most important ones)\n"; } else { - print "Unexpected termination, probably when starting mysqld\n"; + print "\nUnexpected termination, probably when starting mysqld\n"; } } @@ -256,11 +257,11 @@ sub mtr_print_header () { print "\n"; if ( $::opt_timer ) { - print "TEST RESULT TIME (ms)\n"; + print "TEST RESULT TIME (ms)\n"; } else { - print "TEST RESULT\n"; + print "TEST RESULT\n"; } mtr_print_line(); print "\n"; @@ -286,6 +287,11 @@ sub mtr_error (@) { mtr_exit(1); } +sub mtr_child_error (@) { + print STDERR "mysql-test-run: *** ERROR(child): ",join(" ", @_),"\n"; + exit(1); +} + sub mtr_debug (@) { if ( $::opt_script_debug ) { diff --git a/mysql-test/my_manage.c b/mysql-test/my_manage.c index 88e68dfc27e..919d3bd0529 100644 --- a/mysql-test/my_manage.c +++ b/mysql-test/my_manage.c @@ -230,7 +230,10 @@ int wait_for_server_start(char *bin_dir __attribute__((unused)), char *user, char *password, int port,char *tmp_dir) { arg_list_t al; - int err= 0, i; + int err= 0; +#ifndef __WIN__ + int i; +#endif char trash[FN_REFLEN]; /* mysqladmin file */ diff --git a/mysql-test/mysql-stress-test.pl b/mysql-test/mysql-stress-test.pl new file mode 100755 index 00000000000..899dd06a746 --- /dev/null +++ b/mysql-test/mysql-stress-test.pl @@ -0,0 +1,1148 @@ +#!/usr/bin/perl +# ====================================================================== +# MySQL server stress test system +# ====================================================================== +# +########################################################################## +# +# SCENARIOS AND REQUIREMENTS +# +# The system should perform stress testing of MySQL server with +# following requirements and basic scenarios: +# +# Basic requirements: +# +# Design of stress script should allow one: +# +# - to use for stress testing mysqltest binary as test engine +# - to use for stress testing both regular test suite and any +# additional test suites (e.g. mysql-test-extra-5.0) +# - to specify files with lists of tests both for initialization of +# stress db and for further testing itself +# - to define number of threads that will be concurrently used in testing +# - to define limitations for test run. e.g. number of tests or loops +# for execution or duration of testing, delay between test executions, etc. +# - to get readable log file which can be used for identification of +# errors arose during testing +# +# Basic scenarios: +# +# * It should be possible to run stress script in standalone mode +# which will allow to create various scenarios of stress workloads: +# +# simple ones: +# +# box #1: +# - one instance of script with list of tests #1 +# +# and more advanced ones: +# +# box #1: +# - one instance of script with list of tests #1 +# - another instance of script with list of tests #2 +# box #2: +# - one instance of script with list of tests #3 +# - another instance of script with list of tests #4 +# that will recreate whole database to back it to clean +# state +# +# One kind of such complex scenarios maybe continued testing +# when we want to run stress tests from many boxes with various +# lists of tests that will last very long time. And in such case +# we need some wrapper for MySQL server that will restart it in +# case of crashes. +# +# * It should be possible to run stress script in ad-hoc mode from +# shell or perl versions of mysql-test-run. This allows developers +# to reproduce and debug errors that was found in continued stress +# testing +# +######################################################################## + +use Config; + +if (!defined($Config{useithreads})) +{ + die < {mtime => 0, data => []}, + initdb => {mtime => 0, data => []}); + +# Error codes and sub-strings with corresponding severity +# +# S1 - Critical errors - cause immediately abort of testing. These errors +# could be caused by server crash or impossibility +# of test execution +# +# S2 - Serious errors - these errors are bugs for sure as it knowns that +# they shouldn't appear during stress testing +# +# S3 - Non-seriuos errros - these errors could be caused by fact that +# we execute simultaneously statements that +# affect tests executed by other threads + +%error_strings = ( 'Failed in mysql_real_connect()' => S1, + 'not found (Errcode: 2)' => S1 ); + +%error_codes = ( 1012 => S2, 1015 => S2, 1021 => S2, + 1027 => S2, 1037 => S2, 1038 => S2, + 1039 => S2, 1040 => S2, 1046 => S2, + 1180 => S2, 1181 => S2, 1203 => S2, + 1205 => S2, 1206 => S2, 1207 => S2, + 1223 => S2, 2013 => S1); + +share(%test_counters); +%test_counters=( loop_count => 0, test_count=>0); + +share($exiting); +$exiting=0; + +share($test_counters_lock); +$test_counters_lock=0; +share($log_file_lock); +$log_file_lock=0; + +$SIG{INT}= \&sig_INT_handler; +$SIG{TERM}= \&sig_TERM_handler; + + +GetOptions("server-host=s", "server-logs-dir=s", "server-port=s", + "server-socket=s", "server-user=s", "server-password=s", + "server-database=s", + "stress-suite-basedir=s", "suite=s", "stress-init-file:s", + "stress-tests-file:s", "stress-basedir=s", "stress-mode=s", + "stress-datadir=s", + "threads=s", "sleep-time=s", "loop-count=i", "test-count=i", + "test-duration=i", "test-suffix=s", "check-tests-file", + "verbose", "log-error-details", "cleanup", "mysqltest=s", + "abort-on-error", "help") || usage(); + +usage() if ($opt_help); + +#$opt_abort_on_error=1; + +$test_dirname=get_timestamp(); +$test_dirname.="-$opt_test_suffix" if ($opt_test_suffix ne ''); + +print <rel2abs($opt_stress_basedir); +$opt_stress_suite_basedir=File::Spec->rel2abs($opt_stress_suite_basedir); +$opt_server_logs_dir=File::Spec->rel2abs($opt_server_logs_dir); + +if ($opt_stress_datadir ne '') +{ + $opt_stress_datadir=File::Spec->rel2abs($opt_stress_datadir); +} + +if (! -d "$opt_stress_basedir") +{ + die <catdir($opt_server_logs_dir, $test_dirname), 0, 0755); + #Define filename of global session log file + $stress_log_file=File::Spec->catfile($opt_server_logs_dir, $test_dirname, + "mysql-stress-test.log"); +} + +if ($opt_suite ne '' && $opt_suite ne 'main' && $opt_suite ne 'default') +{ + $test_suite_dir=File::Spec->catdir($opt_stress_suite_basedir, "suite", $opt_suite); +} +else +{ + $test_suite_dir= $opt_stress_suite_basedir; +} + +if (!-d $test_suite_dir) +{ + die <catdir($test_suite_dir,'t'); +$test_suite_r_path=File::Spec->catdir($test_suite_dir,'r'); + +foreach my $suite_dir ($test_suite_t_path, $test_suite_r_path) +{ + if (!-d $suite_dir) + { + die <catdir($opt_stress_basedir,'t'); +$test_r_path=File::Spec->catdir($opt_stress_basedir,'r'); + +foreach $test_dir ($test_t_path, $test_r_path) +{ + if (-d $test_dir) + { + if ($opt_cleanup) + { + #Delete existing 't', 'r', 'r/*' subfolders in $stress_basedir + rmtree("$test_dir", 0, 0); + print "Cleanup $test_dir\n"; + } + else + { + die <{filename}= File::Spec->catfile($opt_stress_suite_basedir, + "testslist_client.txt"); + } + else + { + $tests_files{client}->{filename}= $opt_stress_tests_file; + } + + if (!-f $tests_files{client}->{filename}) + { + die <{filename}' with list of tests not exists. +Please ensure that this file exists, readable or specify another one with +--stress-tests-file option. + +EOF + } +} + +if (defined($opt_stress_init_file)) +{ + if ($opt_stress_init_file eq '') + { + #Default location of file with set of tests for current test run + $tests_files{initdb}->{filename}= File::Spec->catfile($opt_stress_suite_basedir, + "testslist_initdb.txt"); + } + else + { + $tests_files{initdb}->{filename}= $opt_stress_init_file; + } + + if (!-f $tests_files{initdb}->{filename}) + { + die <{filename}' with list of tests for initialization of database +for stress test not exists. +Please ensure that this file exists, readable or specify another one with +--stress-init-file option. + +EOF + } +} + +if ($opt_stress_mode !~ /^(random|seq)$/) +{ + die <); + close(TEST); + print "FOUND MYSQLTEST BINARY: ", $mysqltest_version,"\n"; +} +else +{ + die <\©_test_files, bydepth=>1}, "$test_suite_t_path"); + print "Done\n"; + + #$test_r_path/r0 dir reserved for initdb + $count_start= defined($opt_stress_init_file) ? 0 : 1; + + our $r_folder=''; + print "\nCreating 'r' folder and copying Protocol files to each 'r#' sub-folder..."; + for($count=$count_start; $count <= $opt_threads; $count++) + { + $r_folder = File::Spec->catdir($test_r_path, "r".$count); + mkpath("$r_folder", 0, 0777); + + find(\©_result_files,"$test_suite_r_path"); + } + print "Done\n\n"; +} + +if (defined($opt_stress_init_file)) +{ + print < 1, test_count => undef); + + #Read list of tests from $opt_stress_init_file + read_tests_names($tests_files{initdb}); + test_loop($client_ip, 0, 'seq', $tests_files{initdb}); + #print Dumper($tests_files{initdb}),"\n"; + print <{filename} file. + +EOF +} + +if (defined($opt_stress_tests_file)) +{ + print < 0, test_count=>0); + %limits=(loop_count => $opt_loop_count, test_count => $opt_test_count); + + if (($opt_loop_count && $opt_threads > $opt_loop_count) || + ($opt_test_count && $opt_threads > $opt_test_count)) + { + warn <create("test_loop", $client_ip, $id, + $opt_stress_mode, $tests_files{client}); + + print "main: Thread ID $id TID ",$thrd[$id]->tid," started\n"; + select(undef, undef, undef, 0.5); + } + + if ($opt_test_duration) + { + sleep($opt_test_duration); + kill INT, $$; #Interrupt child threads + } + + #Let other threads to process INT signal + sleep(1); + + for ($id=1; $id<=$opt_threads;$id++) + { + if (defined($thrd[$id])) + { + $thrd[$id]->join(); + } + } + print "EXIT\n"; +} + +sub test_init +{ + my ($env)=@_; + + $env->{session_id}=$env->{ip}."_".$env->{thread_id}; + $env->{r_folder}='r'.$env->{thread_id}; + $env->{screen_logs}=File::Spec->catdir($opt_server_logs_dir, $test_dirname, + "screen_logs", $env->{session_id}); + $env->{reject_logs}=File::Spec->catdir($opt_server_logs_dir, $test_dirname, + "reject_logs", $env->{session_id}); + + mkpath($env->{screen_logs}, 0, 0755) unless (-d $env->{screen_logs}); + mkpath($env->{reject_logs}, 0, 0755) unless (-d $env->{reject_logs}); + + $env->{session_log}= File::Spec->catfile($env->{screen_logs}, $env->{session_id}.".log"); +} + +sub test_execute +{ + my $env= shift; + my $test_name= shift; + + my $g_start= ""; + my $g_end= ""; + my $mysqltest_cmd= ""; + my @mysqltest_test_args=(); + my @stderr=(); + + #Get time stamp + $g_start = get_timestamp(); + $env->{errors}={}; + @{$env->{test_status}}=(); + + my $test_file= $test_name.".test"; + my $result_file= $test_name.".result"; + my $reject_file = $test_name.'.reject'; + my $output_file = $env->{session_id}.'_'.$test_name.'_'.$g_start."_".$env->{test_count}.'.txt'; + + my $test_filename = File::Spec->catfile($test_t_path, $test_file); + my $result_filename = File::Spec->catdir($test_r_path, $env->{r_folder}, $result_file); + my $reject_filename = File::Spec->catdir($test_r_path, $env->{r_folder}, $reject_file); + my $output_filename = File::Spec->catfile($env->{screen_logs}, $output_file); + + + push @mysqltest_test_args, "--basedir=$opt_stress_suite_basedir/", + "--tmpdir=$opt_stress_basedir", + "-x $test_filename", + "-R $result_filename", + "2>$output_filename"; + + $cmd= "$opt_mysqltest --no-defaults ".join(" ", @mysqltest_args)." ". + join(" ", @mysqltest_test_args); + + system($cmd); + + $exit_value = $? >> 8; + $signal_num = $? & 127; + $dumped_core = $? & 128; + + my $tid= threads->self->tid; + + if (-s $output_filename > 0) + { + #Read stderr for further analysis + open (STDERR_LOG, $output_filename) or + warn "Can't open file $output_filename"; + @stderr=; + close(STDERR_LOG); + + if ($opt_verbose) + { + $session_debug_file="$opt_stress_basedir/error$tid.txt"; + + stress_log($session_debug_file, + "Something wrong happened during execution of this command line:"); + stress_log($session_debug_file, "MYSQLTEST CMD - $cmd"); + stress_log($session_debug_file, "STDERR:".join("",@stderr)); + + stress_log($session_debug_file, "EXIT STATUS:\n1. EXIT: $exit_value \n". + "2. SIGNAL: $signal_num\n". + "3. CORE: $dumped_core\n"); + } + } + + #If something wrong trying to analyse stderr + if ($exit_value || $signal_num) + { + if (@stderr) + { + foreach my $line (@stderr) + { + #FIXME: we should handle case when for one sub-string/code + # we have several different error messages + # Now for both codes/substrings we assume that + # first found message will represent error + + #Check line for error codes + if (($err_msg, $err_code)= $line=~/failed: ((\d+):.+?$)/) + { + if (!exists($error_codes{$err_code})) + { + $severity="S3"; + $err_code=0; + } + else + { + $severity=$error_codes{$err_code}; + } + + if (!exists($env->{errors}->{$severity}->{$err_code})) + { + $env->{errors}->{$severity}->{$err_code}=[0, $err_msg]; + } + $env->{errors}->{$severity}->{$err_code}->[0]++; + $env->{errors}->{$severity}->{total}++; + } + + #Check line for error patterns + foreach $err_string (keys %error_strings) + { + $pattern= quotemeta $err_string; + if ($line =~ /$pattern/i) + { + my $severity= $error_strings{$err_string}; + if (!exists($env->{errors}->{$severity}->{$err_string})) + { + $env->{errors}->{$severity}->{$err_string}=[0, $line]; + } + $env->{errors}->{$severity}->{$err_string}->[0]++; + $env->{errors}->{$severity}->{total}++; + } + } + } + } + else + { + $env->{errors}->{S3}->{'Unknown error'}= + [1,"Unknown error. Nothing was output to STDERR"]; + $env->{errors}->{S3}->{total}=1; + } + } + + # + #FIXME: Here we can perform further analysis of recognized + # error codes + # + + foreach my $severity (sort {$a cmp $b} keys %{$env->{errors}}) + { + my $total=$env->{errors}->{$severity}->{total}; + if ($total) + { + push @{$env->{test_status}}, "Severity $severity: $total"; + $env->{errors}->{total}=+$total; + } + } + + #FIXME: Should we take into account $exit_value here? + # Now we assume that all stringified errors(i.e. errors without + # error codes) which are not exist in %error_string structure + # are OK + if (!$env->{errors}->{total}) + { + push @{$env->{test_status}},"No Errors. Test Passed OK"; + } + + log_session_errors($env, $test_file); + + if (!$exiting && ($signal_num == 2 || $signal_num == 15 || + ($opt_abort_on_error && $env->{errors}->{S1} > 0))) + { + #mysqltest was interrupted with INT or TERM signals or test was + #ran with --abort-on-error option and we got errors with severity S1 + #so we assume that we should cancel testing and exit + $exiting=1; + print STDERR<{reject_logs}, $reject_filename, $reject_file); + } + + if (-e $output_filename) + { + move_to_logs($env->{screen_logs}, $output_filename, $output_file); + } + +} + +sub test_loop +{ + my %client_env=(); + my $test_name=""; + + # KEY for session identification: IP-THREAD_ID + $client_env{ip} = shift; + $client_env{thread_id} = shift; + + $client_env{mode} = shift; + $client_env{tests_file}=shift; + + $client_env{test_seq_idx}=0; + + #Initialize session variables + test_init(\%client_env); + +LOOP: + + while(!$exiting) + { + if ($opt_check_tests_file) + { + #Check if tests_file was modified and reread it in this case + read_tests_names($client_env{tests_file}, 0); + } + + { + lock($test_counters_lock); + + if (($limits{loop_count} && $limits{loop_count} <= $test_counters{loop_count}*1) || + ($limits{test_count} && $limits{test_count} <= $test_counters{test_count}*1) ) + { + $exiting=1; + next LOOP; + } + } + + #Get random file name + if (($test_name = get_test(\%client_env)) ne '') + { + { + lock($test_counters_lock); + + #Save current counters values + $client_env{loop_count}=$test_counters{loop_count}; + $client_env{test_count}=$test_counters{test_count}; + } + #Run test and analyze results + test_execute(\%client_env, $test_name); + + print "test_loop[".$limits{loop_count}.":". + $limits{test_count}." ". + $client_env{loop_count}.":". + $client_env{test_count}."]:". + " TID ".$client_env{thread_id}. + " test: '$test_name' ". + " Errors: ".join(" ",@{$client_env{test_status}}),"\n"; + print "\n"; + } + + sleep($opt_sleep_time) if($opt_sleep_time); + + } +} + +sub move_to_logs ($$$) +{ + my $path_to_logs = shift; + my $src_file = shift; + my $random_filename = shift; + + my $dst_file = File::Spec->catfile($path_to_logs, $random_filename); + + move ($src_file, $dst_file) or warn<catfile($test_t_path, $test_filename); + + copy($src_file, $dst_file) or die "ERROR: copy_test_files: File cannot be copied. $!"; + } + } +} + +sub copy_result_files () +{ + if (/\.result$/) + { + $src_file = $File::Find::name; + + if ($File::Find::topdir eq $File::Find::dir && $src_file !~ /SCCS/) + { + $result_filename = basename($src_file) ; + $dst_file = File::Spec->catfile($r_folder, $result_filename); + + copy($src_file, $dst_file) or die "ERROR: copy_result_files: File cannot be copied. $!"; + } + } +} + +sub get_timestamp +{ + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$ydat,$isdst) = localtime(); + + return sprintf("%04d%02d%02d%02d%02d%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec); +} + +sub read_tests_names +{ + my $tests_file = shift; + my $force_load = shift; + + if ($force_load || ( (stat($tests_file->{filename}))[9] != $tests_file->{mtime}) ) + { + open (TEST, $tests_file->{filename}) || die ("Could not open file <". + $tests_file->{filename}."> $!"); + @{$tests_file->{data}}= grep {!/^[#\r\n]|^$/} map { s/[\r\n]//g; $_ } ; + + close (TEST); + $tests_file->{mtime}=(stat(_))[9]; + } +} + +sub get_random_test +{ + my $envt=shift; + my $tests= $envt->{tests_file}->{data}; + + my $random = int(rand(@{$tests})); + my $test = $tests->[$random]; + + return $test; +} + +sub get_next_test +{ + my $envt=shift; + my $test; + + if (@{$envt->{tests_file}->{data}}) + { + $test=${$envt->{tests_file}->{data}}[$envt->{test_seq_idx}]; + $envt->{test_seq_idx}++; + } + + #If we reach bound of array, reset seq index and increment loop counter + if ($envt->{test_seq_idx} == scalar(@{$envt->{tests_file}->{data}})) + { + $envt->{test_seq_idx}=0; + { + lock($test_counters_lock); + $test_counters{loop_count}++; + } + } + + return $test; +} + +sub get_test +{ + my $envt=shift; + + { + lock($test_counters_lock); + $test_counters{test_count}++; + } + + if ($envt->{mode} eq 'seq') + { + return get_next_test($envt); + } + elsif ($envt->{mode} eq 'random') + { + return get_random_test($envt); + } +} + +sub stress_log +{ + my ($log_file, $line)=@_; + + { + open(SLOG,">>$log_file") or warn "Error during opening log file $log_file"; + print SLOG $line,"\n"; + close(SLOG); + } +} + +sub log_session_errors +{ + my ($env, $test_name) = @_; + my $line=''; + + { + lock ($log_file_lock); + + #header in the begining of log file + if (!-e $stress_log_file) + { + stress_log($stress_log_file, + "TestID TID Suite TestFileName Found Errors"); + stress_log($stress_log_file, + "======================================================="); + } + + $line=sprintf('%6d %3d %10s %20s %s', $env->{test_count}, threads->self->tid, + $opt_suite, $test_name, + join(",", @{$env->{test_status}})); + + stress_log($stress_log_file, $line); + #stress_log_with_lock($stress_log_file, "\n"); + + if ($opt_log_error_details) + { + foreach $severity (sort {$a cmp $b} keys %{$env->{errors}}) + { + stress_log($stress_log_file, ""); + foreach $error (keys %{$env->{errors}->{$severity}}) + { + if ($error ne 'total') + { + stress_log($stress_log_file, "$severity: Count:". + $env->{errors}->{$severity}->{$error}->[0]. + " Error:". $env->{errors}->{$severity}->{$error}->[1]); + } + } + } + } + } +} + +sub sig_INT_handler +{ + $SIG{INT}= \&sig_INT_handler; + $exiting=1; + print STDERR "$$: Got INT signal-------------------------------------------\n"; + +} + +sub sig_TERM_handler +{ + $SIG{TERM}= \&sig_TERM_handler; + $exiting=1; + print STDERR "$$: Got TERM signal\n"; +} + +sub usage +{ + print < --stress-suite-basedir= --server-logs-dir= + +--server-host +--server-port +--server-socket +--server-user +--server-password +--server-logs-dir + Directory where all clients session logs will be stored. Usually + this is shared directory associated with server that used + in testing + + Required option. + +--stress-suite-basedir= + Directory that has r/ t/ subfolders with test/result files + which will be used for testing. Also by default we are looking + in this directory for 'stress-tests.txt' file which contains + list of tests. It is possible to specify other location of this + file with --stress-tests-file option. + + Required option. + +--stress-basedir= + Working directory for this test run. This directory will be used + as temporary location for results tracking during testing + + Required option. + +--stress-datadir= + Location of data files used which will be used in testing. + By default we search for these files in /data where dir + is value of --stress-suite-basedir option. + +--stress-init-file[=/path/to/file with tests for initialization of stress db] + Using of this option allows to perform initialization of database + by execution of test files. List of tests will be taken either from + specified file or if it omited from default file 'stress-init.txt' + located in <--stress-suite-basedir/--suite> dir + +--stress-tests-file[=/path/to/file with tests] + Using of this option allows to run stress test itself. Tests for testing + will be taken either from specified file or if it omited from default + file 'stress-tests.txt' located in <--stress-suite-basedir/--suite> dir + +--stress-mode= [random|seq] + There are two possible modes which affect order of selecting tests + from the list: + - in random mode tests will be selected in random order + - in seq mode each thread will execute tests in the loop one by one as + they specified in the list file. + +--sleep-time=