diff options
228 files changed, 6531 insertions, 1711 deletions
diff --git a/.bzrignore b/.bzrignore index 5e6c7509354..555199fd166 100644 --- a/.bzrignore +++ b/.bzrignore @@ -671,6 +671,7 @@ mysql-test/*.ds? mysql-test/*.vcproj mysql-test/gmon.out mysql-test/install_test_db +mysql-test/mtr mysql-test/mysql-test-run mysql-test/mysql-test-run.log mysql-test/mysql_test_run_new @@ -913,6 +914,7 @@ ndb/src/common/mgmcommon/printConfig/*.d ndb/src/common/portlib/libportlib.dsp ndb/src/common/transporter/libtransporter.dsp ndb/src/common/util/libgeneral.dsp +ndb/src/common/util/testBitmask.cpp ndb/src/cw/cpcd/ndb_cpcd ndb/src/dummy.cpp ndb/src/kernel/blocks/backup/libbackup.dsp @@ -1138,6 +1140,7 @@ sql/*.ds? sql/*.vcproj sql/.gdbinit sql/client.c +sql/f.c sql/gen_lex_hash sql/gmon.out sql/lex_hash.h @@ -1296,4 +1299,3 @@ vio/viotest-sslconnect.cpp vio/viotest.cpp zlib/*.ds? zlib/*.vcproj -ndb/src/common/util/testBitmask.cpp diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 57061f3dbff..8055f337821 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -1,6 +1,6 @@ #!/bin/sh -if ! test -f sql/mysqld.cc +if test ! -f sql/mysqld.cc then echo "You must run this script from the MySQL top-level directory" exit 1 @@ -122,12 +122,6 @@ fi # (returns 0 if finds lines) if ccache -V > /dev/null 2>&1 then - if ! (echo "$CC" | grep "ccache" > /dev/null) - then - CC="ccache $CC" - fi - if ! (echo "$CXX" | grep "ccache" > /dev/null) - then - CXX="ccache $CXX" - fi + echo "$CC" | grep "ccache" > /dev/null || CC="ccache $CC" + echo "$CXX" | grep "ccache" > /dev/null || CXX="ccache $CXX" fi diff --git a/BUILD/check-cpu b/BUILD/check-cpu index d12a690eaa8..fb69fd0acae 100755 --- a/BUILD/check-cpu +++ b/BUILD/check-cpu @@ -3,213 +3,216 @@ # Check cpu of current machine and find the # best compiler optimization flags for gcc # -# -if test -r /proc/cpuinfo ; then - # on Linux (and others?) we can get detailed CPU information out of /proc - cpuinfo="cat /proc/cpuinfo" +check_cpu () { + if test -r /proc/cpuinfo ; then + # on Linux (and others?) we can get detailed CPU information out of /proc + cpuinfo="cat /proc/cpuinfo" - # detect CPU family - cpu_family=`$cpuinfo | grep 'family' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` - if test -z "$cpu_family" ; then - cpu_family=`$cpuinfo | grep 'cpu' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` - fi + # detect CPU family + cpu_family=`$cpuinfo | grep 'family' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` + if test -z "$cpu_family" ; then + cpu_family=`$cpuinfo | grep 'cpu' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` + fi - # detect CPU vendor and model - cpu_vendor=`$cpuinfo | grep 'vendor_id' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` - model_name=`$cpuinfo | grep 'model name' | cut -d ':' -f 2 | head -1` - if test -z "$model_name" ; then - model_name=`$cpuinfo | grep 'cpu model' | cut -d ':' -f 2 | head -1` - fi + # detect CPU vendor and model + cpu_vendor=`$cpuinfo | grep 'vendor_id' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` + model_name=`$cpuinfo | grep 'model name' | cut -d ':' -f 2 | head -1` + if test -z "$model_name" ; then + model_name=`$cpuinfo | grep 'cpu model' | cut -d ':' -f 2 | head -1` + fi + + # fallback: get CPU model from uname output + if test -z "$model_name" ; then + model_name=`uname -m` + fi - # fallback: get CPU model from uname output - if test -z "$model_name" ; then - model_name=`uname -m` + # parse CPU flags + for flag in `$cpuinfo | grep '^flags' | sed -e 's/^flags.*: //'`; do + eval cpu_flag_$flag=yes + done + else + # Fallback when there is no /proc/cpuinfo + case "`uname -s`" in + FreeBSD|OpenBSD) + cpu_family=`uname -m`; + model_name=`sysctl -n hw.model` + ;; + Darwin) + cpu_family=`uname -p` + model_name=`machine` + ;; + *) + cpu_family=`uname -m`; + model_name=`uname -p`; + ;; + esac fi - # parse CPU flags - for flag in `$cpuinfo | grep '^flags' | sed -e 's/^flags.*: //'`; do - eval cpu_flag_$flag=yes - done -else - # Fallback when there is no /proc/cpuinfo - case "`uname -s`" in - FreeBSD|OpenBSD) - cpu_family=`uname -m`; - model_name=`sysctl -n hw.model` - ;; - Darwin) - cpu_family=`uname -p` - model_name=`machine` + # detect CPU shortname as used by gcc options + # this list is not complete, feel free to add further entries + cpu_arg="" + case "$cpu_family--$model_name" in + # DEC Alpha + Alpha*EV6*) + cpu_arg="ev6"; ;; - *) - cpu_family=`uname -m`; - model_name=`uname -p`; + + # Intel ia32 + *Xeon*) + # a Xeon is just another pentium4 ... + # ... unless it has the "lm" (long-mode) flag set, + # in that case it's a Xeon with EM64T support + if [ -z "$cpu_flag_lm" ]; then + cpu_arg="pentium4"; + else + cpu_arg="nocona"; + fi ;; - esac -fi - -# detect CPU shortname as used by gcc options -# this list is not complete, feel free to add further entries -cpu_arg="" -case "$cpu_family--$model_name" in - # DEC Alpha - Alpha*EV6*) - cpu_arg="ev6"; + *Pentium*4*Mobile*) + cpu_arg="pentium4m"; ;; - - # Intel ia32 - *Xeon*) - # a Xeon is just another pentium4 ... - # ... unless it has the "lm" (long-mode) flag set, - # in that case it's a Xeon with EM64T support - if [ -z "$cpu_flag_lm" ]; then + *Pentium*4*) cpu_arg="pentium4"; - else - cpu_arg="nocona"; - fi - ;; - *Pentium*4*Mobile*) - cpu_arg="pentium4m"; - ;; - *Pentium*4*) - cpu_arg="pentium4"; - ;; - *Pentium*III*Mobile*) - cpu_arg="pentium3m"; - ;; - *Pentium*III*) - cpu_arg="pentium3"; - ;; - *Pentium*M*pro*) - cpu_arg="pentium-m"; - ;; - *Athlon*64*) - cpu_arg="athlon64"; - ;; - *Athlon*) - cpu_arg="athlon"; + ;; + *Pentium*III*Mobile*) + cpu_arg="pentium3m"; ;; - *Opteron*) - cpu_arg="opteron"; + *Pentium*III*) + cpu_arg="pentium3"; ;; - # MacOSX / Intel - *i386*i486*) - cpu_arg="pentium-m"; + *Pentium*M*pro*) + cpu_arg="pentium-m"; ;; + *Athlon*64*) + cpu_arg="athlon64"; + ;; + *Athlon*) + cpu_arg="athlon"; + ;; + *Opteron*) + cpu_arg="opteron"; + ;; + # MacOSX / Intel + *i386*i486*) + cpu_arg="pentium-m"; + ;; - # Intel ia64 - *Itanium*) - # Don't need to set any flags for itanium(at the moment) - cpu_arg=""; - ;; + # Intel ia64 + *Itanium*) + # Don't need to set any flags for itanium(at the moment) + cpu_arg=""; + ;; - # - *ppc*) - cpu_arg='powerpc' - ;; - - *powerpc*) - cpu_arg='powerpc' - ;; + # + *ppc*) + cpu_arg='powerpc' + ;; + + *powerpc*) + cpu_arg='powerpc' + ;; - # unknown - *) - cpu_arg=""; - ;; -esac - - -if test -z "$cpu_arg"; then - echo "BUILD/check-cpu: Oops, could not find out what kind of cpu this machine is using." - check_cpu_cflags="" - return -fi - -# different compiler versions have different option names -# for CPU specific command line options -if test -z "$CC" ; then - cc="gcc"; -else - cc=$CC -fi - -cc_ver=`$cc --version | sed 1q` -cc_verno=`echo $cc_ver | sed -e 's/^.*gcc/gcc/g; s/[^0-9. ]//g; s/^ *//g; s/ .*//g'` - -case "$cc_ver--$cc_verno" in - *GCC*) - # different gcc backends (and versions) have different CPU flags - case `gcc -dumpmachine` in - i?86-*) - case "$cc_verno" in - 3.4*|3.5*|4.*) - check_cpu_args='-mtune=$cpu_arg -march=$cpu_arg' - ;; - *) - check_cpu_args='-mcpu=$cpu_arg -march=$cpu_arg' - ;; - esac - ;; - ppc-*) - check_cpu_args='-mcpu=$cpu_arg -mtune=$cpu_arg' - ;; - x86_64-*) - check_cpu_args='-mtune=$cpu_arg' - ;; - *) - check_cpu_cflags="" - return - ;; - esac - ;; - 2.95.*) - # GCC 2.95 doesn't expose its name in --version output - check_cpu_args='-m$cpu_arg' - ;; - *) + # unknown + *) + cpu_arg=""; + ;; + esac + + + if test -z "$cpu_arg"; then + echo "BUILD/check-cpu: Oops, could not find out what kind of cpu this machine is using." >&2 check_cpu_cflags="" return - ;; -esac - -# now we check whether the compiler really understands the cpu type -touch __test.c - -while [ "$cpu_arg" ] ; do - echo -n testing $cpu_arg "... " - - # compile check - check_cpu_cflags=`eval echo $check_cpu_args` - if $cc -c $check_cpu_cflags __test.c 2>/dev/null; then - echo ok - break; fi - echo failed - check_cpu_cflags="" + # different compiler versions have different option names + # for CPU specific command line options + if test -z "$CC" ; then + cc="gcc"; + else + cc=$CC + fi - # if compile failed: check whether it supports a predecessor of this CPU - # this list is not complete, feel free to add further entries - case "$cpu_arg" in - # Intel ia32 - nocona) cpu_arg=pentium4 ;; - prescott) cpu_arg=pentium4 ;; - pentium4m) cpu_arg=pentium4 ;; - pentium4) cpu_arg=pentium3 ;; - pentium3m) cpu_arg=pentium3 ;; - pentium3) cpu_arg=pentium2 ;; - pentium2) cpu_arg=pentiumpro ;; - pentiumpro) cpu_arg=pentium ;; - pentium) cpu_arg=i486 ;; - i486) cpu_arg=i386 ;; - - # power / powerPC - 7450) cpu_arg=7400 ;; - - *) cpu_arg="" ;; + cc_ver=`$cc --version | sed 1q` + cc_verno=`echo $cc_ver | sed -e 's/^.*gcc/gcc/g; s/[^0-9. ]//g; s/^ *//g; s/ .*//g'` + + case "$cc_ver--$cc_verno" in + *GCC*) + # different gcc backends (and versions) have different CPU flags + case `gcc -dumpmachine` in + i?86-*) + case "$cc_verno" in + 3.4*|3.5*|4.*) + check_cpu_args='-mtune=$cpu_arg -march=$cpu_arg' + ;; + *) + check_cpu_args='-mcpu=$cpu_arg -march=$cpu_arg' + ;; + esac + ;; + ppc-*) + check_cpu_args='-mcpu=$cpu_arg -mtune=$cpu_arg' + ;; + x86_64-*) + check_cpu_args='-mtune=$cpu_arg' + ;; + *) + check_cpu_cflags="" + return + ;; + esac + ;; + 2.95.*) + # GCC 2.95 doesn't expose its name in --version output + check_cpu_args='-m$cpu_arg' + ;; + *) + check_cpu_cflags="" + return + ;; esac -done -rm __test.* + # now we check whether the compiler really understands the cpu type + touch __test.c + + while [ "$cpu_arg" ] ; do + # FIXME: echo -n isn't portable - see contortions autoconf goes through + echo -n testing $cpu_arg "... " >&2 + + # compile check + check_cpu_cflags=`eval echo $check_cpu_args` + if $cc -c $check_cpu_cflags __test.c 2>/dev/null; then + echo ok >&2 + break; + fi + + echo failed >&2 + check_cpu_cflags="" + + # if compile failed: check whether it supports a predecessor of this CPU + # this list is not complete, feel free to add further entries + case "$cpu_arg" in + # Intel ia32 + nocona) cpu_arg=pentium4 ;; + prescott) cpu_arg=pentium4 ;; + pentium4m) cpu_arg=pentium4 ;; + pentium4) cpu_arg=pentium3 ;; + pentium3m) cpu_arg=pentium3 ;; + pentium3) cpu_arg=pentium2 ;; + pentium2) cpu_arg=pentiumpro ;; + pentiumpro) cpu_arg=pentium ;; + pentium) cpu_arg=i486 ;; + i486) cpu_arg=i386 ;; + + # power / powerPC + 7450) cpu_arg=7400 ;; + + *) cpu_arg="" ;; + esac + done + + rm __test.* +} +check_cpu diff --git a/BUILD/compile-ndb-autotest b/BUILD/compile-ndb-autotest new file mode 100755 index 00000000000..be28cc28346 --- /dev/null +++ b/BUILD/compile-ndb-autotest @@ -0,0 +1,19 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_configs="$max_configs --with-ndb-test --with-ndb-ccflags='-DERROR_INSERT'" +if [ "$full_debug" ] +then + extra_flags="$debug_cflags" + c_warnings="$c_warnings $debug_extra_warnings" + cxx_warnings="$cxx_warnings $debug_extra_warnings" + extra_configs="$debug_configs $extra_configs" +else + extra_flags="$fast_cflags" +fi + +extra_flags="$extra_flags $max_cflags -g" + +. "$path/FINISH.sh" diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed index 8b90deae622..d4d681937a2 100644 --- a/BitKeeper/etc/collapsed +++ b/BitKeeper/etc/collapsed @@ -1 +1,4 @@ 44d03f27qNdqJmARzBoP3Is_cN5e0w +44ec850ac2k4y2Omgr92GiWPBAVKGQ +44edb86b1iE5knJ97MbliK_3lCiAXA +44f33f3aj5KW5qweQeekY1LU0E9ZCg diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 00000000000..fd780ec6a13 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,132 @@ +PROJECT(MySql) + +# This reads user configuration, generated by configure.js. +INCLUDE(win/configure.data) + +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/mysql_version.h.in + ${CMAKE_SOURCE_DIR}/include/mysql_version.h @ONLY) + +# Set standard options +ADD_DEFINITIONS(-D WITH_MYISAM_STORAGE_ENGINE) +ADD_DEFINITIONS(-D CMAKE_BUILD) +ADD_DEFINITIONS(-D HAVE_YASSL) + +SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_myisam_plugin") + + +IF(WITH_ARCHIVE_STORAGE_ENGINE) + ADD_DEFINITIONS(-D HAVE_ARCHIVE_DB) +ENDIF(WITH_ARCHIVE_STORAGE_ENGINE) + +IF (WITH_HEAP_STORAGE_ENGINE) + ADD_DEFINITIONS(-D WITH_HEAP_STORAGE_ENGINE) + SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_heap_plugin") +ENDIF (WITH_HEAP_STORAGE_ENGINE) + +IF (WITH_MYISAMMRG_STORAGE_ENGINE) + ADD_DEFINITIONS(-D WITH_MYISAMMRG_STORAGE_ENGINE) + SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_myisammrg_plugin") +ENDIF (WITH_MYISAMMRG_STORAGE_ENGINE) + +IF(WITH_INNOBASE_STORAGE_ENGINE) + CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/innobase/ib_config.h.in + ${CMAKE_SOURCE_DIR}/innobase/ib_config.h @ONLY) + ADD_DEFINITIONS(-D HAVE_INNOBASE_DB) + ADD_DEFINITIONS(-D WITH_INNOBASE_STORAGE_ENGINE) + SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_innobase_plugin") +ENDIF(WITH_INNOBASE_STORAGE_ENGINE) + +IF(WITH_FEDERATED_STORAGE_ENGINE) + ADD_DEFINITIONS(-D HAVE_FEDERATED_DB) + ADD_DEFINITIONS(-D WITH_FEDERATED_STORAGE_ENGINE) + SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_federated_plugin") +ENDIF(WITH_FEDERATED_STORAGE_ENGINE) + +IF(WITH_BERKELEY_STORAGE_ENGINE) + ADD_DEFINITIONS(-D HAVE_BERKELEY_DB) + ADD_DEFINITIONS(-D WITH_BERKELEY_STORAGE_ENGINE) + SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_berkeley_plugin") +ENDIF(WITH_BERKELEY_STORAGE_ENGINE) + +IF (WITH_BLACKHOLE_STORAGE_ENGINE) + ADD_DEFINITIONS(-D HAVE_BLACKHOLE_DB) +ENDIF (WITH_BLACKHOLE_STORAGE_ENGINE) + +SET(localstatedir "C:\\mysql\\data") +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-huge.cnf.sh + ${CMAKE_SOURCE_DIR}/support-files/my-huge.ini @ONLY) +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-innodb-heavy-4G.cnf.sh + ${CMAKE_SOURCE_DIR}/support-files/my-innodb-heavy-4G.ini @ONLY) +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-large.cnf.sh + ${CMAKE_SOURCE_DIR}/support-files/my-large.ini @ONLY) +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-medium.cnf.sh + ${CMAKE_SOURCE_DIR}/support-files/my-medium.ini @ONLY) +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-small.cnf.sh + ${CMAKE_SOURCE_DIR}/support-files/my-small.ini @ONLY) + +IF(__NT__) + ADD_DEFINITIONS(-D __NT__) +ENDIF(__NT__) +IF(CYBOZU) + ADD_DEFINITIONS(-D CYBOZU) +ENDIF(CYBOZU) + +# in some places we use DBUG_OFF +SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -D DBUG_OFF") +SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D DBUG_OFF") + +IF(CMAKE_GENERATOR MATCHES "Visual Studio 8") + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /wd4996") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /wd4996") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /wd4996") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /wd4996") +ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 8") + +IF(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR + CMAKE_GENERATOR MATCHES "Visual Studio 8") + # replace /MDd with /MTd + STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG_INIT + ${CMAKE_CXX_FLAGS_DEBUG_INIT}) + STRING(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG_INIT + ${CMAKE_C_FLAGS_DEBUG_INIT}) + STRING(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE + ${CMAKE_C_FLAGS_RELEASE}) + STRING(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG + ${CMAKE_C_FLAGS_DEBUG}) + STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE + ${CMAKE_CXX_FLAGS_RELEASE}) + STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG + ${CMAKE_CXX_FLAGS_DEBUG}) + + # remove support for Exception handling + STRING(REPLACE "/GX" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + STRING(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + STRING(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS_INIT + ${CMAKE_CXX_FLAGS_INIT}) + STRING(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS_DEBUG_INIT + ${CMAKE_CXX_FLAGS_DEBUG_INIT}) +ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR + CMAKE_GENERATOR MATCHES "Visual Studio 8") + +ADD_DEFINITIONS("-D_WINDOWS -D__WIN__ -D _CRT_SECURE_NO_DEPRECATE") + +ADD_SUBDIRECTORY(vio) +ADD_SUBDIRECTORY(dbug) +ADD_SUBDIRECTORY(strings) +ADD_SUBDIRECTORY(regex) +ADD_SUBDIRECTORY(mysys) +ADD_SUBDIRECTORY(extra/yassl) +ADD_SUBDIRECTORY(extra/yassl/taocrypt) +ADD_SUBDIRECTORY(extra) +ADD_SUBDIRECTORY(zlib) +ADD_SUBDIRECTORY(heap) +ADD_SUBDIRECTORY(myisam) +ADD_SUBDIRECTORY(myisammrg) +ADD_SUBDIRECTORY(client) +ADD_SUBDIRECTORY(bdb) +ADD_SUBDIRECTORY(innobase) +ADD_SUBDIRECTORY(sql) +ADD_SUBDIRECTORY(sql/examples) +ADD_SUBDIRECTORY(server-tools/instance-manager) +ADD_SUBDIRECTORY(libmysql) +ADD_SUBDIRECTORY(tests) diff --git a/Makefile.am b/Makefile.am index f0784a9baed..d48f0e24966 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,7 +20,7 @@ AUTOMAKE_OPTIONS = foreign # These are built from source in the Docs directory EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \ - README COPYING EXCEPTIONS-CLIENT + README COPYING EXCEPTIONS-CLIENT CMakeLists.txt SUBDIRS = . include @docs_dirs@ @zlib_dir@ @yassl_dir@ \ @readline_topdir@ sql-common \ @thread_dirs@ pstack \ @@ -33,7 +33,7 @@ DIST_SUBDIRS = . include @docs_dirs@ zlib \ @thread_dirs@ pstack \ @sql_union_dirs@ scripts @man_dirs@ tests SSL\ BUILD netware os2 @libmysqld_dirs@ \ - @bench_dirs@ support-files @tools_dirs@ + @bench_dirs@ support-files @tools_dirs@ win # Run these targets before any others, also make part of clean target, # to make sure we create new links after a clean. diff --git a/VC++Files/mysql.sln b/VC++Files/mysql.sln index bd0cae1d5d8..1e3a33b8eb4 100644 --- a/VC++Files/mysql.sln +++ b/VC++Files/mysql.sln @@ -174,7 +174,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqlimport", "client\mysql {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysql_upgrade", "client\mysql_upgrade.vcproj", "{AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysql_upgrade", "client\mysql_upgrade.vcproj", "{AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}" ProjectSection(ProjectDependencies) = postProject {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} {26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB} @@ -990,6 +990,33 @@ Global {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.pro nt.Build.0 = Release|Win32 {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Release.ActiveCfg = Release|Win32 {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Release.Build.0 = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.classic.ActiveCfg = classic|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.classic.Build.0 = classic|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.classic nt.ActiveCfg = classic|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.classic nt.Build.0 = classic|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Debug.ActiveCfg = Debug|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Debug.Build.0 = Debug|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Embedded_Classic.ActiveCfg = classic|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Embedded_Debug.ActiveCfg = Debug|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Embedded_Pro.ActiveCfg = classic|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Embedded_ProGPL.ActiveCfg = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Embedded_Release.ActiveCfg = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Max.ActiveCfg = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Max.Build.0 = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Max nt.ActiveCfg = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Max nt.Build.0 = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.nt.ActiveCfg = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.nt.Build.0 = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.pro.ActiveCfg = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.pro.Build.0 = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.pro gpl.ActiveCfg = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.pro gpl.Build.0 = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.pro gpl nt.ActiveCfg = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.pro gpl nt.Build.0 = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.pro nt.ActiveCfg = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.pro nt.Build.0 = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Release.ActiveCfg = Release|Win32 + {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Release.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.classic.ActiveCfg = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.classic.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.classic nt.ActiveCfg = Release|Win32 diff --git a/bdb/CMakeLists.txt b/bdb/CMakeLists.txt new file mode 100755 index 00000000000..c5dd60852d4 --- /dev/null +++ b/bdb/CMakeLists.txt @@ -0,0 +1,44 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/bdb/build_win32 + ${CMAKE_SOURCE_DIR}/bdb/dbinc + ${CMAKE_SOURCE_DIR}/bdb) + +# BDB needs a number of source files that are auto-generated by the unix +# configure. So to build BDB, it is necessary to copy these over to the Windows +# bitkeeper tree, or to use a source .tar.gz package which already has these +# files. +ADD_LIBRARY(bdb btree/bt_compare.c btree/bt_conv.c btree/bt_curadj.c btree/bt_cursor.c + btree/bt_delete.c btree/bt_method.c btree/bt_open.c btree/bt_put.c btree/bt_rec.c + btree/bt_reclaim.c btree/bt_recno.c btree/bt_rsearch.c btree/bt_search.c + btree/bt_split.c btree/bt_stat.c btree/bt_upgrade.c btree/bt_verify.c btree/btree_auto.c + db/crdel_auto.c db/crdel_rec.c db/db.c db/db_am.c db/db_auto.c common/db_byteorder.c + db/db_cam.c db/db_conv.c db/db_dispatch.c db/db_dup.c common/db_err.c common/db_getlong.c + common/db_idspace.c db/db_iface.c db/db_join.c common/db_log2.c db/db_meta.c + db/db_method.c db/db_open.c db/db_overflow.c db/db_pr.c db/db_rec.c db/db_reclaim.c + db/db_remove.c db/db_rename.c db/db_ret.c env/db_salloc.c env/db_shash.c db/db_truncate.c + db/db_upg.c db/db_upg_opd.c db/db_vrfy.c db/db_vrfyutil.c dbm/dbm.c dbreg/dbreg.c + dbreg/dbreg_auto.c dbreg/dbreg_rec.c dbreg/dbreg_util.c env/env_file.c env/env_method.c + env/env_open.c env/env_recover.c env/env_region.c fileops/fileops_auto.c fileops/fop_basic.c + fileops/fop_rec.c fileops/fop_util.c hash/hash.c hash/hash_auto.c hash/hash_conv.c + hash/hash_dup.c hash/hash_func.c hash/hash_meta.c hash/hash_method.c hash/hash_open.c + hash/hash_page.c hash/hash_rec.c hash/hash_reclaim.c hash/hash_stat.c hash/hash_upgrade.c + hash/hash_verify.c hmac/hmac.c hsearch/hsearch.c lock/lock.c lock/lock_deadlock.c + lock/lock_method.c lock/lock_region.c lock/lock_stat.c lock/lock_util.c log/log.c + log/log_archive.c log/log_compare.c log/log_get.c log/log_method.c log/log_put.c + mp/mp_alloc.c mp/mp_bh.c mp/mp_fget.c mp/mp_fopen.c mp/mp_fput.c + mp/mp_fset.c mp/mp_method.c mp/mp_region.c mp/mp_register.c mp/mp_stat.c mp/mp_sync.c + mp/mp_trickle.c mutex/mut_tas.c mutex/mut_win32.c mutex/mutex.c os_win32/os_abs.c + os/os_alloc.c os_win32/os_clock.c os_win32/os_config.c os_win32/os_dir.c os_win32/os_errno.c + os_win32/os_fid.c os_win32/os_fsync.c os_win32/os_handle.c os/os_id.c os_win32/os_map.c + os/os_method.c os/os_oflags.c os_win32/os_open.c os/os_region.c os_win32/os_rename.c + os/os_root.c os/os_rpath.c os_win32/os_rw.c os_win32/os_seek.c os_win32/os_sleep.c + os_win32/os_spin.c os_win32/os_stat.c os/os_tmpdir.c os_win32/os_type.c os/os_unlink.c + qam/qam.c qam/qam_auto.c qam/qam_conv.c qam/qam_files.c qam/qam_method.c qam/qam_open.c + qam/qam_rec.c qam/qam_stat.c qam/qam_upgrade.c qam/qam_verify.c rep/rep_method.c + rep/rep_record.c rep/rep_region.c rep/rep_util.c hmac/sha1.c + clib/strcasecmp.c txn/txn.c txn/txn_auto.c txn/txn_method.c txn/txn_rec.c + txn/txn_recover.c txn/txn_region.c txn/txn_stat.c txn/txn_util.c common/util_log.c + common/util_sig.c xa/xa.c xa/xa_db.c xa/xa_map.c) + diff --git a/bdb/Makefile.in b/bdb/Makefile.in index c83d40ac8b2..d40fffed769 100644 --- a/bdb/Makefile.in +++ b/bdb/Makefile.in @@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ # distdir and top_distdir are set by the calling Makefile bdb_build = build_unix -files = LICENSE Makefile Makefile.in README +files = LICENSE Makefile Makefile.in README CMakeLists.txt subdirs = btree build_vxworks build_win32 clib common cxx db dbinc \ dbinc_auto db185 db_archive db_checkpoint db_deadlock db_dump \ db_dump185 db_load db_printlog db_recover db_stat db_upgrade \ diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt new file mode 100755 index 00000000000..3e7f1a48c70 --- /dev/null +++ b/client/CMakeLists.txt @@ -0,0 +1,79 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +# The old Windows build method used renamed (.cc -> .cpp) source files, fails +# in #include in mysqlbinlog.cc. So disable that using the USING_CMAKE define. +ADD_DEFINITIONS(-DUSING_CMAKE) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/zlib + ${CMAKE_SOURCE_DIR}/extra/yassl/include + ${CMAKE_SOURCE_DIR}/libmysql + ${CMAKE_SOURCE_DIR}/regex + ${CMAKE_SOURCE_DIR}/mysys + ${CMAKE_SOURCE_DIR}/sql + ${CMAKE_SOURCE_DIR}/strings) + +ADD_LIBRARY(mysqlclient ../mysys/array.c ../strings/bchange.c ../strings/bmove.c + ../strings/bmove_upp.c ../mysys/charset-def.c ../mysys/charset.c + ../sql-common/client.c ../strings/ctype-big5.c ../strings/ctype-bin.c + ../strings/ctype-cp932.c ../strings/ctype-czech.c ../strings/ctype-euc_kr.c + ../strings/ctype-eucjpms.c ../strings/ctype-extra.c ../strings/ctype-gb2312.c + ../strings/ctype-gbk.c ../strings/ctype-latin1.c ../strings/ctype-mb.c + ../strings/ctype-simple.c ../strings/ctype-sjis.c ../strings/ctype-tis620.c + ../strings/ctype-uca.c ../strings/ctype-ucs2.c ../strings/ctype-ujis.c + ../strings/ctype-utf8.c ../strings/ctype-win1250ch.c ../strings/ctype.c + ../mysys/default.c ../libmysql/errmsg.c ../mysys/errors.c + ../libmysql/get_password.c ../strings/int2str.c ../strings/is_prefix.c + ../libmysql/libmysql.c ../mysys/list.c ../strings/llstr.c + ../strings/longlong2str.c ../libmysql/manager.c ../mysys/mf_cache.c + ../mysys/mf_dirname.c ../mysys/mf_fn_ext.c ../mysys/mf_format.c + ../mysys/mf_iocache.c ../mysys/mf_iocache2.c ../mysys/mf_loadpath.c + ../mysys/mf_pack.c ../mysys/mf_path.c ../mysys/mf_tempfile.c ../mysys/mf_unixpath.c + ../mysys/mf_wcomp.c ../mysys/mulalloc.c ../mysys/my_access.c ../mysys/my_alloc.c + ../mysys/my_chsize.c ../mysys/my_compress.c ../mysys/my_create.c + ../mysys/my_delete.c ../mysys/my_div.c ../mysys/my_error.c ../mysys/my_file.c + ../mysys/my_fopen.c ../mysys/my_fstream.c ../mysys/my_gethostbyname.c + ../mysys/my_getopt.c ../mysys/my_getwd.c ../mysys/my_init.c ../mysys/my_lib.c + ../mysys/my_malloc.c ../mysys/my_messnc.c ../mysys/my_net.c ../mysys/my_once.c + ../mysys/my_open.c ../mysys/my_pread.c ../mysys/my_pthread.c ../mysys/my_read.c + ../mysys/my_realloc.c ../mysys/my_rename.c ../mysys/my_seek.c + ../mysys/my_static.c ../strings/my_strtoll10.c ../mysys/my_symlink.c + ../mysys/my_symlink2.c ../mysys/my_thr_init.c ../sql-common/my_time.c + ../strings/my_vsnprintf.c ../mysys/my_wincond.c ../mysys/my_winthread.c + ../mysys/my_write.c ../sql/net_serv.cc ../sql-common/pack.c ../sql/password.c + ../mysys/safemalloc.c ../mysys/sha1.c ../strings/str2int.c + ../strings/str_alloc.c ../strings/strcend.c ../strings/strcont.c ../strings/strend.c + ../strings/strfill.c ../mysys/string.c ../strings/strinstr.c ../strings/strmake.c + ../strings/strmov.c ../strings/strnlen.c ../strings/strnmov.c ../strings/strtod.c + ../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c + ../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c + ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c) + +ADD_DEPENDENCIES(mysqlclient GenError) +ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc sql_string.cc) +LINK_DIRECTORIES(${MYSQL_BINARY_DIR}/mysys ${MYSQL_BINARY_DIR}/zlib) +TARGET_LINK_LIBRARIES(mysql mysqlclient mysys yassl taocrypt zlib dbug wsock32) + +ADD_EXECUTABLE(mysqltest mysqltest.c) +TARGET_LINK_LIBRARIES(mysqltest mysqlclient mysys yassl taocrypt zlib dbug regex wsock32) + +ADD_EXECUTABLE(mysqlcheck mysqlcheck.c) +TARGET_LINK_LIBRARIES(mysqlcheck mysqlclient dbug yassl taocrypt zlib wsock32) + +ADD_EXECUTABLE(mysqldump mysqldump.c ../sql-common/my_user.c) +TARGET_LINK_LIBRARIES(mysqldump mysqlclient mysys dbug yassl taocrypt zlib wsock32) + +ADD_EXECUTABLE(mysqlimport mysqlimport.c) +TARGET_LINK_LIBRARIES(mysqlimport mysqlclient mysys dbug yassl taocrypt zlib wsock32) + +ADD_EXECUTABLE(mysqlshow mysqlshow.c) +TARGET_LINK_LIBRARIES(mysqlshow mysqlclient mysys dbug yassl taocrypt zlib wsock32) + +ADD_EXECUTABLE(mysqlbinlog mysqlbinlog.cc ../mysys/mf_tempdir.c ../mysys/my_new.cc + ../mysys/my_bit.c ../mysys/my_bitmap.c + ../mysys/base64.c) +TARGET_LINK_LIBRARIES(mysqlbinlog mysqlclient dbug yassl taocrypt zlib wsock32) + +ADD_EXECUTABLE(mysqladmin mysqladmin.cc) +TARGET_LINK_LIBRARIES(mysqladmin mysqlclient mysys dbug yassl taocrypt zlib wsock32) + diff --git a/client/Makefile.am b/client/Makefile.am index b80357f68ea..d3c320db56c 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -60,6 +60,8 @@ DEFS = -DUNDEF_THREADS_HACK \ -DDEFAULT_MYSQL_HOME="\"$(prefix)\"" \ -DDATADIR="\"$(localstatedir)\"" +EXTRA_DIST = get_password.c CMakeLists.txt + link_sources: for f in $(sql_src) ; do \ rm -f $$f; \ diff --git a/client/mysql.cc b/client/mysql.cc index 6af9be965bb..2ba9e896747 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1974,6 +1974,9 @@ com_charset(String *buffer __attribute__((unused)), char *line) if (new_cs) { charset_info= new_cs; + mysql_set_character_set(&mysql, charset_info->csname); + default_charset= (char *)charset_info->csname; + default_charset_used= 1; put_info("Charset changed", INFO_INFO); } else put_info("Charset is not found", INFO_INFO); @@ -2351,9 +2354,14 @@ print_table_data(MYSQL_RES *result) (void) tee_fputs("|", PAGER); for (uint off=0; (field = mysql_fetch_field(result)) ; off++) { - tee_fprintf(PAGER, " %-*s |",(int) min(field->max_length, + uint name_length= (uint) strlen(field->name); + uint numcells= charset_info->cset->numcells(charset_info, + field->name, + field->name + name_length); + uint display_length= field->max_length + name_length - numcells; + tee_fprintf(PAGER, " %-*s |",(int) min(display_length, MAX_COLUMN_LENGTH), - field->name); + field->name); num_flag[off]= IS_NUM(field->type); not_null_flag[off]= IS_NOT_NULL(field->flags); } diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index c68f8777624..9a73263f558 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -157,17 +157,29 @@ static int create_defaults_file(const char *path, const char *our_defaults_path) File our_defaults_file, defaults_file; char buffer[512]; char *buffer_end; + int failed_to_open_count= 0; int error; /* check if the defaults file is needed at all */ if (!opt_password) return 0; - defaults_file= my_open(path, O_BINARY | O_CREAT | O_WRONLY, +retry_open: + defaults_file= my_open(path, O_BINARY | O_CREAT | O_WRONLY | O_EXCL, MYF(MY_FAE | MY_WME)); if (defaults_file < 0) - return 1; + { + if (failed_to_open_count == 0) + { + remove(path); + failed_to_open_count+= 1; + goto retry_open; + } + else + return 1; + } + upgrade_defaults_created= 1; if (our_defaults_path) { diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 9cecdb4eafc..c04c2ecabd6 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1490,14 +1490,13 @@ int main(int argc, char** argv) the server */ -#ifdef __WIN__ #include "my_decimal.h" #include "decimal.c" + +#if defined(__WIN__) && !defined(CMAKE_BUILD) #include "my_decimal.cpp" #include "log_event.cpp" #else -#include "my_decimal.h" -#include "decimal.c" #include "my_decimal.cc" #include "log_event.cc" #endif diff --git a/client/mysqldump.c b/client/mysqldump.c index 5ecf334c9f7..e774a07295b 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -417,7 +417,9 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row, int string_value); static int dump_selected_tables(char *db, char **table_names, int tables); static int dump_all_tables_in_db(char *db); -static int init_dumping(char *); +static int init_dumping_views(char *); +static int init_dumping_tables(char *); +static int init_dumping(char *, int init_func(char*)); static int dump_databases(char **); static int dump_all_databases(); static char *quote_name(const char *name, char *buff, my_bool force); @@ -848,8 +850,9 @@ static int get_options(int *argc, char ***argv) static void DB_error(MYSQL *mysql, const char *when) { DBUG_ENTER("DB_error"); - my_printf_error(0,"Got error: %d: %s %s", MYF(0), - mysql_errno(mysql), mysql_error(mysql), when); + fprintf(stderr, "%s: Got error: %d: %s %s\n", my_progname, + mysql_errno(mysql), mysql_error(mysql), when); + fflush(stderr); safe_exit(EX_MYSQLERR); DBUG_VOID_RETURN; } /* DB_error */ @@ -877,8 +880,9 @@ static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res, if (mysql_query(mysql_con, query) || (res && !((*res)= mysql_store_result(mysql_con)))) { - my_printf_error(0, "Couldn't execute '%s': %s (%d)", MYF(0), - query, mysql_error(mysql_con), mysql_errno(mysql_con)); + fprintf(stderr, "%s: Couldn't execute '%s': %s (%d)\n", + my_progname, query, + mysql_error(mysql_con), mysql_errno(mysql_con)); safe_exit(EX_MYSQLERR); return 1; } @@ -2232,7 +2236,10 @@ static void dump_table(char *table, char *db) check_io(md_result_file); } if (mysql_query_with_error_report(mysql, 0, query)) + { DB_error(mysql, "when retrieving data from server"); + goto err; + } if (quick) res=mysql_use_result(mysql); else @@ -2635,7 +2642,76 @@ static int dump_databases(char **db_names) } /* dump_databases */ -static int init_dumping(char *database) +/* +View Specific database initalization. + +SYNOPSIS + init_dumping_views + qdatabase quoted name of the database + +RETURN VALUES + 0 Success. + 1 Failure. +*/ +int init_dumping_views(char *qdatabase) +{ + return 0; +} /* init_dumping_views */ + + +/* +Table Specific database initalization. + +SYNOPSIS + init_dumping_tables + qdatabase quoted name of the database + +RETURN VALUES + 0 Success. + 1 Failure. +*/ +int init_dumping_tables(char *qdatabase) +{ + if (!opt_create_db) + { + char qbuf[256]; + MYSQL_ROW row; + MYSQL_RES *dbinfo; + + my_snprintf(qbuf, sizeof(qbuf), + "SHOW CREATE DATABASE IF NOT EXISTS %s", + qdatabase); + + if (mysql_query(mysql, qbuf) || !(dbinfo = mysql_store_result(mysql))) + { + /* Old server version, dump generic CREATE DATABASE */ + if (opt_drop_database) + fprintf(md_result_file, + "\n/*!40000 DROP DATABASE IF EXISTS %s;*/\n", + qdatabase); + fprintf(md_result_file, + "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n", + qdatabase); + } + else + { + if (opt_drop_database) + fprintf(md_result_file, + "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n", + qdatabase); + row = mysql_fetch_row(dbinfo); + if (row[1]) + { + fprintf(md_result_file,"\n%s;\n",row[1]); + } + } + } + + return 0; +} /* init_dumping_tables */ + + +static int init_dumping(char *database, int init_func(char*)) { if (mysql_get_server_version(mysql) >= 50003 && !my_strcasecmp(&my_charset_latin1, database, "information_schema")) @@ -2660,40 +2736,10 @@ static int init_dumping(char *database) fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase); check_io(md_result_file); } - if (!opt_create_db) - { - char qbuf[256]; - MYSQL_ROW row; - MYSQL_RES *dbinfo; - my_snprintf(qbuf, sizeof(qbuf), - "SHOW CREATE DATABASE IF NOT EXISTS %s", - qdatabase); + /* Call the view or table specific function */ + init_func(qdatabase); - if (mysql_query(mysql, qbuf) || !(dbinfo = mysql_store_result(mysql))) - { - /* Old server version, dump generic CREATE DATABASE */ - if (opt_drop_database) - fprintf(md_result_file, - "\n/*!40000 DROP DATABASE IF EXISTS %s;*/\n", - qdatabase); - fprintf(md_result_file, - "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n", - qdatabase); - } - else - { - if (opt_drop_database) - fprintf(md_result_file, - "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n", - qdatabase); - row = mysql_fetch_row(dbinfo); - if (row[1]) - { - fprintf(md_result_file,"\n%s;\n",row[1]); - } - } - } fprintf(md_result_file,"\nUSE %s;\n", qdatabase); check_io(md_result_file); } @@ -2725,7 +2771,7 @@ static int dump_all_tables_in_db(char *database) afterdot= strmov(hash_key, database); *afterdot++= '.'; - if (init_dumping(database)) + if (init_dumping(database, init_dumping_tables)) return 1; if (opt_xml) print_xml_tag1(md_result_file, "", "database name=", database, "\n"); @@ -2797,23 +2843,8 @@ static my_bool dump_all_views_in_db(char *database) uint numrows; char table_buff[NAME_LEN*2+3]; - if (mysql_select_db(mysql, database)) - { - DB_error(mysql, "when selecting the database"); + if (init_dumping(database, init_dumping_views)) return 1; - } - if (opt_databases || opt_alldbs) - { - char quoted_database_buf[NAME_LEN*2+3]; - char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted); - if (opt_comments) - { - fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase); - check_io(md_result_file); - } - fprintf(md_result_file,"\nUSE %s;\n", qdatabase); - check_io(md_result_file); - } if (opt_xml) print_xml_tag1(md_result_file, "", "database name=", database, "\n"); if (lock_tables) @@ -2908,7 +2939,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) char **dump_tables, **pos, **end; DBUG_ENTER("dump_selected_tables"); - if (init_dumping(db)) + if (init_dumping(db, init_dumping_tables)) return 1; init_alloc_root(&root, 8192, 0); diff --git a/configure.in b/configure.in index 3430bd8a5b5..34d94b4f7da 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.25) +AM_INIT_AUTOMAKE(mysql, 5.0.26) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=25 +NDB_VERSION_BUILD=26 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? @@ -1655,20 +1655,17 @@ AC_ARG_WITH(debug, if test "$with_debug" = "yes" then # Medium debug. - AC_DEFINE([DBUG_ON], [1], [Use libdbug]) - CFLAGS="$DEBUG_CFLAGS $DEBUG_OPTIMIZE_CC -DSAFE_MUTEX $CFLAGS" - CXXFLAGS="$DEBUG_CXXFLAGS $DEBUG_OPTIMIZE_CXX -DSAFE_MUTEX $CXXFLAGS" + CFLAGS="$DEBUG_CFLAGS $DEBUG_OPTIMIZE_CC -DDBUG_ON -DSAFE_MUTEX $CFLAGS" + CXXFLAGS="$DEBUG_CXXFLAGS $DEBUG_OPTIMIZE_CXX -DDBUG_ON -DSAFE_MUTEX $CXXFLAGS" elif test "$with_debug" = "full" then # Full debug. Very slow in some cases - AC_DEFINE([DBUG_ON], [1], [Use libdbug]) - CFLAGS="$DEBUG_CFLAGS -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS" - CXXFLAGS="$DEBUG_CXXFLAGS -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS" + CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS" + CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS" else # Optimized version. No debug - AC_DEFINE([DBUG_OFF], [1], [Don't use libdbug]) - CFLAGS="$OPTIMIZE_CFLAGS $CFLAGS" - CXXFLAGS="$OPTIMIZE_CXXFLAGS $CXXFLAGS" + CFLAGS="$OPTIMIZE_CFLAGS -DDBUG_OFF $CFLAGS" + CXXFLAGS="$OPTIMIZE_CXXFLAGS -DDBUG_OFF $CXXFLAGS" fi # Force static compilation to avoid linking problems/get more speed @@ -2829,6 +2826,7 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl include/mysql_version.h dnl cmd-line-utils/Makefile dnl cmd-line-utils/libedit/Makefile dnl + win/Makefile dnl zlib/Makefile dnl cmd-line-utils/readline/Makefile) AC_CONFIG_COMMANDS([default], , test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h) diff --git a/dbug/CMakeLists.txt b/dbug/CMakeLists.txt new file mode 100755 index 00000000000..fe20fdd3db6 --- /dev/null +++ b/dbug/CMakeLists.txt @@ -0,0 +1,5 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -D__WIN32__") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +ADD_LIBRARY(dbug dbug.c factorial.c sanity.c) diff --git a/dbug/Makefile.am b/dbug/Makefile.am index 38705e63847..57288d32431 100644 --- a/dbug/Makefile.am +++ b/dbug/Makefile.am @@ -22,7 +22,8 @@ noinst_HEADERS = dbug_long.h libdbug_a_SOURCES = dbug.c sanity.c EXTRA_DIST = example1.c example2.c example3.c \ user.r monty.doc readme.prof dbug_add_tags.pl \ - my_main.c main.c factorial.c dbug_analyze.c + my_main.c main.c factorial.c dbug_analyze.c \ + CMakeLists.txt NROFF_INC = example1.r example2.r example3.r main.r \ factorial.r output1.r output2.r output3.r \ output4.r output5.r diff --git a/dbug/dbug.c b/dbug/dbug.c index 575481305e7..c991daf3617 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -66,13 +66,10 @@ * Check of malloc on entry/exit (option "S") */ -#include <my_global.h> - -/* This file won't compile unless DBUG_OFF is undefined locally */ #ifdef DBUG_OFF #undef DBUG_OFF #endif - +#include <my_global.h> #include <m_string.h> #include <errno.h> #if defined(MSDOS) || defined(__WIN__) diff --git a/extra/CMakeLists.txt b/extra/CMakeLists.txt new file mode 100755 index 00000000000..50e0f04eb14 --- /dev/null +++ b/extra/CMakeLists.txt @@ -0,0 +1,32 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + +ADD_EXECUTABLE(comp_err comp_err.c) +TARGET_LINK_LIBRARIES(comp_err dbug mysys strings wsock32) + +GET_TARGET_PROPERTY(COMP_ERR_EXE comp_err LOCATION) + +ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_SOURCE_DIR}/include/mysqld_error.h + COMMAND ${COMP_ERR_EXE} + --charset=${PROJECT_SOURCE_DIR}/sql/share/charsets + --out-dir=${PROJECT_SOURCE_DIR}/sql/share/ + --header_file=${PROJECT_SOURCE_DIR}/include/mysqld_error.h + --name_file=${PROJECT_SOURCE_DIR}/include/mysqld_ername.h + --state_file=${PROJECT_SOURCE_DIR}/include/sql_state.h + --in_file=${PROJECT_SOURCE_DIR}/sql/share/errmsg.txt + DEPENDS comp_err ${PROJECT_SOURCE_DIR}/sql/share/errmsg.txt) + +ADD_CUSTOM_TARGET(GenError + ALL + DEPENDS ${PROJECT_SOURCE_DIR}/include/mysqld_error.h) + +ADD_EXECUTABLE(my_print_defaults my_print_defaults.c) +TARGET_LINK_LIBRARIES(my_print_defaults strings mysys dbug taocrypt odbc32 odbccp32 wsock32) + +ADD_EXECUTABLE(perror perror.c) +TARGET_LINK_LIBRARIES(perror strings mysys dbug wsock32) + +ADD_EXECUTABLE(replace replace.c) +TARGET_LINK_LIBRARIES(replace strings mysys dbug wsock32) diff --git a/extra/Makefile.am b/extra/Makefile.am index c0ad75059df..0de513ba15a 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -43,6 +43,7 @@ $(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 innochecksum noinst_PROGRAMS = charset2html +EXTRA_DIST = CMakeLists.txt # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/extra/comp_err.c b/extra/comp_err.c index 65fc131a5fc..14774c87a28 100644 --- a/extra/comp_err.c +++ b/extra/comp_err.c @@ -188,8 +188,9 @@ int main(int argc, char *argv[]) DBUG_RETURN(1); } clean_up(lang_head, error_head); + DBUG_LEAVE; /* we can't call my_end after DBUG_RETURN */ my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); - DBUG_RETURN(0); + return(0); } } diff --git a/extra/yassl/CMakeLists.txt b/extra/yassl/CMakeLists.txt new file mode 100755 index 00000000000..e5429876072 --- /dev/null +++ b/extra/yassl/CMakeLists.txt @@ -0,0 +1,6 @@ +ADD_DEFINITIONS("-DWIN32 -D_LIB -DYASSL_PREFIX") + +INCLUDE_DIRECTORIES(include taocrypt/include mySTL) +ADD_LIBRARY(yassl src/buffer.cpp src/cert_wrapper.cpp src/crypto_wrapper.cpp src/handshake.cpp src/lock.cpp + src/log.cpp src/socket_wrapper.cpp src/ssl.cpp src/timer.cpp src/yassl_error.cpp + src/yassl_imp.cpp src/yassl_int.cpp) diff --git a/extra/yassl/Makefile.am b/extra/yassl/Makefile.am index d0415012767..12a7da1085b 100644 --- a/extra/yassl/Makefile.am +++ b/extra/yassl/Makefile.am @@ -1,2 +1,2 @@ SUBDIRS = taocrypt src testsuite -EXTRA_DIST = yassl.dsp yassl.dsw $(wildcard mySTL/*.hpp) +EXTRA_DIST = yassl.dsp yassl.dsw $(wildcard mySTL/*.hpp) CMakeLists.txt diff --git a/extra/yassl/include/openssl/generate_prefix_files.pl b/extra/yassl/include/openssl/generate_prefix_files.pl index b921ee11e9a..da591b31332 100755 --- a/extra/yassl/include/openssl/generate_prefix_files.pl +++ b/extra/yassl/include/openssl/generate_prefix_files.pl @@ -30,7 +30,7 @@ sub generate_prefix($$) next; } - if ( /^\s*[a-zA-Z0-9*_ ]+\s+([_a-zA-Z0-9]+)\s*\(/ ) + if ( /^\s*[a-zA-Z0-9*_ ]+\s+\*?([_a-zA-Z0-9]+)\s*\(/ ) { print OUT "#define $1 ya$1\n"; } diff --git a/extra/yassl/include/openssl/prefix_ssl.h b/extra/yassl/include/openssl/prefix_ssl.h index 7f815156f47..aa3f799cf80 100644 --- a/extra/yassl/include/openssl/prefix_ssl.h +++ b/extra/yassl/include/openssl/prefix_ssl.h @@ -1,5 +1,6 @@ #define Copyright yaCopyright #define yaSSL_CleanUp yayaSSL_CleanUp +#define BN_bin2bn yaBN_bin2bn #define DH_new yaDH_new #define DH_free yaDH_free #define RSA_free yaRSA_free @@ -92,6 +93,12 @@ #define SSL_want_read yaSSL_want_read #define SSL_want_write yaSSL_want_write #define SSL_pending yaSSL_pending +#define SSLv3_method yaSSLv3_method +#define SSLv3_server_method yaSSLv3_server_method +#define SSLv3_client_method yaSSLv3_client_method +#define TLSv1_server_method yaTLSv1_server_method +#define TLSv1_client_method yaTLSv1_client_method +#define SSLv23_server_method yaSSLv23_server_method #define SSL_CTX_use_certificate_file yaSSL_CTX_use_certificate_file #define SSL_CTX_use_PrivateKey_file yaSSL_CTX_use_PrivateKey_file #define SSL_CTX_set_cipher_list yaSSL_CTX_set_cipher_list @@ -115,11 +122,13 @@ #define RAND_write_file yaRAND_write_file #define RAND_load_file yaRAND_load_file #define RAND_status yaRAND_status +#define RAND_bytes yaRAND_bytes #define DES_set_key yaDES_set_key #define DES_set_odd_parity yaDES_set_odd_parity #define DES_ecb_encrypt yaDES_ecb_encrypt #define SSL_CTX_set_default_passwd_cb_userdata yaSSL_CTX_set_default_passwd_cb_userdata #define SSL_SESSION_free yaSSL_SESSION_free +#define SSL_peek yaSSL_peek #define SSL_get_certificate yaSSL_get_certificate #define SSL_get_privatekey yaSSL_get_privatekey #define X509_get_pubkey yaX509_get_pubkey diff --git a/extra/yassl/taocrypt/CMakeLists.txt b/extra/yassl/taocrypt/CMakeLists.txt new file mode 100755 index 00000000000..0af0a242e5d --- /dev/null +++ b/extra/yassl/taocrypt/CMakeLists.txt @@ -0,0 +1,10 @@ +INCLUDE_DIRECTORIES(../mySTL include) + +ADD_LIBRARY(taocrypt src/aes.cpp src/aestables.cpp src/algebra.cpp src/arc4.cpp src/asn.cpp src/coding.cpp + src/des.cpp src/dh.cpp src/dsa.cpp src/file.cpp src/hash.cpp src/integer.cpp src/md2.cpp + src/md4.cpp src/md5.cpp src/misc.cpp src/random.cpp src/ripemd.cpp src/rsa.cpp src/sha.cpp + include/aes.hpp include/algebra.hpp include/arc4.hpp include/asn.hpp include/block.hpp + include/coding.hpp include/des.hpp include/dh.hpp include/dsa.hpp include/dsa.hpp + include/error.hpp include/file.hpp include/hash.hpp include/hmac.hpp include/integer.hpp + include/md2.hpp include/md5.hpp include/misc.hpp include/modarith.hpp include/modes.hpp + include/random.hpp include/ripemd.hpp include/rsa.hpp include/sha.hpp) diff --git a/extra/yassl/taocrypt/Makefile.am b/extra/yassl/taocrypt/Makefile.am index ac0c1bc29dd..e232b499cc7 100644 --- a/extra/yassl/taocrypt/Makefile.am +++ b/extra/yassl/taocrypt/Makefile.am @@ -1,2 +1,2 @@ SUBDIRS = src test benchmark -EXTRA_DIST = taocrypt.dsw taocrypt.dsp +EXTRA_DIST = taocrypt.dsw taocrypt.dsp CMakeLists.txt diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp index b8095334789..a33ca4fa432 100644 --- a/extra/yassl/taocrypt/src/misc.cpp +++ b/extra/yassl/taocrypt/src/misc.cpp @@ -29,7 +29,7 @@ #include "runtime.hpp" #include "misc.hpp" - +#if !defined(YASSL_MYSQL_COMPATIBLE) extern "C" { // for libcurl configure test, these are the signatures they use @@ -37,6 +37,7 @@ extern "C" { char CRYPTO_lock() { return 0;} char CRYPTO_add_lock() { return 0;} } // extern "C" +#endif #ifdef YASSL_PURE_C diff --git a/heap/CMakeLists.txt b/heap/CMakeLists.txt new file mode 100755 index 00000000000..db5fb8b2981 --- /dev/null +++ b/heap/CMakeLists.txt @@ -0,0 +1,8 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +ADD_LIBRARY(heap _check.c _rectest.c hp_block.c hp_clear.c hp_close.c hp_create.c + hp_delete.c hp_extra.c hp_hash.c hp_info.c hp_open.c hp_panic.c + hp_rename.c hp_rfirst.c hp_rkey.c hp_rlast.c hp_rnext.c hp_rprev.c + hp_rrnd.c hp_rsame.c hp_scan.c hp_static.c hp_update.c hp_write.c) diff --git a/heap/Makefile.am b/heap/Makefile.am index 567c7774751..a89c8a4a878 100644 --- a/heap/Makefile.am +++ b/heap/Makefile.am @@ -28,6 +28,6 @@ libheap_a_SOURCES = hp_open.c hp_extra.c hp_close.c hp_panic.c hp_info.c \ hp_rnext.c hp_rlast.c hp_rprev.c hp_clear.c \ hp_rkey.c hp_block.c \ hp_hash.c _check.c _rectest.c hp_static.c - +EXTRA_DIST = CMakeLists.txt # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/include/my_dbug.h b/include/my_dbug.h index 6e60b599f53..bf2e8d9969b 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -97,6 +97,7 @@ extern void _db_unlock_file(void); #define DBUG_UNLOCK_FILE #define DBUG_OUTPUT(A) #define DBUG_ASSERT(A) {} +#define DBUG_LEAVE #endif #ifdef __cplusplus } diff --git a/include/mysql.h b/include/mysql.h index 72e5c457d5a..ae4a8222c5b 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -165,7 +165,6 @@ struct st_mysql_options { char *ssl_ca; /* PEM CA file */ char *ssl_capath; /* PEM directory of CA-s? */ char *ssl_cipher; /* cipher to use */ - my_bool ssl_verify_server_cert; /* if to verify server cert */ char *shared_memory_base_name; unsigned long max_allowed_packet; my_bool use_ssl; /* if to use SSL or not */ diff --git a/include/mysql_com.h b/include/mysql_com.h index 60e726396cb..b1dd6152cf4 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -26,6 +26,9 @@ #define USERNAME_LENGTH 16 #define SERVER_VERSION_LENGTH 60 #define SQLSTATE_LENGTH 5 +#define SYSTEM_CHARSET_MBMAXLEN 3 +#define NAME_BYTE_LEN NAME_LEN*SYSTEM_CHARSET_MBMAXLEN +#define USERNAME_BYTE_LENGTH USERNAME_LENGTH*SYSTEM_CHARSET_MBMAXLEN /* USER_HOST_BUFF_SIZE -- length of string buffer, that is enough to contain @@ -33,7 +36,7 @@ MySQL standard format: user_name_part@host_name_part\0 */ -#define USER_HOST_BUFF_SIZE HOSTNAME_LENGTH + USERNAME_LENGTH + 2 +#define USER_HOST_BUFF_SIZE HOSTNAME_LENGTH + USERNAME_BYTE_LENGTH + 2 #define LOCAL_HOST "localhost" #define LOCAL_HOST_NAMEDPIPE "." @@ -134,8 +137,10 @@ enum enum_server_command #define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ #define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */ #define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */ -#define CLIENT_MULTI_STATEMENTS 65536 /* Enable/disable multi-stmt support */ -#define CLIENT_MULTI_RESULTS 131072 /* Enable/disable multi-results */ +#define CLIENT_MULTI_STATEMENTS (((ulong) 1) << 16) /* Enable/disable multi-stmt support */ +#define CLIENT_MULTI_RESULTS (((ulong) 1) << 17) /* Enable/disable multi-results */ + +#define CLIENT_SSL_VERIFY_SERVER_CERT (((ulong) 1) << 30) #define CLIENT_REMEMBER_OPTIONS (((ulong) 1) << 31) #define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */ @@ -209,7 +214,13 @@ typedef struct st_net { char last_error[MYSQL_ERRMSG_SIZE], sqlstate[SQLSTATE_LENGTH+1]; unsigned int last_errno; unsigned char error; + + /* + 'query_cache_query' should be accessed only via query cache + functions and methods to maintain proper locking. + */ gptr query_cache_query; + my_bool report_error; /* We should report error (we have unreported error) */ my_bool return_errno; } NET; diff --git a/innobase/CMakeLists.txt b/innobase/CMakeLists.txt new file mode 100755 index 00000000000..f9661963d56 --- /dev/null +++ b/innobase/CMakeLists.txt @@ -0,0 +1,35 @@ +#SET(CMAKE_CXX_FLAGS_DEBUG "-DSAFEMALLOC -DSAFE_MUTEX") +#SET(CMAKE_C_FLAGS_DEBUG "-DSAFEMALLOC -DSAFE_MUTEX") +ADD_DEFINITIONS(-DMYSQL_SERVER -D_WIN32 -DWIN32 -D_LIB) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include include) +ADD_LIBRARY(innobase btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c + buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c + data/data0data.c data/data0type.c + dict/dict0boot.c dict/dict0crea.c dict/dict0dict.c dict/dict0load.c dict/dict0mem.c + dyn/dyn0dyn.c + eval/eval0eval.c eval/eval0proc.c + fil/fil0fil.c + fsp/fsp0fsp.c + fut/fut0fut.c fut/fut0lst.c + ha/ha0ha.c ha/hash0hash.c + ibuf/ibuf0ibuf.c + pars/lexyy.c pars/pars0grm.c pars/pars0opt.c pars/pars0pars.c pars/pars0sym.c + lock/lock0lock.c + log/log0log.c log/log0recv.c + mach/mach0data.c + mem/mem0mem.c mem/mem0pool.c + mtr/mtr0log.c mtr/mtr0mtr.c + os/os0file.c os/os0proc.c os/os0sync.c os/os0thread.c + page/page0cur.c page/page0page.c + que/que0que.c + read/read0read.c + rem/rem0cmp.c rem/rem0rec.c + row/row0ins.c row/row0mysql.c row/row0purge.c row/row0row.c row/row0sel.c row/row0uins.c + row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c + srv/srv0que.c srv/srv0srv.c srv/srv0start.c + sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c + thr/thr0loc.c + trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c + usr/usr0sess.c + ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ) diff --git a/innobase/Makefile.am b/innobase/Makefile.am index 8ff90d16a2c..10e793396d8 100644 --- a/innobase/Makefile.am +++ b/innobase/Makefile.am @@ -25,6 +25,7 @@ noinst_HEADERS = ib_config.h SUBDIRS = os ut btr buf data dict dyn eval fil fsp fut \ ha ibuf include lock log mach mem mtr page \ pars que read rem row srv sync thr trx usr +EXTRA_DIST = CMakeLists.txt # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt new file mode 100755 index 00000000000..d12b6ca6c10 --- /dev/null +++ b/libmysql/CMakeLists.txt @@ -0,0 +1,54 @@ +# Need to set USE_TLS, since __declspec(thread) approach to thread local +# storage does not work properly in DLLs. +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_TLS") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_TLS") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/zlib + ${CMAKE_SOURCE_DIR}/extra/yassl/include + ${CMAKE_SOURCE_DIR}/libmysql + ${CMAKE_SOURCE_DIR}/regex + ${CMAKE_SOURCE_DIR}/sql + ${CMAKE_SOURCE_DIR}/strings) + +ADD_LIBRARY(libmysql SHARED dll.c libmysql.def + ../mysys/array.c ../strings/bchange.c ../strings/bmove.c + ../strings/bmove_upp.c ../mysys/charset-def.c ../mysys/charset.c + ../sql-common/client.c ../strings/ctype-big5.c ../strings/ctype-bin.c + ../strings/ctype-cp932.c ../strings/ctype-czech.c ../strings/ctype-euc_kr.c + ../strings/ctype-eucjpms.c ../strings/ctype-extra.c ../strings/ctype-gb2312.c + ../strings/ctype-gbk.c ../strings/ctype-latin1.c ../strings/ctype-mb.c + ../strings/ctype-simple.c ../strings/ctype-sjis.c ../strings/ctype-tis620.c + ../strings/ctype-uca.c ../strings/ctype-ucs2.c ../strings/ctype-ujis.c + ../strings/ctype-utf8.c ../strings/ctype-win1250ch.c ../strings/ctype.c + ../mysys/default.c ../libmysql/errmsg.c ../mysys/errors.c + ../libmysql/get_password.c ../strings/int2str.c ../strings/is_prefix.c + ../libmysql/libmysql.c ../mysys/list.c ../strings/llstr.c + ../strings/longlong2str.c ../libmysql/manager.c ../mysys/mf_cache.c + ../mysys/mf_dirname.c ../mysys/mf_fn_ext.c ../mysys/mf_format.c + ../mysys/mf_iocache.c ../mysys/mf_iocache2.c ../mysys/mf_loadpath.c + ../mysys/mf_pack.c ../mysys/mf_path.c ../mysys/mf_tempfile.c ../mysys/mf_unixpath.c + ../mysys/mf_wcomp.c ../mysys/mulalloc.c ../mysys/my_access.c ../mysys/my_alloc.c + ../mysys/my_chsize.c ../mysys/my_compress.c ../mysys/my_create.c + ../mysys/my_delete.c ../mysys/my_div.c ../mysys/my_error.c ../mysys/my_file.c + ../mysys/my_fopen.c ../mysys/my_fstream.c ../mysys/my_gethostbyname.c + ../mysys/my_getopt.c ../mysys/my_getwd.c ../mysys/my_init.c ../mysys/my_lib.c + ../mysys/my_malloc.c ../mysys/my_messnc.c ../mysys/my_net.c ../mysys/my_once.c + ../mysys/my_open.c ../mysys/my_pread.c ../mysys/my_pthread.c ../mysys/my_read.c + ../mysys/my_realloc.c ../mysys/my_rename.c ../mysys/my_seek.c + ../mysys/my_static.c ../strings/my_strtoll10.c ../mysys/my_symlink.c + ../mysys/my_symlink2.c ../mysys/my_thr_init.c ../sql-common/my_time.c + ../strings/my_vsnprintf.c ../mysys/my_wincond.c ../mysys/my_winthread.c + ../mysys/my_write.c ../sql/net_serv.cc ../sql-common/pack.c ../sql/password.c + ../mysys/safemalloc.c ../mysys/sha1.c ../strings/str2int.c + ../strings/str_alloc.c ../strings/strcend.c ../strings/strcont.c ../strings/strend.c + ../strings/strfill.c ../mysys/string.c ../strings/strinstr.c ../strings/strmake.c + ../strings/strmov.c ../strings/strnlen.c ../strings/strnmov.c ../strings/strtod.c + ../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c + ../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c + ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c) +ADD_DEPENDENCIES(libmysql dbug vio mysys strings GenError zlib yassl taocrypt) +TARGET_LINK_LIBRARIES(libmysql mysys strings wsock32) + +ADD_EXECUTABLE(myTest mytest.c) +TARGET_LINK_LIBRARIES(myTest libmysql) diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index d089d56f38a..5e6c60a007b 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -31,7 +31,7 @@ include $(srcdir)/Makefile.shared libmysqlclient_la_SOURCES = $(target_sources) libmysqlclient_la_LIBADD = $(target_libadd) $(yassl_las) libmysqlclient_la_LDFLAGS = $(target_ldflags) -EXTRA_DIST = Makefile.shared libmysql.def +EXTRA_DIST = Makefile.shared libmysql.def dll.c mytest.c CMakeLists.txt noinst_HEADERS = client_settings.h # This is called from the toplevel makefile diff --git a/libmysql/mytest.c b/libmysql/mytest.c new file mode 100644 index 00000000000..2d5c576b72a --- /dev/null +++ b/libmysql/mytest.c @@ -0,0 +1,175 @@ +/*C4*/ +/****************************************************************/ +/* Author: Jethro Wright, III TS : 3/ 4/1998 9:15 */ +/* Date: 02/18/1998 */ +/* mytest.c : do some testing of the libmySQL.DLL.... */ +/* */ +/* History: */ +/* 02/18/1998 jw3 also sprach zarathustra.... */ +/****************************************************************/ + + +#include <windows.h> +#include <stdio.h> +#include <string.h> + +#include <mysql.h> + +#define DEFALT_SQL_STMT "SELECT * FROM db" +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + + +/******************************************************** +** +** main :- +** +********************************************************/ + +int +main( int argc, char * argv[] ) +{ + + char szSQL[ 200 ], aszFlds[ 25 ][ 25 ], szDB[ 50 ] ; + const char *pszT; + int i, j, k, l, x ; + MYSQL * myData ; + MYSQL_RES * res ; + MYSQL_FIELD * fd ; + MYSQL_ROW row ; + + //....just curious.... + printf( "sizeof( MYSQL ) == %d\n", (int) sizeof( MYSQL ) ) ; + if ( argc == 2 ) + { + strcpy( szDB, argv[ 1 ] ) ; + strcpy( szSQL, DEFALT_SQL_STMT ) ; + if (!strcmp(szDB,"--debug")) + { + strcpy( szDB, "mysql" ) ; + printf("Some mysql struct information (size and offset):\n"); + printf("net:\t%3d %3d\n",(int) sizeof(myData->net), + (int) offsetof(MYSQL,net)); + printf("host:\t%3d %3d\n",(int) sizeof(myData->host), + (int) offsetof(MYSQL,host)); + printf("port:\t%3d %3d\n", (int) sizeof(myData->port), + (int) offsetof(MYSQL,port)); + printf("protocol_version:\t%3d %3d\n", + (int) sizeof(myData->protocol_version), + (int) offsetof(MYSQL,protocol_version)); + printf("thread_id:\t%3d %3d\n",(int) sizeof(myData->thread_id), + (int) offsetof(MYSQL,thread_id)); + printf("affected_rows:\t%3d %3d\n",(int) sizeof(myData->affected_rows), + (int) offsetof(MYSQL,affected_rows)); + printf("packet_length:\t%3d %3d\n",(int) sizeof(myData->packet_length), + (int) offsetof(MYSQL,packet_length)); + printf("status:\t%3d %3d\n",(int) sizeof(myData->status), + (int) offsetof(MYSQL,status)); + printf("fields:\t%3d %3d\n",(int) sizeof(myData->fields), + (int) offsetof(MYSQL,fields)); + printf("field_alloc:\t%3d %3d\n",(int) sizeof(myData->field_alloc), + (int) offsetof(MYSQL,field_alloc)); + printf("free_me:\t%3d %3d\n",(int) sizeof(myData->free_me), + (int) offsetof(MYSQL,free_me)); + printf("options:\t%3d %3d\n",(int) sizeof(myData->options), + (int) offsetof(MYSQL,options)); + puts(""); + } + } + else if ( argc > 2 ) { + strcpy( szDB, argv[ 1 ] ) ; + strcpy( szSQL, argv[ 2 ] ) ; + } + else { + strcpy( szDB, "mysql" ) ; + strcpy( szSQL, DEFALT_SQL_STMT ) ; + } + //.... + + if ( (myData = mysql_init((MYSQL*) 0)) && + mysql_real_connect( myData, NULL, NULL, NULL, NULL, MYSQL_PORT, + NULL, 0 ) ) + { + myData->reconnect= 1; + if ( mysql_select_db( myData, szDB ) < 0 ) { + printf( "Can't select the %s database !\n", szDB ) ; + mysql_close( myData ) ; + return 2 ; + } + } + else { + printf( "Can't connect to the mysql server on port %d !\n", + MYSQL_PORT ) ; + mysql_close( myData ) ; + return 1 ; + } + //.... + if ( ! mysql_query( myData, szSQL ) ) { + res = mysql_store_result( myData ) ; + i = (int) mysql_num_rows( res ) ; l = 1 ; + printf( "Query: %s\nNumber of records found: %ld\n", szSQL, i ) ; + //....we can get the field-specific characteristics here.... + for ( x = 0 ; fd = mysql_fetch_field( res ) ; x++ ) + strcpy( aszFlds[ x ], fd->name ) ; + //.... + while ( row = mysql_fetch_row( res ) ) { + j = mysql_num_fields( res ) ; + printf( "Record #%ld:-\n", l++ ) ; + for ( k = 0 ; k < j ; k++ ) + printf( " Fld #%d (%s): %s\n", k + 1, aszFlds[ k ], + (((row[k]==NULL)||(!strlen(row[k])))?"NULL":row[k])) ; + puts( "==============================\n" ) ; + } + mysql_free_result( res ) ; + } + else printf( "Couldn't execute %s on the server !\n", szSQL ) ; + //.... + puts( "==== Diagnostic info ====" ) ; + pszT = mysql_get_client_info() ; + printf( "Client info: %s\n", pszT ) ; + //.... + pszT = mysql_get_host_info( myData ) ; + printf( "Host info: %s\n", pszT ) ; + //.... + pszT = mysql_get_server_info( myData ) ; + printf( "Server info: %s\n", pszT ) ; + //.... + res = mysql_list_processes( myData ) ; l = 1 ; + if (res) + { + for ( x = 0 ; fd = mysql_fetch_field( res ) ; x++ ) + strcpy( aszFlds[ x ], fd->name ) ; + while ( row = mysql_fetch_row( res ) ) { + j = mysql_num_fields( res ) ; + printf( "Process #%ld:-\n", l++ ) ; + for ( k = 0 ; k < j ; k++ ) + printf( " Fld #%d (%s): %s\n", k + 1, aszFlds[ k ], + (((row[k]==NULL)||(!strlen(row[k])))?"NULL":row[k])) ; + puts( "==============================\n" ) ; + } + } + else + { + printf("Got error %s when retreiving processlist\n",mysql_error(myData)); + } + //.... + res = mysql_list_tables( myData, "%" ) ; l = 1 ; + for ( x = 0 ; fd = mysql_fetch_field( res ) ; x++ ) + strcpy( aszFlds[ x ], fd->name ) ; + while ( row = mysql_fetch_row( res ) ) { + j = mysql_num_fields( res ) ; + printf( "Table #%ld:-\n", l++ ) ; + for ( k = 0 ; k < j ; k++ ) + printf( " Fld #%d (%s): %s\n", k + 1, aszFlds[ k ], + (((row[k]==NULL)||(!strlen(row[k])))?"NULL":row[k])) ; + puts( "==============================\n" ) ; + } + //.... + pszT = mysql_stat( myData ) ; + puts( pszT ) ; + //.... + mysql_close( myData ) ; + return 0 ; + +} diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def index 3895588e02c..0e80681700f 100644 --- a/libmysqld/libmysqld.def +++ b/libmysqld/libmysqld.def @@ -163,3 +163,4 @@ EXPORTS my_charset_bin my_charset_same modify_defaults_file + mysql_set_server_option diff --git a/myisam/CMakeLists.txt b/myisam/CMakeLists.txt new file mode 100755 index 00000000000..3ba7aba4555 --- /dev/null +++ b/myisam/CMakeLists.txt @@ -0,0 +1,26 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +ADD_LIBRARY(myisam ft_boolean_search.c ft_nlq_search.c ft_parser.c ft_static.c ft_stem.c + ft_stopwords.c ft_update.c mi_cache.c mi_changed.c mi_check.c + mi_checksum.c mi_close.c mi_create.c mi_dbug.c mi_delete.c + mi_delete_all.c mi_delete_table.c mi_dynrec.c mi_extra.c mi_info.c + mi_key.c mi_keycache.c mi_locking.c mi_log.c mi_open.c + mi_packrec.c mi_page.c mi_panic.c mi_preload.c mi_range.c mi_rename.c + mi_rfirst.c mi_rlast.c mi_rnext.c mi_rnext_same.c mi_rprev.c mi_rrnd.c + mi_rsame.c mi_rsamepos.c mi_scan.c mi_search.c mi_static.c mi_statrec.c + mi_unique.c mi_update.c mi_write.c rt_index.c rt_key.c rt_mbr.c + rt_split.c sort.c sp_key.c ft_eval.h myisamdef.h rt_index.h mi_rkey.c) + +ADD_EXECUTABLE(myisam_ftdump myisam_ftdump.c) +TARGET_LINK_LIBRARIES(myisam_ftdump myisam mysys dbug strings zlib wsock32) + +ADD_EXECUTABLE(myisamchk myisamchk.c) +TARGET_LINK_LIBRARIES(myisamchk myisam mysys dbug strings zlib wsock32) + +ADD_EXECUTABLE(myisamlog myisamlog.c) +TARGET_LINK_LIBRARIES(myisamlog myisam mysys dbug strings zlib wsock32) + +ADD_EXECUTABLE(myisampack myisampack.c) +TARGET_LINK_LIBRARIES(myisampack myisam mysys dbug strings zlib wsock32) diff --git a/myisam/Makefile.am b/myisam/Makefile.am index e4327070997..081d7facf3a 100644 --- a/myisam/Makefile.am +++ b/myisam/Makefile.am @@ -14,7 +14,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -EXTRA_DIST = mi_test_all.sh mi_test_all.res +EXTRA_DIST = mi_test_all.sh mi_test_all.res ft_stem.c CMakeLists.txt pkgdata_DATA = mi_test_all mi_test_all.res INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include diff --git a/myisammrg/CMakeLists.txt b/myisammrg/CMakeLists.txt new file mode 100755 index 00000000000..83168f6c60c --- /dev/null +++ b/myisammrg/CMakeLists.txt @@ -0,0 +1,9 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +ADD_LIBRARY(myisammrg myrg_close.c myrg_create.c myrg_delete.c myrg_extra.c myrg_info.c + myrg_locking.c myrg_open.c myrg_panic.c myrg_queue.c myrg_range.c + myrg_rfirst.c myrg_rkey.c myrg_rlast.c myrg_rnext.c myrg_rnext_same.c + myrg_rprev.c myrg_rrnd.c myrg_rsame.c myrg_static.c myrg_update.c + myrg_write.c) diff --git a/myisammrg/Makefile.am b/myisammrg/Makefile.am index 14e3295c1ae..19543927fd2 100644 --- a/myisammrg/Makefile.am +++ b/myisammrg/Makefile.am @@ -23,6 +23,6 @@ libmyisammrg_a_SOURCES = myrg_open.c myrg_extra.c myrg_info.c myrg_locking.c \ myrg_rkey.c myrg_rfirst.c myrg_rlast.c myrg_rnext.c \ myrg_rprev.c myrg_queue.c myrg_write.c myrg_range.c \ myrg_rnext_same.c - +EXTRA_DIST = CMakeLists.txt # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 11bcef10fff..9f54b4fe192 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -34,7 +34,7 @@ benchdir_root= $(prefix) testdir = $(benchdir_root)/mysql-test EXTRA_SCRIPTS = mysql-test-run.sh install_test_db.sh valgrind.supp $(PRESCRIPTS) EXTRA_DIST = $(EXTRA_SCRIPTS) -GENSCRIPTS = mysql-test-run install_test_db +GENSCRIPTS = mysql-test-run install_test_db mtr PRESCRIPTS = mysql-test-run.pl test_SCRIPTS = $(GENSCRIPTS) $(PRESCRIPTS) test_DATA = std_data/client-key.pem std_data/client-cert.pem std_data/cacert.pem \ @@ -112,6 +112,11 @@ std_data/server-cert.pem: $(top_srcdir)/SSL/$(@F) std_data/server-key.pem: $(top_srcdir)/SSL/$(@F) @RM@ -f $@; @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data +# mtr - a shortcut for executing mysql-test-run.pl +mtr: + $(RM) -f mtr + $(LN_S) mysql-test-run.pl mtr + SUFFIXES = .sh .sh: diff --git a/mysql-test/include/im_check_env.inc b/mysql-test/include/im_check_env.inc index 169edbac6b3..019e0984614 100644 --- a/mysql-test/include/im_check_env.inc +++ b/mysql-test/include/im_check_env.inc @@ -2,10 +2,6 @@ # that ensure that starting conditions (environment) for the IM-test are as # expected. -# Wait for mysqld1 (guarded instance) to start. - ---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD1_PATH_PID 30 started - # Check the running instances. --connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK) @@ -14,6 +10,8 @@ SHOW VARIABLES LIKE 'server_id'; +--source include/not_windows.inc + --connection default # Let IM detect that mysqld1 is online. This delay should be longer than diff --git a/mysql-test/include/im_check_os.inc b/mysql-test/include/im_check_os.inc deleted file mode 100644 index 9465115feb5..00000000000 --- a/mysql-test/include/im_check_os.inc +++ /dev/null @@ -1,7 +0,0 @@ ---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/loaddata_autocom.inc b/mysql-test/include/loaddata_autocom.inc new file mode 100644 index 00000000000..e5071c73c49 --- /dev/null +++ b/mysql-test/include/loaddata_autocom.inc @@ -0,0 +1,21 @@ +# Test if the engine does autocommit in LOAD DATA INFILE, or not +# (NDB wants to do, others don't). + +eval SET SESSION STORAGE_ENGINE = $engine_type; + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1 (a text, b text); +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +commit; +select count(*) from t1; +truncate table t1; +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +rollback; +select count(*) from t1; + +drop table t1; diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index ed0395abd9d..009269f382e 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -82,7 +82,7 @@ sub collect_test_cases ($) { if ( $mysqld_test_exists and $im_test_exists ) { - mtr_error("Ambiguos test case name ($tname)"); + mtr_error("Ambiguous test case name ($tname)"); } elsif ( ! $mysqld_test_exists and ! $im_test_exists ) { @@ -154,34 +154,38 @@ sub collect_test_cases ($) { if ( $::opt_reorder ) { - @$cases = sort { - if ( ! $a->{'master_restart'} and ! $b->{'master_restart'} ) - { - return $a->{'name'} cmp $b->{'name'}; - } - if ( $a->{'master_restart'} and $b->{'master_restart'} ) - { - my $cmp= mtr_cmp_opts($a->{'master_opt'}, $b->{'master_opt'}); - if ( $cmp == 0 ) - { - return $a->{'name'} cmp $b->{'name'}; - } - else - { - return $cmp; - } - } + my %sort_criteria; + my $tinfo; - if ( $a->{'master_restart'} ) - { - return 1; # Is greater - } - else - { - return -1; # Is less - } - } @$cases; + # Make a mapping of test name to a string that represents how that test + # should be sorted among the other tests. Put the most important criterion + # first, then a sub-criterion, then sub-sub-criterion, et c. + foreach $tinfo (@$cases) + { + my @this_criteria = (); + + # Append the criteria for sorting, in order of importance. + push(@this_criteria, join("!", sort @{$tinfo->{'master_opt'}}) . "~"); # Ending with "~" makes empty sort later than filled + push(@this_criteria, "ndb=" . ($tinfo->{'ndb_test'} ? "1" : "0")); + push(@this_criteria, "restart=" . ($tinfo->{'master_restart'} ? "1" : "0")); + push(@this_criteria, "big_test=" . ($tinfo->{'big_test'} ? "1" : "0")); + push(@this_criteria, join("|", sort keys %{$tinfo})); # Group similar things together. The values may differ substantially. FIXME? + push(@this_criteria, $tinfo->{'name'}); # Finally, order by the name + + $sort_criteria{$tinfo->{"name"}} = join(" ", @this_criteria); + } + + @$cases = sort { $sort_criteria{$a->{"name"}} cmp $sort_criteria{$b->{"name"}}; } @$cases; + +### For debugging the sort-order +# foreach $tinfo (@$cases) +# { +# print $sort_criteria{$tinfo->{"name"}}; +# print " -> \t"; +# print $tinfo->{"name"}; +# print "\n"; +# } } return $cases; diff --git a/mysql-test/lib/mtr_io.pl b/mysql-test/lib/mtr_io.pl index b3da6d97664..bdf91212b59 100644 --- a/mysql-test/lib/mtr_io.pl +++ b/mysql-test/lib/mtr_io.pl @@ -19,13 +19,39 @@ sub mtr_tonewfile($@); ############################################################################## sub mtr_get_pid_from_file ($) { - my $file= shift; + my $pid_file_path= shift; + my $TOTAL_ATTEMPTS= 30; + my $timeout= 1; - open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!"); - my $pid= <FILE>; - chomp($pid); - close FILE; - return $pid; + # We should read from the file until we get correct pid. As it is + # stated in BUG#21884, pid file can be empty at some moment. So, we should + # read it until we get valid data. + + for (my $cur_attempt= 1; $cur_attempt <= $TOTAL_ATTEMPTS; ++$cur_attempt) + { + mtr_debug("Reading pid file '$pid_file_path' " . + "($cur_attempt of $TOTAL_ATTEMPTS)..."); + + open(FILE, '<', $pid_file_path) + or mtr_error("can't open file \"$pid_file_path\": $!"); + + my $pid= <FILE>; + + chomp($pid) if defined $pid; + + close FILE; + + return $pid if defined $pid && $pid ne ''; + + mtr_debug("Pid file '$pid_file_path' is empty. " . + "Sleeping $timeout second(s)..."); + + sleep(1); + } + + mtr_error("Pid file '$pid_file_path' is corrupted. " . + "Can not retrieve PID in " . + ($timeout * $TOTAL_ATTEMPTS) . " seconds."); } sub mtr_get_opts_from_file ($) { diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index 0ca16b61fc2..bf869ca91c4 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -20,7 +20,29 @@ sub mtr_record_dead_children (); sub mtr_exit ($); sub sleep_until_file_created ($$$); sub mtr_kill_processes ($); -sub mtr_kill_process ($$$$); +sub mtr_ping_mysqld_server ($); + +# Private IM-related operations. + +sub mtr_im_kill_process ($$$$); +sub mtr_im_load_pids ($); +sub mtr_im_terminate ($); +sub mtr_im_check_alive ($); +sub mtr_im_check_main_alive ($); +sub mtr_im_check_angel_alive ($); +sub mtr_im_check_mysqlds_alive ($); +sub mtr_im_check_mysqld_alive ($$); +sub mtr_im_cleanup ($); +sub mtr_im_rm_file ($); +sub mtr_im_errlog ($); +sub mtr_im_kill ($); +sub mtr_im_wait_for_connection ($$$); +sub mtr_im_wait_for_mysqld($$$); + +# Public IM-related operations. + +sub mtr_im_start ($$); +sub mtr_im_stop ($); # static in C sub spawn_impl ($$$$$$$$); @@ -359,40 +381,54 @@ sub mtr_process_exit_status { 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?! + mtr_debug("mtr_kill_leftovers(): started."); + + mtr_im_stop($::instance_manager); + + # Kill mysqld servers (masters and slaves) that would conflict with this + # run. Make sure to remove the PID file, if any. + # Don't touch IM-managed mysqld instances -- they should be stopped by + # mtr_im_stop(). + + mtr_debug("Collecting mysqld-instances to shutdown..."); my @args; - for ( my $idx; $idx < 2; $idx++ ) + for ( my $idx= 0; $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'}, - }); - } + my $pidfile= $::master->[$idx]->{'path_mypid'}; + my $sockfile= $::master->[$idx]->{'path_mysock'}; + my $port= $::master->[$idx]->{'path_myport'}; - for ( my $idx; $idx < 2; $idx++ ) - { push(@args,{ pid => 0, # We don't know the PID - pidfile => $::master->[$idx]->{'path_mypid'}, - sockfile => $::master->[$idx]->{'path_mysock'}, - port => $::master->[$idx]->{'path_myport'}, + pidfile => $pidfile, + sockfile => $sockfile, + port => $port, }); + + mtr_debug(" - Master mysqld " . + "(idx: $idx; pid: '$pidfile'; socket: '$sockfile'; port: $port)"); + $::master->[$idx]->{'pid'}= 0; # Assume we are done with it } - for ( my $idx; $idx < 3; $idx++ ) + for ( my $idx= 0; $idx < 3; $idx++ ) { + my $pidfile= $::slave->[$idx]->{'path_mypid'}; + my $sockfile= $::slave->[$idx]->{'path_mysock'}; + my $port= $::slave->[$idx]->{'path_myport'}; + push(@args,{ pid => 0, # We don't know the PID - pidfile => $::slave->[$idx]->{'path_mypid'}, - sockfile => $::slave->[$idx]->{'path_mysock'}, - port => $::slave->[$idx]->{'path_myport'}, + pidfile => $pidfile, + sockfile => $sockfile, + port => $port, }); + + mtr_debug(" - Slave mysqld " . + "(idx: $idx; pid: '$pidfile'; socket: '$sockfile'; port: $port)"); + + $::slave->[$idx]->{'pid'}= 0; # Assume we are done with it } mtr_mysqladmin_shutdown(\@args, 20); @@ -413,6 +449,8 @@ sub mtr_kill_leftovers () { # FIXME $path_run_dir or something my $rundir= "$::opt_vardir/run"; + mtr_debug("Processing PID files in directory '$rundir'..."); + if ( -d $rundir ) { opendir(RUNDIR, $rundir) @@ -426,8 +464,12 @@ sub mtr_kill_leftovers () { if ( -f $pidfile ) { + mtr_debug("Processing PID file: '$pidfile'..."); + my $pid= mtr_get_pid_from_file($pidfile); + mtr_debug("Got pid: $pid from file '$pidfile'"); + # Race, could have been removed between I tested with -f # and the unlink() below, so I better check again with -f @@ -438,14 +480,24 @@ sub mtr_kill_leftovers () { if ( $::glob_cygwin_perl or kill(0, $pid) ) { + mtr_debug("There is process with pid $pid -- scheduling for kill."); push(@pids, $pid); # We know (cygwin guess) it exists } + else + { + mtr_debug("There is no process with pid $pid -- skipping."); + } } } closedir(RUNDIR); if ( @pids ) { + mtr_debug("Killing the following processes with PID files: " . + join(' ', @pids) . "..."); + + start_reap_all(); + if ( $::glob_cygwin_perl ) { # We have no (easy) way of knowing the Cygwin controlling @@ -459,6 +511,7 @@ sub mtr_kill_leftovers () { my $retries= 10; # 10 seconds do { + mtr_debug("Sending SIGKILL to pids: " . join(' ', @pids)); kill(9, @pids); mtr_debug("Sleep 1 second waiting for processes to die"); sleep(1) # Wait one second @@ -469,19 +522,29 @@ sub mtr_kill_leftovers () { mtr_warning("can't kill process(es) " . join(" ", @pids)); } } + + stop_reap_all(); } } + else + { + mtr_debug("Directory for PID files ($rundir) does not exist."); + } # We may have failed everything, bug we now check again if we have # the listen ports free to use, and if they are free, just go for it. + mtr_debug("Checking known mysqld servers..."); + foreach my $srv ( @args ) { - if ( mtr_ping_mysqld_server($srv->{'port'}, $srv->{'sockfile'}) ) + if ( mtr_ping_mysqld_server($srv->{'port'}) ) { mtr_warning("can't kill old mysqld holding port $srv->{'port'}"); } } + + mtr_debug("mtr_kill_leftovers(): finished."); } ############################################################################## @@ -653,10 +716,15 @@ sub mtr_mysqladmin_shutdown { my %mysql_admin_pids; my @to_kill_specs; + mtr_debug("mtr_mysqladmin_shutdown(): starting..."); + mtr_debug("Collecting mysqld-instances to shutdown..."); + foreach my $srv ( @$spec ) { - if ( mtr_ping_mysqld_server($srv->{'port'}, $srv->{'sockfile'}) ) + if ( mtr_ping_mysqld_server($srv->{'port'}) ) { + mtr_debug("Mysqld (port: $srv->{port}) needs to be stopped."); + push(@to_kill_specs, $srv); } } @@ -688,6 +756,9 @@ sub mtr_mysqladmin_shutdown { mtr_add_arg($args, "--shutdown_timeout=$adm_shutdown_tmo"); mtr_add_arg($args, "shutdown"); + mtr_debug("Shutting down mysqld " . + "(port: $srv->{port}; socket: '$srv->{sockfile}')..."); + my $path_mysqladmin_log= "$::opt_vardir/log/mysqladmin.log"; my $pid= mtr_spawn($::exe_mysqladmin, $args, "", $path_mysqladmin_log, $path_mysqladmin_log, "", @@ -719,14 +790,18 @@ sub mtr_mysqladmin_shutdown { my $res= 1; # If we just fall through, we are done # in the sense that the servers don't # listen to their ports any longer + + mtr_debug("Waiting for mysqld servers to stop..."); + TIME: while ( $timeout-- ) { foreach my $srv ( @to_kill_specs ) { $res= 1; # We are optimistic - if ( mtr_ping_mysqld_server($srv->{'port'}, $srv->{'sockfile'}) ) + if ( mtr_ping_mysqld_server($srv->{'port'}) ) { + mtr_debug("Mysqld (port: $srv->{port}) is still alive."); mtr_debug("Sleep 1 second waiting for processes to stop using port"); sleep(1); # One second $res= 0; @@ -736,7 +811,14 @@ sub mtr_mysqladmin_shutdown { last; # If we got here, we are done } - $timeout or mtr_debug("At least one server is still listening to its port"); + if ($res) + { + mtr_debug("mtr_mysqladmin_shutdown(): All mysqld instances are down."); + } + else + { + mtr_debug("mtr_mysqladmin_shutdown(): At least one server is alive."); + } return $res; } @@ -795,7 +877,7 @@ sub stop_reap_all { $SIG{CHLD}= 'DEFAULT'; } -sub mtr_ping_mysqld_server () { +sub mtr_ping_mysqld_server ($) { my $port= shift; my $remote= "localhost"; @@ -810,13 +892,18 @@ sub mtr_ping_mysqld_server () { { mtr_error("can't create socket: $!"); } + + mtr_debug("Pinging server (port: $port)..."); + if ( connect(SOCK, $paddr) ) { + mtr_debug("Server (port: $port) is alive."); close(SOCK); # FIXME check error? return 1; } else { + mtr_debug("Server (port: $port) is dead."); return 0; } } @@ -886,34 +973,6 @@ sub mtr_kill_processes ($) { } } - -sub mtr_kill_process ($$$$) { - my $pid= shift; - my $signal= shift; - my $total_retries= shift; - my $timeout= shift; - - for (my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt) - { - mtr_debug("Sending $signal to $pid..."); - - kill($signal, $pid); - - unless (kill (0, $pid)) - { - mtr_debug("Process $pid died."); - return; - } - - mtr_debug("Sleeping $timeout second(s) waiting for processes to die..."); - - sleep($timeout); - } - - mtr_debug("Process $pid is still alive after $total_retries " . - "of sending signal $signal."); -} - ############################################################################## # # When we exit, we kill off all children @@ -943,4 +1002,676 @@ sub mtr_exit ($) { exit($code); } +############################################################################## +# +# Instance Manager management routines. +# +############################################################################## + +sub mtr_im_kill_process ($$$$) { + my $pid_lst= shift; + my $signal= shift; + my $total_retries= shift; + my $timeout= shift; + + my %pids; + + foreach my $pid (@{$pid_lst}) + { + $pids{$pid}= 1; + } + + for (my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt) + { + foreach my $pid (keys %pids) + { + mtr_debug("Sending $signal to $pid..."); + + kill($signal, $pid); + + unless (kill (0, $pid)) + { + mtr_debug("Process $pid died."); + delete $pids{$pid}; + } + } + + return if scalar keys %pids == 0; + + mtr_debug("Sleeping $timeout second(s) waiting for processes to die..."); + + sleep($timeout); + } + + mtr_debug("Process(es) " . + join(' ', keys %pids) . + " is still alive after $total_retries " . + "of sending signal $signal."); +} + +########################################################################### + +sub mtr_im_load_pids($) { + my $instance_manager= shift; + + mtr_debug("Loading PID files..."); + + # Obtain mysqld-process pids. + + my $instances = $instance_manager->{'instances'}; + + for (my $idx= 0; $idx < 2; ++$idx) + { + mtr_debug("IM-guarded mysqld[$idx] PID file: '" . + $instances->[$idx]->{'path_pid'} . "'."); + + my $mysqld_pid; + + if (-r $instances->[$idx]->{'path_pid'}) + { + $mysqld_pid= mtr_get_pid_from_file($instances->[$idx]->{'path_pid'}); + mtr_debug("IM-guarded mysqld[$idx] PID: $mysqld_pid."); + } + else + { + $mysqld_pid= undef; + mtr_debug("IM-guarded mysqld[$idx]: no PID file."); + } + + $instances->[$idx]->{'pid'}= $mysqld_pid; + } + + # Re-read Instance Manager PIDs from the file, since during tests Instance + # Manager could have been restarted, so its PIDs could have been changed. + + # - IM-main + + mtr_debug("IM-main PID file: '$instance_manager->{path_pid}'."); + + if (-f $instance_manager->{'path_pid'}) + { + $instance_manager->{'pid'} = + mtr_get_pid_from_file($instance_manager->{'path_pid'}); + + mtr_debug("IM-main PID: $instance_manager->{pid}."); + } + else + { + mtr_debug("IM-main: no PID file."); + $instance_manager->{'pid'}= undef; + } + + # - IM-angel + + mtr_debug("IM-angel PID file: '$instance_manager->{path_angel_pid}'."); + + if (-f $instance_manager->{'path_angel_pid'}) + { + $instance_manager->{'angel_pid'} = + mtr_get_pid_from_file($instance_manager->{'path_angel_pid'}); + + mtr_debug("IM-angel PID: $instance_manager->{'angel_pid'}."); + } + else + { + mtr_debug("IM-angel: no PID file."); + $instance_manager->{'angel_pid'} = undef; + } +} + +########################################################################### + +sub mtr_im_terminate($) { + my $instance_manager= shift; + + # Load pids from pid-files. We should do it first of all, because IM deletes + # them on shutdown. + + mtr_im_load_pids($instance_manager); + + mtr_debug("Shutting Instance Manager down..."); + + # Ignoring SIGCHLD so that all children could rest in peace. + + start_reap_all(); + + # Send SIGTERM to IM-main. + + if (defined $instance_manager->{'pid'}) + { + mtr_debug("IM-main pid: $instance_manager->{pid}."); + mtr_debug("Stopping IM-main..."); + + mtr_im_kill_process([ $instance_manager->{'pid'} ], 'TERM', 10, 1); + } + else + { + mtr_debug("IM-main pid: n/a."); + } + + # If IM-angel was alive, wait for it to die. + + if (defined $instance_manager->{'angel_pid'}) + { + mtr_debug("IM-angel pid: $instance_manager->{'angel_pid'}."); + mtr_debug("Waiting for IM-angel to die..."); + + my $total_attempts= 10; + + for (my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt) + { + unless (kill (0, $instance_manager->{'angel_pid'})) + { + mtr_debug("IM-angel died."); + last; + } + + sleep(1); + } + } + else + { + mtr_debug("IM-angel pid: n/a."); + } + + stop_reap_all(); + + # Re-load PIDs. + + mtr_im_load_pids($instance_manager); +} + +########################################################################### + +sub mtr_im_check_alive($) { + my $instance_manager= shift; + + mtr_debug("Checking whether IM-components are alive..."); + + return 1 if mtr_im_check_main_alive($instance_manager); + + return 1 if mtr_im_check_angel_alive($instance_manager); + + return 1 if mtr_im_check_mysqlds_alive($instance_manager); + + return 0; +} + +########################################################################### + +sub mtr_im_check_main_alive($) { + my $instance_manager= shift; + + # Check that the process, that we know to be IM's, is dead. + + if (defined $instance_manager->{'pid'}) + { + if (kill (0, $instance_manager->{'pid'})) + { + mtr_debug("IM-main (PID: $instance_manager->{pid}) is alive."); + return 1; + } + else + { + mtr_debug("IM-main (PID: $instance_manager->{pid}) is dead."); + } + } + else + { + mtr_debug("No PID file for IM-main."); + } + + # Check that IM does not accept client connections. + + if (mtr_ping_mysqld_server($instance_manager->{'port'})) + { + mtr_debug("IM-main (port: $instance_manager->{port}) " . + "is accepting connections."); + + mtr_im_errlog("IM-main is accepting connections on port " . + "$instance_manager->{port}, but there is no " . + "process information."); + return 1; + } + else + { + mtr_debug("IM-main (port: $instance_manager->{port}) " . + "does not accept connections."); + return 0; + } +} + +########################################################################### + +sub mtr_im_check_angel_alive($) { + my $instance_manager= shift; + + # Check that the process, that we know to be the Angel, is dead. + + if (defined $instance_manager->{'angel_pid'}) + { + if (kill (0, $instance_manager->{'angel_pid'})) + { + mtr_debug("IM-angel (PID: $instance_manager->{angel_pid}) is alive."); + return 1; + } + else + { + mtr_debug("IM-angel (PID: $instance_manager->{angel_pid}) is dead."); + return 0; + } + } + else + { + mtr_debug("No PID file for IM-angel."); + return 0; + } +} + +########################################################################### + +sub mtr_im_check_mysqlds_alive($) { + my $instance_manager= shift; + + mtr_debug("Checking for IM-guarded mysqld instances..."); + + my $instances = $instance_manager->{'instances'}; + + for (my $idx= 0; $idx < 2; ++$idx) + { + mtr_debug("Checking mysqld[$idx]..."); + + return 1 + if mtr_im_check_mysqld_alive($instance_manager, $instances->[$idx]); + } +} + +########################################################################### + +sub mtr_im_check_mysqld_alive($$) { + my $instance_manager= shift; + my $mysqld_instance= shift; + + # Check that the process is dead. + + if (defined $instance_manager->{'pid'}) + { + if (kill (0, $instance_manager->{'pid'})) + { + mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is alive."); + return 1; + } + else + { + mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is dead."); + } + } + else + { + mtr_debug("No PID file for mysqld instance."); + } + + # Check that mysqld does not accept client connections. + + if (mtr_ping_mysqld_server($mysqld_instance->{'port'})) + { + mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . + "is accepting connections."); + + mtr_im_errlog("Mysqld is accepting connections on port " . + "$mysqld_instance->{port}, but there is no " . + "process information."); + return 1; + } + else + { + mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . + "does not accept connections."); + return 0; + } +} + +########################################################################### + +sub mtr_im_cleanup($) { + my $instance_manager= shift; + + mtr_im_rm_file($instance_manager->{'path_pid'}); + mtr_im_rm_file($instance_manager->{'path_sock'}); + + mtr_im_rm_file($instance_manager->{'path_angel_pid'}); + + for (my $idx= 0; $idx < 2; ++$idx) + { + mtr_im_rm_file($instance_manager->{'instances'}->[$idx]->{'path_pid'}); + mtr_im_rm_file($instance_manager->{'instances'}->[$idx]->{'path_sock'}); + } +} + +########################################################################### + +sub mtr_im_rm_file($) +{ + my $file_path= shift; + + if (-f $file_path) + { + mtr_debug("Removing '$file_path'..."); + + mtr_warning("Can not remove '$file_path'.") + unless unlink($file_path); + } + else + { + mtr_debug("File '$file_path' does not exist already."); + } +} + +########################################################################### + +sub mtr_im_errlog($) { + my $msg= shift; + + # Complain in error log so that a warning will be shown. + # + # TODO: unless BUG#20761 is fixed, we will print the warning to stdout, so + # that it can be seen on console and does not produce pushbuild error. + + # my $errlog= "$opt_vardir/log/mysql-test-run.pl.err"; + # + # open (ERRLOG, ">>$errlog") || + # mtr_error("Can not open error log ($errlog)"); + # + # my $ts= localtime(); + # print ERRLOG + # "Warning: [$ts] $msg\n"; + # + # close ERRLOG; + + my $ts= localtime(); + print "Warning: [$ts] $msg\n"; +} + +########################################################################### + +sub mtr_im_kill($) { + my $instance_manager= shift; + + # Re-load PIDs. That can be useful because some processes could have been + # restarted. + + mtr_im_load_pids($instance_manager); + + # Ignoring SIGCHLD so that all children could rest in peace. + + start_reap_all(); + + # Kill IM-angel first of all. + + if (defined $instance_manager->{'angel_pid'}) + { + mtr_debug("Killing IM-angel (PID: $instance_manager->{angel_pid})..."); + mtr_im_kill_process([ $instance_manager->{'angel_pid'} ], 'KILL', 10, 1) + } + else + { + mtr_debug("IM-angel is dead."); + } + + # Re-load PIDs again. + + mtr_im_load_pids($instance_manager); + + # Kill IM-main. + + if (defined $instance_manager->{'pid'}) + { + mtr_debug("Killing IM-main (PID: $instance_manager->pid})..."); + mtr_im_kill_process([ $instance_manager->{'pid'} ], 'KILL', 10, 1); + } + else + { + mtr_debug("IM-main is dead."); + } + + # Re-load PIDs again. + + mtr_im_load_pids($instance_manager); + + # Kill guarded mysqld instances. + + my @mysqld_pids; + + mtr_debug("Collecting PIDs of mysqld instances to kill..."); + + for (my $idx= 0; $idx < 2; ++$idx) + { + my $pid= $instance_manager->{'instances'}->[$idx]->{'pid'}; + + next unless defined $pid; + + mtr_debug(" - IM-guarded mysqld[$idx] PID: $pid."); + + push (@mysqld_pids, $pid); + } + + if (scalar @mysqld_pids > 0) + { + mtr_debug("Killing IM-guarded mysqld instances..."); + mtr_im_kill_process(\@mysqld_pids, 'KILL', 10, 1); + } + + # That's all. + + stop_reap_all(); +} + +############################################################################## + +sub mtr_im_wait_for_connection($$$) { + my $instance_manager= shift; + my $total_attempts= shift; + my $connect_timeout= shift; + + mtr_debug("Waiting for IM on port $instance_manager->{port} " . + "to start accepting connections..."); + + for (my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt) + { + mtr_debug("Trying to connect to IM ($cur_attempt of $total_attempts)..."); + + if (mtr_ping_mysqld_server($instance_manager->{'port'})) + { + mtr_debug("IM is accepting connections " . + "on port $instance_manager->{port}."); + return 1; + } + + mtr_debug("Sleeping $connect_timeout..."); + sleep($connect_timeout); + } + + mtr_debug("IM does not accept connections " . + "on port $instance_manager->{port} after " . + ($total_attempts * $connect_timeout) . " seconds."); + + return 0; +} + +############################################################################## + +sub mtr_im_wait_for_mysqld($$$) { + my $mysqld= shift; + my $total_attempts= shift; + my $connect_timeout= shift; + + mtr_debug("Waiting for IM-guarded mysqld on port $mysqld->{port} " . + "to start accepting connections..."); + + for (my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt) + { + mtr_debug("Trying to connect to mysqld " . + "($cur_attempt of $total_attempts)..."); + + if (mtr_ping_mysqld_server($mysqld->{'port'})) + { + mtr_debug("Mysqld is accepting connections " . + "on port $mysqld->{port}."); + return 1; + } + + mtr_debug("Sleeping $connect_timeout..."); + sleep($connect_timeout); + } + + mtr_debug("Mysqld does not accept connections " . + "on port $mysqld->{port} after " . + ($total_attempts * $connect_timeout) . " seconds."); + + return 0; +} + +############################################################################## + +sub mtr_im_start($$) { + my $instance_manager = shift; + my $opts = shift; + + mtr_debug("Starting Instance Manager..."); + + my $args; + mtr_init_args(\$args); + mtr_add_arg($args, "--defaults-file=%s", + $instance_manager->{'defaults_file'}); + + foreach my $opt (@{$opts}) + { + mtr_add_arg($args, $opt); + } + + $instance_manager->{'pid'} = + mtr_spawn( + $::exe_im, # path to the executable + $args, # cmd-line args + '', # stdin + $instance_manager->{'path_log'}, # stdout + $instance_manager->{'path_err'}, # stderr + '', # pid file path (not used) + { append_log_file => 1 } # append log files + ); + + if ( ! $instance_manager->{'pid'} ) + { + mtr_report('Could not start Instance Manager'); + return; + } + + # Instance Manager can be run in daemon mode. In this case, it creates + # several processes and the parent process, created by mtr_spawn(), exits just + # after start. So, we have to obtain Instance Manager PID from the PID file. + + if ( ! sleep_until_file_created( + $instance_manager->{'path_pid'}, + $instance_manager->{'start_timeout'}, + -1)) # real PID is still unknown + { + mtr_report("Instance Manager PID file is missing"); + return; + } + + $instance_manager->{'pid'} = + mtr_get_pid_from_file($instance_manager->{'path_pid'}); + + mtr_debug("Instance Manager started. PID: $instance_manager->{pid}."); + + # Wait until we can connect to IM. + + my $IM_CONNECT_TIMEOUT= 30; + + unless (mtr_im_wait_for_connection($instance_manager, + $IM_CONNECT_TIMEOUT, 1)) + { + mtr_debug("Can not connect to Instance Manager " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_error("Can not connect to Instance Manager " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + } + + # Wait until we can connect to guarded mysqld-instances + # (in other words -- wait for IM to start guarded instances). + + for (my $idx= 0; $idx < 2; ++$idx) + { + my $mysqld= $instance_manager->{'instances'}->[$idx]; + + next if exists $mysqld->{'nonguarded'}; + + mtr_debug("Waiting for mysqld[$idx] to start..."); + + unless (mtr_im_wait_for_mysqld($mysqld, 30, 1)) + { + mtr_debug("Can not connect to mysqld[$idx] " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_error("Can not connect to mysqld[$idx] " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + } + + mtr_debug("mysqld[$idx] started."); + } + + mtr_debug("Instance Manager started."); +} + +############################################################################## + +sub mtr_im_stop($) { + my $instance_manager= shift; + + mtr_debug("Stopping Instance Manager..."); + + # Try graceful shutdown. + + mtr_im_terminate($instance_manager); + + # Check that all processes died. + + unless (mtr_im_check_alive($instance_manager)) + { + mtr_debug("Instance Manager has been stopped successfully."); + mtr_im_cleanup($instance_manager); + return 1; + } + + # Instance Manager don't want to die. We should kill it. + + mtr_im_errlog("Instance Manager did not shutdown gracefully."); + + mtr_im_kill($instance_manager); + + # Check again that all IM-related processes have been killed. + + my $im_is_alive= mtr_im_check_alive($instance_manager); + + mtr_im_cleanup($instance_manager); + + if ($im_is_alive) + { + mtr_error("Can not kill Instance Manager or its children."); + return 0; + } + + mtr_debug("Instance Manager has been killed successfully."); + return 1; +} + +########################################################################### + 1; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index afd79e9c887..7bca21e3ff6 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -336,7 +336,7 @@ sub snapshot_setup (); sub executable_setup (); sub environment_setup (); sub kill_running_server (); -sub kill_and_cleanup (); +sub cleanup_stale_files (); sub check_ssl_support (); sub check_running_as_root(); sub check_ndbcluster_support (); @@ -356,8 +356,6 @@ sub mysqld_arguments ($$$$$$); sub stop_masters_slaves (); sub stop_masters (); sub stop_slaves (); -sub im_start ($$); -sub im_stop ($); sub run_mysqltest ($); sub usage ($); @@ -499,7 +497,7 @@ sub command_line_setup () { my $opt_master_myport= 9306; my $opt_slave_myport= 9308; $opt_ndbcluster_port= 9350; - my $im_port= 9310; + my $im_port= 9311; my $im_mysqld1_port= 9312; my $im_mysqld2_port= 9314; @@ -1044,20 +1042,30 @@ sub executable_setup () { if ( $glob_win32 ) { $path_client_bindir= mtr_path_exists("$glob_basedir/client_release", - "$glob_basedir/client_debug", + "$glob_basedir/client_debug", + "$glob_basedir/client/release", + "$glob_basedir/client/debug", "$glob_basedir/bin",); $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-max-nt", "$path_client_bindir/mysqld-max", "$path_client_bindir/mysqld-nt", "$path_client_bindir/mysqld", "$path_client_bindir/mysqld-debug", - "$path_client_bindir/mysqld-max"); - $path_language= mtr_path_exists("$glob_basedir/share/english/"); - $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets"); + "$path_client_bindir/mysqld-max", + "$glob_basedir/sql/release/mysqld", + "$glob_basedir/sql/debug/mysqld"); + $path_language= mtr_path_exists("$glob_basedir/share/english/", + "$glob_basedir/sql/share/english/"); + $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets", + "$glob_basedir/sql/share/charsets/"); $exe_my_print_defaults= - mtr_exe_exists("$path_client_bindir/my_print_defaults"); + mtr_exe_exists("$path_client_bindir/my_print_defaults", + "$glob_basedir/extra/release/my_print_defaults", + "$glob_basedir/extra/debug/my_print_defaults"); $exe_perror= - mtr_exe_exists("$path_client_bindir/perror"); + mtr_exe_exists("$path_client_bindir/perror", + "$glob_basedir/extra/release/perror", + "$glob_basedir/extra/debug/perror"); } else { @@ -1088,6 +1096,9 @@ sub executable_setup () { $exe_mysql_client_test= mtr_exe_exists("$glob_basedir/tests/mysql_client_test", "$path_client_bindir/mysql_client_test", + "$glob_basedir/tests/release/mysql_client_test", + "$glob_basedir/tests/debug/mysql_client_test", + "$path_client_bindir/mysql_client_test", "/usr/bin/false"); } $exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck"); @@ -1098,7 +1109,8 @@ sub executable_setup () { $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin"); $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql"); $exe_mysql_fix_system_tables= - mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables"); + mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables", + "/usr/bin/false"); $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools"); $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm"; $lib_udf_example= @@ -1116,7 +1128,8 @@ sub executable_setup () { $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql"); $exe_mysql_fix_system_tables= mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables", - "$glob_basedir/scripts/mysql_fix_privilege_tables"); + "$glob_basedir/scripts/mysql_fix_privilege_tables", + "/usr/bin/false"); $exe_my_print_defaults= mtr_exe_exists("$path_client_bindir/my_print_defaults"); $exe_perror= @@ -1150,7 +1163,9 @@ sub executable_setup () { } else { - $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest"); + $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest", + "$glob_basedir/client/release/mysqltest", + "$glob_basedir/client/debug/mysqltest"); $exe_mysql_client_test= mtr_exe_exists("$path_client_bindir/mysql_client_test", "/usr/bin/false"); # FIXME temporary @@ -1303,6 +1318,7 @@ sub kill_running_server () { mtr_report("Killing Possible Leftover Processes"); mkpath("$opt_vardir/log"); # Needed for mysqladmin log + mtr_kill_leftovers(); $using_ndbcluster_master= $opt_with_ndbcluster; @@ -1311,9 +1327,7 @@ sub kill_running_server () { } } -sub kill_and_cleanup () { - - kill_running_server (); +sub cleanup_stale_files () { mtr_report("Removing Stale Files"); @@ -1692,13 +1706,11 @@ sub run_suite () { sub initialize_servers () { if ( ! $glob_use_running_server ) { - if ( $opt_start_dirty ) - { - kill_running_server(); - } - else + kill_running_server(); + + unless ( $opt_start_dirty ) { - kill_and_cleanup(); + cleanup_stale_files(); mysql_install_db(); if ( $opt_force ) { @@ -2100,7 +2112,7 @@ sub run_testcase ($) { im_create_defaults_file($instance_manager); - im_start($instance_manager, $tinfo->{im_opts}); + mtr_im_start($instance_manager, $tinfo->{im_opts}); } # ---------------------------------------------------------------------- @@ -2195,10 +2207,9 @@ sub run_testcase ($) { # Stop Instance Manager if we are processing an IM-test case. # ---------------------------------------------------------------------- - if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' and - $instance_manager->{'pid'} ) + if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' ) { - im_stop($instance_manager); + mtr_im_stop($instance_manager); } } @@ -2726,11 +2737,8 @@ sub stop_masters_slaves () { print "Ending Tests\n"; - if ( $instance_manager->{'pid'} ) - { - print "Shutting-down Instance Manager\n"; - im_stop($instance_manager); - } + print "Shutting-down Instance Manager\n"; + mtr_im_stop($instance_manager); print "Shutting-down MySQL daemon\n\n"; stop_masters(); @@ -2792,230 +2800,6 @@ sub stop_slaves () { mtr_stop_mysqld_servers(\@args); } -############################################################################## -# -# Instance Manager management routines. -# -############################################################################## - -sub im_start($$) { - my $instance_manager = shift; - my $opts = shift; - - my $args; - mtr_init_args(\$args); - mtr_add_arg($args, "--defaults-file=%s", - $instance_manager->{'defaults_file'}); - - foreach my $opt (@{$opts}) - { - mtr_add_arg($args, $opt); - } - - $instance_manager->{'pid'} = - mtr_spawn( - $exe_im, # path to the executable - $args, # cmd-line args - '', # stdin - $instance_manager->{'path_log'}, # stdout - $instance_manager->{'path_err'}, # stderr - '', # pid file path (not used) - { append_log_file => 1 } # append log files - ); - - if ( ! $instance_manager->{'pid'} ) - { - mtr_report('Could not start Instance Manager'); - return; - } - - # Instance Manager can be run in daemon mode. In this case, it creates - # several processes and the parent process, created by mtr_spawn(), exits just - # after start. So, we have to obtain Instance Manager PID from the PID file. - - if ( ! sleep_until_file_created( - $instance_manager->{'path_pid'}, - $instance_manager->{'start_timeout'}, - -1)) # real PID is still unknown - { - mtr_report("Instance Manager PID file is missing"); - return; - } - - $instance_manager->{'pid'} = - mtr_get_pid_from_file($instance_manager->{'path_pid'}); -} - - -sub im_stop($) { - my $instance_manager = shift; - - # Obtain mysqld-process pids before we start stopping IM (it can delete pid - # files). - - my @mysqld_pids = (); - my $instances = $instance_manager->{'instances'}; - - push(@mysqld_pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'})) - if -r $instances->[0]->{'path_pid'}; - - push(@mysqld_pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'})) - if -r $instances->[1]->{'path_pid'}; - - # Re-read pid from the file, since during tests Instance Manager could have - # been restarted, so its pid could have been changed. - - $instance_manager->{'pid'} = - mtr_get_pid_from_file($instance_manager->{'path_pid'}) - if -f $instance_manager->{'path_pid'}; - - if (-f $instance_manager->{'path_angel_pid'}) - { - $instance_manager->{'angel_pid'} = - mtr_get_pid_from_file($instance_manager->{'path_angel_pid'}) - } - else - { - $instance_manager->{'angel_pid'} = undef; - } - - # Inspired from mtr_stop_mysqld_servers(). - - start_reap_all(); - - # Try graceful shutdown. - - mtr_debug("IM-main pid: $instance_manager->{'pid'}"); - mtr_debug("Stopping IM-main..."); - - mtr_kill_process($instance_manager->{'pid'}, 'TERM', 10, 1); - - # If necessary, wait for angel process to die. - - if (defined $instance_manager->{'angel_pid'}) - { - mtr_debug("IM-angel pid: $instance_manager->{'angel_pid'}"); - mtr_debug("Waiting for IM-angel to die..."); - - my $total_attempts= 10; - - for (my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt) - { - unless (kill (0, $instance_manager->{'angel_pid'})) - { - mtr_debug("IM-angel died."); - last; - } - - sleep(1); - } - } - - # Check that all processes died. - - my $clean_shutdown= 0; - - while (1) - { - # Check that IM-main died. - - if (kill (0, $instance_manager->{'pid'})) - { - mtr_debug("IM-main is still alive."); - last; - } - - # Check that IM-angel died. - - if (defined $instance_manager->{'angel_pid'} && - kill (0, $instance_manager->{'angel_pid'})) - { - mtr_debug("IM-angel is still alive."); - last; - } - - # Check that all guarded mysqld-instances died. - - my $guarded_mysqlds_dead= 1; - - foreach my $pid (@mysqld_pids) - { - if (kill (0, $pid)) - { - mtr_debug("Guarded mysqld ($pid) is still alive."); - $guarded_mysqlds_dead= 0; - last; - } - } - - last unless $guarded_mysqlds_dead; - - # Ok, all necessary processes are dead. - - $clean_shutdown= 1; - last; - } - - # Kill leftovers (the order is important). - - if ($clean_shutdown) - { - mtr_debug("IM-shutdown was clean -- all processed died."); - } - else - { - mtr_debug("IM failed to shutdown gracefully. We have to clean the mess..."); - } - - unless ($clean_shutdown) - { - - if (defined $instance_manager->{'angel_pid'}) - { - mtr_debug("Killing IM-angel..."); - mtr_kill_process($instance_manager->{'angel_pid'}, 'KILL', 10, 1) - } - - mtr_debug("Killing IM-main..."); - mtr_kill_process($instance_manager->{'pid'}, 'KILL', 10, 1); - - # Shutdown managed mysqld-processes. Some of them may be nonguarded, so IM - # will not stop them on shutdown. So, we should firstly try to end them - # legally. - - mtr_debug("Killing guarded mysqld(s)..."); - mtr_kill_processes(\@mysqld_pids); - - # Complain in error log so that a warning will be shown. - # - # TODO: unless BUG#20761 is fixed, we will print the warning - # to stdout, so that it can be seen on console and does not - # produce pushbuild error. - - # my $errlog= "$opt_vardir/log/mysql-test-run.pl.err"; - # - # open (ERRLOG, ">>$errlog") || - # mtr_error("Can not open error log ($errlog)"); - # - # my $ts= localtime(); - # print ERRLOG - # "Warning: [$ts] Instance Manager did not shutdown gracefully.\n"; - # - # close ERRLOG; - - my $ts= localtime(); - print "Warning: [$ts] Instance Manager did not shutdown gracefully.\n"; - } - - # That's all. - - stop_reap_all(); - - $instance_manager->{'pid'} = undef; - $instance_manager->{'angel_pid'} = undef; -} - - # # Run include/check-testcase.test # Before a testcase, run in record mode, save result file to var diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index 996f6fa8645..4e145346081 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -248,3 +248,14 @@ select rpad(c1,3,'ö'), rpad('ö',3,c1) from t1; rpad(c1,3,'ö') rpad('ö',3,c1) ßöö ößß drop table t1; +set names koi8r; +create table t1(a char character set cp1251 default _koi8r 0xFF); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(1) character set cp1251 default 'ÿ' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1(a char character set latin1 default _cp1251 0xFF); +ERROR 42000: Invalid default value for 'a' +End of 4.1 tests diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 890cdfd5cfc..3b6bfa6d776 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -730,6 +730,45 @@ id MIN(s) 1 ZZZ 2 ZZZ DROP TABLE t1; +drop table if exists bug20536; +set names latin1; +create table bug20536 (id bigint not null auto_increment primary key, name +varchar(255) character set ucs2 not null); +insert into `bug20536` (`id`,`name`) values (1, _latin1 x'7465737431'), (2, "'test\\_2'"); +select md5(name) from bug20536; +md5(name) +f4b7ce8b45a20e3c4e84bef515d1525c +48d95db0d8305c2fe11548a3635c9385 +select sha1(name) from bug20536; +sha1(name) +e0b52f38deddb9f9e8d5336b153592794cb49baf +677d4d505355eb5b0549b865fcae4b7f0c28aef5 +select make_set(3, name, upper(name)) from bug20536; +make_set(3, name, upper(name)) +test1,TEST1 +'test\_2','TEST\_2' +select export_set(5, name, upper(name)) from bug20536; +export_set(5, name, upper(name)) +test1,TEST1,test1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1 +'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2' +select export_set(5, name, upper(name), ",", 5) from bug20536; +export_set(5, name, upper(name), ",", 5) +test1,TEST1,test1,TEST1,TEST1 +'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2' +select password(name) from bug20536; +password(name) +???????????????????? +???????????????????? +select old_password(name) from bug20536; +old_password(name) +???????? +???????? +select quote(name) from bug20536; +quote(name) +???????? +???????????????? +drop table bug20536; +End of 4.1 tests CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3)); INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0); update t1 set b=a; @@ -765,3 +804,4 @@ blob 65535 65535 text 65535 65535 text 65535 32767 drop table t1; +End of 5.0 tests diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index f78fe3521fa..51f361349e6 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -924,6 +924,37 @@ NULL select ifnull(NULL, _utf8'string'); ifnull(NULL, _utf8'string') string +set names utf8; +create table t1 (s1 char(5) character set utf8 collate utf8_lithuanian_ci); +insert into t1 values ('I'),('K'),('Y'); +select * from t1 where s1 < 'K' and s1 = 'Y'; +s1 +I +Y +select * from t1 where 'K' > s1 and s1 = 'Y'; +s1 +I +Y +drop table t1; +create table t1 (s1 char(5) character set utf8 collate utf8_czech_ci); +insert into t1 values ('c'),('d'),('h'),('ch'),('CH'),('cH'),('Ch'),('i'); +select * from t1 where s1 > 'd' and s1 = 'CH'; +s1 +ch +CH +Ch +select * from t1 where 'd' < s1 and s1 = 'CH'; +s1 +ch +CH +Ch +select * from t1 where s1 = 'cH' and s1 <> 'ch'; +s1 +cH +select * from t1 where 'cH' = s1 and s1 <> 'ch'; +s1 +cH +drop table t1; create table t1 (a varchar(255)) default character set utf8; insert into t1 values (1.0); drop table t1; @@ -1309,6 +1340,19 @@ select a from t1 group by a; a e drop table t1; +set names utf8; +grant select on test.* to юзер_юзер@localhost; +user() +юзер_юзер@localhost +revoke all on test.* from юзер_юзер@localhost; +drop user юзер_юзер@localhost; +create database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +use имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +select database(); +database() +имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45 +drop database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +use test; CREATE TABLE t1(id varchar(20) NOT NULL) DEFAULT CHARSET=utf8; INSERT INTO t1 VALUES ('xxx'), ('aa'), ('yyy'), ('aa'); SELECT id FROM t1; diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result index 979e5d48871..d122dabc4ec 100644 --- a/mysql-test/r/drop.result +++ b/mysql-test/r/drop.result @@ -72,3 +72,16 @@ show tables; Tables_in_test t1 drop table t1; +drop database if exists mysqltest; +drop table if exists t1; +create table t1 (i int); +lock tables t1 read; +create database mysqltest; + drop table t1; +show open tables; + drop database mysqltest; +select 1; +1 +1 +unlock tables; +End of 5.0 tests diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 33e642c74c4..f0262acd71e 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -87,6 +87,10 @@ SELECT IS_USED_LOCK('bug16501'); IS_USED_LOCK('bug16501') NULL DROP TABLE t1; +select export_set(3, _latin1'foo', _utf8'bar', ',', 4); +export_set(3, _latin1'foo', _utf8'bar', ',', 4) +foo,foo,bar,bar +End of 4.1 tests create table t1 as select uuid(), length(uuid()); show create table t1; Table Create Table @@ -130,3 +134,4 @@ timediff(b, a) >= '00:00:03' drop table t2; drop table t1; set global query_cache_size=default; +End of 5.0 tests diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index b9533104b76..dc6a4561531 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -1053,3 +1053,15 @@ id day id day 3 2005-07-01 3 2005-07-15 DROP TABLE t1,t2; set time_zone= @@global.time_zone; +SET NAMES latin1; +SET character_set_results = NULL; +SHOW VARIABLES LIKE 'character_set_results'; +Variable_name Value +character_set_results +CREATE TABLE testBug8868 (field1 DATE, field2 VARCHAR(32) CHARACTER SET BINARY); +INSERT INTO testBug8868 VALUES ('2006-09-04', 'abcd'); +SELECT DATE_FORMAT(field1,'%b-%e %l:%i%p') as fmtddate, field2 FROM testBug8868; +fmtddate field2 +Sep-4 12:00AM abcd +DROP TABLE testBug8868; +SET NAMES DEFAULT; diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 0b2cfd5ebb0..2f417a41652 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -943,6 +943,31 @@ DROP TABLE mysqltest3.t_nn; DROP DATABASE mysqltest3; REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'mysqltest_1'@'localhost'; DROP USER 'mysqltest_1'@'localhost'; +use test; create user mysqltest1_thisisreallytoolong; -ERROR HY000: Operation CREATE USER failed for 'mysqltest1_thisisreallytoolong'@'%' +ERROR HY000: String 'mysqltest1_thisisreallytoolong' is too long for user name (should be no longer than 16) +GRANT CREATE ON mysqltest.* TO 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +GRANT CREATE ON mysqltest.* TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +REVOKE CREATE ON mysqltest.* FROM 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +REVOKE CREATE ON mysqltest.* FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +GRANT CREATE ON t1 TO 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +GRANT CREATE ON t1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +REVOKE CREATE ON t1 FROM 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +REVOKE CREATE ON t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +GRANT EXECUTE ON PROCEDURE p1 TO 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +GRANT EXECUTE ON PROCEDURE p1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +REVOKE EXECUTE ON PROCEDURE p1 FROM 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +REVOKE EXECUTE ON PROCEDURE t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) End of 5.0 tests diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result index c9d3db5e8e8..5b9c7f2244f 100644 --- a/mysql-test/r/heap_btree.result +++ b/mysql-test/r/heap_btree.result @@ -294,3 +294,4 @@ DROP TABLE t1; CREATE TABLE t1 (a INT, UNIQUE USING BTREE(a)) ENGINE=MEMORY; INSERT INTO t1 VALUES(NULL),(NULL); DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result index 4f7dd77a88f..b805bdc9166 100644 --- a/mysql-test/r/im_daemon_life_cycle.result +++ b/mysql-test/r/im_daemon_life_cycle.result @@ -1,4 +1,3 @@ -Success: the process has been started. SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/r/im_life_cycle.result b/mysql-test/r/im_life_cycle.result index 53737b64f28..69f6bb5a490 100644 --- a/mysql-test/r/im_life_cycle.result +++ b/mysql-test/r/im_life_cycle.result @@ -1,4 +1,3 @@ -Success: the process has been started. SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/r/im_options_set.result b/mysql-test/r/im_options_set.result index c3035079b39..f7b7e8eaef7 100644 --- a/mysql-test/r/im_options_set.result +++ b/mysql-test/r/im_options_set.result @@ -1,4 +1,3 @@ -Success: the process has been started. SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/r/im_options_unset.result b/mysql-test/r/im_options_unset.result index ba468c78a5b..2ab775e611a 100644 --- a/mysql-test/r/im_options_unset.result +++ b/mysql-test/r/im_options_unset.result @@ -1,4 +1,3 @@ -Success: the process has been started. SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/r/im_utils.result b/mysql-test/r/im_utils.result index be696921812..f671089d31d 100644 --- a/mysql-test/r/im_utils.result +++ b/mysql-test/r/im_utils.result @@ -1,4 +1,3 @@ -Success: the process has been started. SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result index 1e38f762dd1..be2776ef533 100644 --- a/mysql-test/r/limit.result +++ b/mysql-test/r/limit.result @@ -76,3 +76,17 @@ a a 1 drop table t1; +create table t1 (a int); +insert into t1 values (1),(2),(3),(4),(5),(6),(7); +explain select count(*) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 7 Using where; Using temporary +select count(*) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +c +7 +explain select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 7 Using where; Using temporary +select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +c +28 diff --git a/mysql-test/r/loaddata_autocom_innodb.result b/mysql-test/r/loaddata_autocom_innodb.result new file mode 100644 index 00000000000..10da6b5dde7 --- /dev/null +++ b/mysql-test/r/loaddata_autocom_innodb.result @@ -0,0 +1,21 @@ +SET SESSION STORAGE_ENGINE = InnoDB; +drop table if exists t1; +create table t1 (a text, b text); +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +commit; +select count(*) from t1; +count(*) +4 +truncate table t1; +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +rollback; +select count(*) from t1; +count(*) +0 +drop table t1; diff --git a/mysql-test/r/loaddata_autocom_ndb.result b/mysql-test/r/loaddata_autocom_ndb.result new file mode 100644 index 00000000000..94e5f825fa2 --- /dev/null +++ b/mysql-test/r/loaddata_autocom_ndb.result @@ -0,0 +1,23 @@ +SET SESSION STORAGE_ENGINE = ndbcluster; +drop table if exists t1; +create table t1 (a text, b text); +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +commit; +select count(*) from t1; +count(*) +4 +truncate table t1; +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +4 +drop table t1; diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index ba4e9daf7cb..99633f5e12a 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -59,16 +59,16 @@ database() test unlock tables; drop table t1; -ソ -ソ +ƒ\ +ƒ\ c_cp932 +ƒ\ +ƒ\ +ƒ\ ソ ソ -ソ -ソ -ソ -ソ -ソ +ƒ\ +ƒ\ +----------------------+------------+--------+ | concat('>',col1,'<') | col2 | col3 | +----------------------+------------+--------+ diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 6669b33e1bb..1d131c67c73 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1403,92 +1403,6 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; -create database db1; -use db1; -CREATE TABLE t2 ( -a varchar(30) default NULL, -KEY a (a(5)) -); -INSERT INTO t2 VALUES ('alfred'); -INSERT INTO t2 VALUES ('angie'); -INSERT INTO t2 VALUES ('bingo'); -INSERT INTO t2 VALUES ('waffle'); -INSERT INTO t2 VALUES ('lemon'); -create view v2 as select * from t2 where a like 'a%' with check option; - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -DROP TABLE IF EXISTS `t2`; -CREATE TABLE `t2` ( - `a` varchar(30) default NULL, - KEY `a` (`a`(5)) -) ENGINE=MyISAM DEFAULT CHARSET=latin1; - -LOCK TABLES `t2` WRITE; -/*!40000 ALTER TABLE `t2` DISABLE KEYS */; -INSERT INTO `t2` VALUES ('alfred'),('angie'),('bingo'),('waffle'),('lemon'); -/*!40000 ALTER TABLE `t2` ENABLE KEYS */; -UNLOCK TABLES; -DROP TABLE IF EXISTS `v2`; -/*!50001 DROP VIEW IF EXISTS `v2`*/; -/*!50001 CREATE TABLE `v2` ( - `a` varchar(30) -) */; -/*!50001 DROP TABLE IF EXISTS `v2`*/; -/*!50001 DROP VIEW IF EXISTS `v2`*/; -/*!50001 CREATE ALGORITHM=UNDEFINED */ -/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `v2` AS select `t2`.`a` AS `a` from `t2` where (`t2`.`a` like _latin1'a%') */ -/*!50002 WITH CASCADED CHECK OPTION */; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - -drop table t2; -drop view v2; -drop database db1; -create database db2; -use db2; -create table t1 (a int); -create table t2 (a int, b varchar(10), primary key(a)); -insert into t2 values (1, "on"), (2, "off"), (10, "pol"), (12, "meg"); -insert into t1 values (289), (298), (234), (456), (789); -create view v1 as select * from t2; -create view v2 as select * from t1; -drop table t1, t2; -drop view v1, v2; -drop database db2; -create database db1; -use db1; -show tables; -Tables_in_db1 -t1 -t2 -v1 -v2 -select * from t2 order by a; -a b -1 on -2 off -10 pol -12 meg -drop table t1, t2; -drop database db1; ---fields-optionally-enclosed-by=" CREATE DATABASE mysqldump_test_db; USE mysqldump_test_db; CREATE TABLE t1 ( a INT ); @@ -1681,6 +1595,7 @@ select * from t1; a b Osnabrück Köln drop table t1; +--fields-optionally-enclosed-by=" create table `t1` ( t1_name varchar(255) default null, t1_id int(10) unsigned not null auto_increment, @@ -1718,7 +1633,162 @@ t1 CREATE TABLE `t1` ( KEY `t1_name` (`t1_name`) ) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1 drop table `t1`; +create table t1(a int); +create table t2(a int); +create table t3(a int); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t3`; +CREATE TABLE `t3` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS `t2`; +CREATE TABLE `t2` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +drop table t1, t2, t3; +create table t1 (a int); +mysqldump: Couldn't execute 'SELECT /*!40001 SQL_NO_CACHE */ * FROM `t1` WHERE xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 (1064) +mysqldump: Got error: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 when retrieving data from server + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +drop table t1; End of 4.1 tests +create database db1; +use db1; +CREATE TABLE t2 ( +a varchar(30) default NULL, +KEY a (a(5)) +); +INSERT INTO t2 VALUES ('alfred'); +INSERT INTO t2 VALUES ('angie'); +INSERT INTO t2 VALUES ('bingo'); +INSERT INTO t2 VALUES ('waffle'); +INSERT INTO t2 VALUES ('lemon'); +create view v2 as select * from t2 where a like 'a%' with check option; + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t2`; +CREATE TABLE `t2` ( + `a` varchar(30) default NULL, + KEY `a` (`a`(5)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +LOCK TABLES `t2` WRITE; +/*!40000 ALTER TABLE `t2` DISABLE KEYS */; +INSERT INTO `t2` VALUES ('alfred'),('angie'),('bingo'),('waffle'),('lemon'); +/*!40000 ALTER TABLE `t2` ENABLE KEYS */; +UNLOCK TABLES; +DROP TABLE IF EXISTS `v2`; +/*!50001 DROP VIEW IF EXISTS `v2`*/; +/*!50001 CREATE TABLE `v2` ( + `a` varchar(30) +) */; +/*!50001 DROP TABLE IF EXISTS `v2`*/; +/*!50001 DROP VIEW IF EXISTS `v2`*/; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ +/*!50001 VIEW `v2` AS select `t2`.`a` AS `a` from `t2` where (`t2`.`a` like _latin1'a%') */ +/*!50002 WITH CASCADED CHECK OPTION */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +drop table t2; +drop view v2; +drop database db1; +use test; +create database db2; +use db2; +create table t1 (a int); +create table t2 (a int, b varchar(10), primary key(a)); +insert into t2 values (1, "on"), (2, "off"), (10, "pol"), (12, "meg"); +insert into t1 values (289), (298), (234), (456), (789); +create view v1 as select * from t2; +create view v2 as select * from t1; +drop table t1, t2; +drop view v1, v2; +drop database db2; +use test; +create database db1; +use db1; +show tables; +Tables_in_db1 +t1 +t2 +v1 +v2 +select * from t2 order by a; +a b +1 on +2 off +10 pol +12 meg +drop table t1, t2; +drop database db1; +use test; create table t1(a int); create view v1 as select * from t1; @@ -2623,44 +2693,6 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1; -create table t1(a int); -create table t2(a int); -create table t3(a int); - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -DROP TABLE IF EXISTS `t3`; -CREATE TABLE `t3` ( - `a` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; -DROP TABLE IF EXISTS `t1`; -CREATE TABLE `t1` ( - `a` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; -DROP TABLE IF EXISTS `t2`; -CREATE TABLE `t2` ( - `a` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - -drop table t1, t2, t3; -End of 4.1 tests create table t1 (a int); insert into t1 values (289), (298), (234), (456), (789); create definer = CURRENT_USER view v1 as select * from t1; @@ -2892,3 +2924,19 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; drop table t1; drop user mysqltest_1@localhost; +create database mysqldump_myDB; +use mysqldump_myDB; +create user myDB_User; +grant create view, select on mysqldump_myDB.* to myDB_User@localhost; +create table t1 (c1 int); +insert into t1 values (3); +use mysqldump_myDB; +create view v1 (c1) as select * from t1; +use mysqldump_myDB; +drop view v1; +drop table t1; +revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; +drop user myDB_User; +drop database mysqldump_myDB; +use test; +End of 5.0 tests diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index d73dd03fc57..080187cfa7b 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1297,3 +1297,18 @@ ERROR 3D000: No database selected create temporary table t1 (i int); ERROR 3D000: No database selected use test; +DROP TABLE IF EXISTS t1, t2, t3; +CREATE TABLE t1 (i BIGINT, j BIGINT); +CREATE TABLE t2 (i BIGINT); +CREATE TABLE t3 (i BIGINT, j BIGINT); +PREPARE stmt FROM "SELECT * FROM t1 JOIN t2 ON (t2.i = t1.i) + LEFT JOIN t3 ON ((t3.i, t3.j) = (t1.i, t1.j)) + WHERE t1.i = ?"; +SET @a= 1; +EXECUTE stmt USING @a; +i j i i j +EXECUTE stmt USING @a; +i j i i j +DEALLOCATE PREPARE stmt; +DROP TABLE IF EXISTS t1, t2, t3; +End of 5.0 tests. diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 926a980f9c4..a735b52a26f 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -947,18 +947,24 @@ COUNT(*) Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 +Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' +Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 +Warning 1292 Truncated incorrect DOUBLE value: '20050328 invalid' +Warning 1292 Truncated incorrect DOUBLE value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 +Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' +Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index 5c2c6e7e965..3edf56496fe 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -896,3 +896,48 @@ EXPLAIN SELECT * FROM t1 WHERE 0 NOT BETWEEN b AND c; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index_merge idx1,idx2 idx1,idx2 4,4 NULL 4 Using sort_union(idx1,idx2); Using where DROP TABLE t1; +CREATE TABLE t1 ( +item char(20) NOT NULL default '', +started datetime NOT NULL default '0000-00-00 00:00:00', +price decimal(16,3) NOT NULL default '0.000', +PRIMARY KEY (item,started) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES +('A1','2005-11-01 08:00:00',1000), +('A1','2005-11-15 00:00:00',2000), +('A1','2005-12-12 08:00:00',3000), +('A2','2005-12-01 08:00:00',1000); +EXPLAIN SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref PRIMARY PRIMARY 20 const 2 Using where +Warnings: +Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1 +Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1 +SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; +item started price +A1 2005-11-01 08:00:00 1000.000 +A1 2005-11-15 00:00:00 2000.000 +Warnings: +Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1 +Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1 +SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-02 00:00:00'; +item started price +A1 2005-11-01 08:00:00 1000.000 +A1 2005-11-15 00:00:00 2000.000 +DROP INDEX `PRIMARY` ON t1; +EXPLAIN SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where +Warnings: +Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1 +SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; +item started price +A1 2005-11-01 08:00:00 1000.000 +A1 2005-11-15 00:00:00 2000.000 +Warnings: +Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1 +SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-02 00:00:00'; +item started price +A1 2005-11-01 08:00:00 1000.000 +A1 2005-11-15 00:00:00 2000.000 +DROP TABLE t1; diff --git a/mysql-test/r/rpl_ndb_innodb_trans.result b/mysql-test/r/rpl_ndb_innodb_trans.result new file mode 100644 index 00000000000..148e6247b03 --- /dev/null +++ b/mysql-test/r/rpl_ndb_innodb_trans.result @@ -0,0 +1,103 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +create table t1 (a int, unique(a)) engine=ndbcluster; +create table t2 (a int, unique(a)) engine=innodb; +begin; +insert into t1 values(1); +insert into t2 values(1); +rollback; +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +delete from t1; +delete from t2; +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +delete from t1; +delete from t2; +begin; +insert into t2 values(3),(4); +insert into t1 values(3),(4); +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +4 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +4 +select count(*) from t2; +count(*) +0 +drop table t1,t2; diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index da1fc58db57..85ea624ce2f 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -634,6 +634,45 @@ flush tables; return 5; end| ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin reset query cache; +return 1; end| +ERROR 0A000: RESET is not allowed in stored function or trigger +create function bug8409() returns int begin reset master; +return 1; end| +ERROR 0A000: RESET is not allowed in stored function or trigger +create function bug8409() returns int begin reset slave; +return 1; end| +ERROR 0A000: RESET is not allowed in stored function or trigger +create function bug8409() returns int begin flush hosts; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush privileges; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush tables with read lock; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush tables; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush logs; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush status; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush slave; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush master; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush des_key_file; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush user_resources; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger create procedure bug9529_901234567890123456789012345678901234567890123456789012345() begin end| diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 88a860d6c8a..854935b071b 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4872,8 +4872,6 @@ declare continue handler for sqlexception begin end; select no_such_function(); end| call bug18787()| -no_such_function() -NULL drop procedure bug18787| create database bug18344_012345678901| use bug18344_012345678901| @@ -5222,6 +5220,126 @@ CHARSET(p3) COLLATION(p3) greek greek_general_ci use test| DROP DATABASE mysqltest1| +drop table if exists t3| +drop table if exists t4| +drop procedure if exists bug8153_subselect| +drop procedure if exists bug8153_subselect_a| +drop procedure if exists bug8153_subselect_b| +drop procedure if exists bug8153_proc_a| +drop procedure if exists bug8153_proc_b| +create table t3 (a int)| +create table t4 (a int)| +insert into t3 values (1), (1), (2), (3)| +insert into t4 values (1), (1)| +create procedure bug8153_subselect() +begin +declare continue handler for sqlexception +begin +select 'statement failed'; +end; +update t3 set a=a+1 where (select a from t4 where a=1) is null; +select 'statement after update'; +end| +call bug8153_subselect()| +statement failed +statement failed +statement after update +statement after update +select * from t3| +a +1 +1 +2 +3 +call bug8153_subselect()| +statement failed +statement failed +statement after update +statement after update +select * from t3| +a +1 +1 +2 +3 +drop procedure bug8153_subselect| +create procedure bug8153_subselect_a() +begin +declare continue handler for sqlexception +begin +select 'in continue handler'; +end; +select 'reachable code a1'; +call bug8153_subselect_b(); +select 'reachable code a2'; +end| +create procedure bug8153_subselect_b() +begin +select 'reachable code b1'; +update t3 set a=a+1 where (select a from t4 where a=1) is null; +select 'unreachable code b2'; +end| +call bug8153_subselect_a()| +reachable code a1 +reachable code a1 +reachable code b1 +reachable code b1 +in continue handler +in continue handler +reachable code a2 +reachable code a2 +select * from t3| +a +1 +1 +2 +3 +call bug8153_subselect_a()| +reachable code a1 +reachable code a1 +reachable code b1 +reachable code b1 +in continue handler +in continue handler +reachable code a2 +reachable code a2 +select * from t3| +a +1 +1 +2 +3 +drop procedure bug8153_subselect_a| +drop procedure bug8153_subselect_b| +create procedure bug8153_proc_a() +begin +declare continue handler for sqlexception +begin +select 'in continue handler'; +end; +select 'reachable code a1'; +call bug8153_proc_b(); +select 'reachable code a2'; +end| +create procedure bug8153_proc_b() +begin +select 'reachable code b1'; +select no_such_function(); +select 'unreachable code b2'; +end| +call bug8153_proc_a()| +reachable code a1 +reachable code a1 +reachable code b1 +reachable code b1 +in continue handler +in continue handler +reachable code a2 +reachable code a2 +drop procedure bug8153_proc_a| +drop procedure bug8153_proc_b| +drop table t3| +drop table t4| drop procedure if exists bug19862| CREATE TABLE t11 (a INT)| CREATE TABLE t12 (a INT)| @@ -5256,4 +5374,24 @@ a 1 use test| drop table t3| +DROP PROCEDURE IF EXISTS bug16899_p1| +DROP FUNCTION IF EXISTS bug16899_f1| +CREATE DEFINER=1234567890abcdefGHIKL@localhost PROCEDURE bug16899_p1() +BEGIN +SET @a = 1; +END| +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY +FUNCTION bug16899_f1() RETURNS INT +BEGIN +RETURN 1; +END| +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +drop procedure if exists bug21416| +create procedure bug21416() show create procedure bug21416| +call bug21416()| +Procedure sql_mode Create Procedure +bug21416 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug21416`() +show create procedure bug21416 +drop procedure bug21416| drop table t1,t2; diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index f3e797d2344..c687d4c49c8 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -626,12 +626,51 @@ Trigger Event Table Statement Timing Created sql_mode Definer t1_bi INSERT t1 set new.a = '2004-01-00' BEFORE # root@localhost drop table t1; create table t1 (id int); +create trigger t1_ai after insert on t1 for each row reset query cache; +ERROR 0A000: RESET is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row reset master; +ERROR 0A000: RESET is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row reset slave; +ERROR 0A000: RESET is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush hosts; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush tables with read lock; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush logs; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush status; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush slave; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush master; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush des_key_file; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush user_resources; +ERROR 0A000: FLUSH is not allowed in stored function or trigger create trigger t1_ai after insert on t1 for each row flush tables; ERROR 0A000: FLUSH is not allowed in stored function or trigger create trigger t1_ai after insert on t1 for each row flush privileges; ERROR 0A000: FLUSH is not allowed in stored function or trigger -create procedure p1() flush tables; +drop procedure if exists p1; create trigger t1_ai after insert on t1 for each row call p1(); +create procedure p1() flush tables; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() reset query cache; +insert into t1 values (0); +ERROR 0A000: RESET is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() reset master; +insert into t1 values (0); +ERROR 0A000: RESET is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() reset slave; +insert into t1 values (0); +ERROR 0A000: RESET is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush hosts; insert into t1 values (0); ERROR 0A000: FLUSH is not allowed in stored function or trigger drop procedure p1; @@ -639,6 +678,38 @@ create procedure p1() flush privileges; insert into t1 values (0); ERROR 0A000: FLUSH is not allowed in stored function or trigger drop procedure p1; +create procedure p1() flush tables with read lock; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush tables; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush logs; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush status; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush slave; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush master; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush des_key_file; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush user_resources; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; drop table t1; create table t1 (id int, data int, username varchar(16)); insert into t1 (id, data) values (1, 0); @@ -1089,4 +1160,17 @@ begin set @a:= 1; end| ERROR HY000: Triggers can not be created on system tables +use test| +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +CREATE TABLE t1(c INT); +CREATE TABLE t2(c INT); +CREATE DEFINER=1234567890abcdefGHIKL@localhost +TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a = 1; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY +TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW SET @a = 2; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +DROP TABLE t1; +DROP TABLE t2; End of 5.0 tests diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result index e74850bba33..1d707b83a4d 100644 --- a/mysql-test/r/type_varchar.result +++ b/mysql-test/r/type_varchar.result @@ -422,3 +422,34 @@ DROP TABLE IF EXISTS t1; CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); DROP TABLE IF EXISTS t1; +drop table if exists t1, t2, t3; +create table t3 ( +id int(11), +en varchar(255) character set utf8, +cz varchar(255) character set utf8 +); +truncate table t3; +insert into t3 (id, en, cz) values +(1,'en string 1','cz string 1'), +(2,'en string 2','cz string 2'), +(3,'en string 3','cz string 3'); +create table t1 ( +id int(11), +name_id int(11) +); +insert into t1 (id, name_id) values (1,1), (2,3), (3,3); +create table t2 (id int(11)); +insert into t2 (id) values (1), (2), (3); +select t1.*, t2.id, t3.en, t3.cz from t1 left join t2 on t1.id=t2.id +left join t3 on t1.id=t3.id order by t3.id; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 t1 id id 3 11 1 Y 32768 0 63 +def test t1 t1 name_id name_id 3 11 1 Y 32768 0 63 +def test t2 t2 id id 3 11 1 Y 32768 0 63 +def test t3 t3 en en 253 255 11 Y 0 0 8 +def test t3 t3 cz cz 253 255 11 Y 0 0 8 +id name_id id en cz +1 1 1 en string 1 cz string 1 +2 3 2 en string 2 cz string 2 +3 3 3 en string 3 cz string 3 +drop table t1, t2, t3; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index a0e516d2397..cd834a789bd 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -689,6 +689,12 @@ select @@log_queries_not_using_indexes; show variables like 'log_queries_not_using_indexes'; Variable_name Value log_queries_not_using_indexes OFF +select @@""; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '""' at line 1 +select @@&; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '&' at line 1 +select @@@; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@' at line 1 End of 5.0 tests set global binlog_cache_size =@my_binlog_cache_size; set global connect_timeout =@my_connect_timeout; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f9267b85134..f70547cd4a8 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2879,3 +2879,41 @@ View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`f1` AS `f1` from `t1` where (`t1`.`f1` between now() and (now() + interval 1 minute)) drop view v1; drop table t1; +DROP TABLE IF EXISTS t1; +DROP VIEW IF EXISTS v1; +DROP VIEW IF EXISTS v2; +CREATE TABLE t1(a INT, b INT); +CREATE DEFINER=1234567890abcdefGHIKL@localhost +VIEW v1 AS SELECT a FROM t1; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY +VIEW v2 AS SELECT b FROM t1; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +DROP TABLE t1; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP VIEW IF EXISTS v1, v2; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE FUNCTION f1() RETURNS INT +BEGIN +INSERT INTO v1 VALUES (0); +RETURN 0; +END | +SELECT f1(); +f1() +0 +CREATE ALGORITHM=TEMPTABLE VIEW v2 AS SELECT * FROM t1; +CREATE FUNCTION f2() RETURNS INT +BEGIN +INSERT INTO v2 VALUES (0); +RETURN 0; +END | +SELECT f2(); +ERROR HY000: The target table v2 of the INSERT is not updatable +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP VIEW v1, v2; +DROP TABLE t1; +End of 5.0 tests. diff --git a/mysql-test/std_data/14897.frm b/mysql-test/std_data/14897.frm Binary files differnew file mode 100644 index 00000000000..aff11b467b0 --- /dev/null +++ b/mysql-test/std_data/14897.frm diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test index 2d6b55600b1..c18c46b6b08 100644 --- a/mysql-test/t/ctype_recoding.test +++ b/mysql-test/t/ctype_recoding.test @@ -187,4 +187,16 @@ select rpad(c1,3,'ö'), rpad('ö',3,c1) from t1; #select case c1 when 'ß' then 'ß' when 'ö' then 'ö' else 'c' end from t1; #select export_set(5,c1,'ö'), export_set(5,'ö',c1) from t1; drop table t1; -# End of 4.1 tests + +# +# Bug 20695: problem with field default value's character set +# + +set names koi8r; +create table t1(a char character set cp1251 default _koi8r 0xFF); +show create table t1; +drop table t1; +--error 1067 +create table t1(a char character set latin1 default _cp1251 0xFF); + +--echo End of 4.1 tests diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index eea0b06b224..8116d39e3db 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -465,7 +465,51 @@ INSERT INTO t1 VALUES (1, 'ZZZZZ'), (1, 'ZZZ'), (2, 'ZZZ'), (2, 'ZZZZZ'); SELECT id, MIN(s) FROM t1 GROUP BY id; DROP TABLE t1; -# End of 4.1 tests + +# +# Bug #20536: md5() with GROUP BY and UCS2 return different results on myisam/innodb +# + +--disable_warnings +drop table if exists bug20536; +--enable_warnings + +set names latin1; +create table bug20536 (id bigint not null auto_increment primary key, name +varchar(255) character set ucs2 not null); +insert into `bug20536` (`id`,`name`) values (1, _latin1 x'7465737431'), (2, "'test\\_2'"); +select md5(name) from bug20536; +select sha1(name) from bug20536; +select make_set(3, name, upper(name)) from bug20536; +select export_set(5, name, upper(name)) from bug20536; +select export_set(5, name, upper(name), ",", 5) from bug20536; + +# Some broken functions: add these tests just to document current behavior. + +# PASSWORD and OLD_PASSWORD don't work with UCS2 strings, but to fix it would +# not be backwards compatible in all cases, so it's best to leave it alone +select password(name) from bug20536; +select old_password(name) from bug20536; + +# Disable test case as encrypt relies on 'crypt' function. +# "decrypt" is noramlly tested in func_crypt.test which have a +# "have_crypt.inc" test +--disable_parsing +# ENCRYPT relies on OS function crypt() which takes a NUL-terminated string; it +# doesn't return good results for strings with embedded 0 bytes. It won't be +# fixed unless we choose to re-implement the crypt() function ourselves to take +# an extra size_t string_length argument. +select encrypt(name, 'SALT') from bug20536; +--enable_parsing + +# QUOTE doesn't work with UCS2 data. It would require a total rewrite +# of Item_func_quote::val_str(), which isn't worthwhile until UCS2 is +# supported fully as a client character set. +select quote(name) from bug20536; + +drop table bug20536; + +--echo End of 4.1 tests # # Conversion from an UCS2 string to a decimal column @@ -497,3 +541,5 @@ create table t1(a blob, b text charset utf8, c text charset ucs2); select data_type, character_octet_length, character_maximum_length from information_schema.columns where table_name='t1'; drop table t1; + +--echo End of 5.0 tests diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 365d0fab4bf..b6137d5f084 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -728,6 +728,24 @@ select repeat(_utf8'+',3) as h union select NULL; select ifnull(NULL, _utf8'string'); # +# Bug#9509 Optimizer: wrong result after AND with comparisons +# +set names utf8; +create table t1 (s1 char(5) character set utf8 collate utf8_lithuanian_ci); +insert into t1 values ('I'),('K'),('Y'); +select * from t1 where s1 < 'K' and s1 = 'Y'; +select * from t1 where 'K' > s1 and s1 = 'Y'; +drop table t1; + +create table t1 (s1 char(5) character set utf8 collate utf8_czech_ci); +insert into t1 values ('c'),('d'),('h'),('ch'),('CH'),('cH'),('Ch'),('i'); +select * from t1 where s1 > 'd' and s1 = 'CH'; +select * from t1 where 'd' < s1 and s1 = 'CH'; +select * from t1 where s1 = 'cH' and s1 <> 'ch'; +select * from t1 where 'cH' = s1 and s1 <> 'ch'; +drop table t1; + +# # Bug#10714: Inserting double value into utf8 column crashes server # create table t1 (a varchar(255)) default character set utf8; @@ -1051,6 +1069,23 @@ explain select a from t1 group by a; select a from t1 group by a; drop table t1; +# +# Bug#20393: User name truncation in mysql client +# Bug#21432: Database/Table name limited to 64 bytes, not chars, problems with multi-byte +# +set names utf8; +#create user юзер_юзер@localhost; +grant select on test.* to юзер_юзер@localhost; +--exec $MYSQL --default-character-set=utf8 --user=юзер_юзер -e "select user()" +revoke all on test.* from юзер_юзер@localhost; +drop user юзер_юзер@localhost; + +create database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +use имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +select database(); +drop database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +use test; + # End of 4.1 tests # diff --git a/mysql-test/t/drop.test b/mysql-test/t/drop.test index 7cd943d46da..a1451773e90 100644 --- a/mysql-test/t/drop.test +++ b/mysql-test/t/drop.test @@ -81,3 +81,44 @@ show tables; drop table t1; # End of 4.1 tests + + +# +# Test for bug#21216 "Simultaneous DROP TABLE and SHOW OPEN TABLES causes +# server to crash". Crash (caused by failed assertion in 5.0 or by null +# pointer dereference in 5.1) happened when one ran SHOW OPEN TABLES +# while concurrently doing DROP TABLE (or RENAME TABLE, CREATE TABLE LIKE +# or any other command that takes name-lock) in other connection. +# +# Also includes test for similar bug#12212 "Crash that happens during +# removing of database name from cache" reappeared in 5.1 as bug#19403 +# In its case crash happened when one concurrently executed DROP DATABASE +# and one of name-locking command. +# +--disable_warnings +drop database if exists mysqltest; +drop table if exists t1; +--enable_warnings +create table t1 (i int); +lock tables t1 read; +create database mysqltest; +connect (addconroot1, localhost, root,,); +--send drop table t1 +connect (addconroot2, localhost, root,,); +# Server should not crash in any of the following statements +--disable_result_log +show open tables; +--enable_result_log +--send drop database mysqltest +connection default; +select 1; +unlock tables; +connection addconroot1; +--reap +connection addconroot2; +--reap +disconnect addconroot1; +disconnect addconroot2; +connection default; + +--echo End of 5.0 tests diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 0475dd4bdb6..52a5512d070 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -78,7 +78,13 @@ connection default; DROP TABLE t1; -# End of 4.1 tests +# +# Bug #21531: EXPORT_SET() doesn't accept args with coercible character sets +# +select export_set(3, _latin1'foo', _utf8'bar', ',', 4); + +--echo End of 4.1 tests + # # Test for BUG#9535 @@ -87,7 +93,9 @@ create table t1 as select uuid(), length(uuid()); show create table t1; drop table t1; +# # Bug #6760: Add SLEEP() function +# create table t1 (a timestamp default '2005-05-05 01:01:01', b timestamp default '2005-05-05 01:01:01'); insert into t1 set a = now(); @@ -117,4 +125,4 @@ drop table t2; drop table t1; set global query_cache_size=default; -# End of 5.0 tests +--echo End of 5.0 tests diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 0945c3ab33e..be09b00ad46 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -583,3 +583,21 @@ DROP TABLE t1,t2; # Restore timezone to default set time_zone= @@global.time_zone; + +# +# 21913: DATE_FORMAT() Crashes mysql server if I use it through +# mysql-connector-j driver. +# + +SET NAMES latin1; +SET character_set_results = NULL; +SHOW VARIABLES LIKE 'character_set_results'; + +CREATE TABLE testBug8868 (field1 DATE, field2 VARCHAR(32) CHARACTER SET BINARY); +INSERT INTO testBug8868 VALUES ('2006-09-04', 'abcd'); + +SELECT DATE_FORMAT(field1,'%b-%e %l:%i%p') as fmtddate, field2 FROM testBug8868; + +DROP TABLE testBug8868; + +SET NAMES DEFAULT; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index cc66615039f..d3781d58780 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -682,8 +682,6 @@ drop table t2; drop table t1; - - # # Bug#20214: Incorrect error when user calls SHOW CREATE VIEW on non # privileged view @@ -807,12 +805,62 @@ DROP DATABASE mysqltest3; REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'mysqltest_1'@'localhost'; DROP USER 'mysqltest_1'@'localhost'; - +# restore the original database +use test; # # Bug #10668: CREATE USER does not enforce username length limit # ---error ER_CANNOT_USER +--error ER_WRONG_STRING_LENGTH create user mysqltest1_thisisreallytoolong; +# +# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause. +# +# These checks are intended to ensure that appropriate errors are risen when +# illegal user name or hostname is specified in user-clause of GRANT/REVOKE +# statements. +# + +# Working with database-level privileges. + +--error ER_WRONG_STRING_LENGTH +GRANT CREATE ON mysqltest.* TO 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +GRANT CREATE ON mysqltest.* TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; + +--error ER_WRONG_STRING_LENGTH +REVOKE CREATE ON mysqltest.* FROM 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +REVOKE CREATE ON mysqltest.* FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; + +# Working with table-level privileges. + +--error ER_WRONG_STRING_LENGTH +GRANT CREATE ON t1 TO 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +GRANT CREATE ON t1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; + +--error ER_WRONG_STRING_LENGTH +REVOKE CREATE ON t1 FROM 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +REVOKE CREATE ON t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; + +# Working with routine-level privileges. + +--error ER_WRONG_STRING_LENGTH +GRANT EXECUTE ON PROCEDURE p1 TO 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +GRANT EXECUTE ON PROCEDURE p1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; + +--error ER_WRONG_STRING_LENGTH +REVOKE EXECUTE ON PROCEDURE p1 FROM 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +REVOKE EXECUTE ON PROCEDURE t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; --echo End of 5.0 tests diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test index a7f1eeaa2cc..bf18b8da941 100644 --- a/mysql-test/t/handler.test +++ b/mysql-test/t/handler.test @@ -1,3 +1,4 @@ +-- source include/not_embedded.inc # # test of HANDLER ... # diff --git a/mysql-test/t/heap_btree.test b/mysql-test/t/heap_btree.test index e74e9723ca6..03ba8661a3c 100644 --- a/mysql-test/t/heap_btree.test +++ b/mysql-test/t/heap_btree.test @@ -204,3 +204,4 @@ CREATE TABLE t1 (a INT, UNIQUE USING BTREE(a)) ENGINE=MEMORY; INSERT INTO t1 VALUES(NULL),(NULL); DROP TABLE t1; +--echo End of 5.0 tests diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest index fe2345a9987..a07da161279 100644 --- a/mysql-test/t/im_daemon_life_cycle.imtest +++ b/mysql-test/t/im_daemon_life_cycle.imtest @@ -6,7 +6,6 @@ # ########################################################################### ---source include/im_check_os.inc --source include/im_check_env.inc ########################################################################### diff --git a/mysql-test/t/im_life_cycle.imtest b/mysql-test/t/im_life_cycle.imtest index 16cf25a8f35..ddfb62d312e 100644 --- a/mysql-test/t/im_life_cycle.imtest +++ b/mysql-test/t/im_life_cycle.imtest @@ -6,7 +6,6 @@ # ########################################################################### ---source include/im_check_os.inc --source include/im_check_env.inc ########################################################################### diff --git a/mysql-test/t/im_options_set.imtest b/mysql-test/t/im_options_set.imtest index 76e209b6a66..6a70c31c0a4 100644 --- a/mysql-test/t/im_options_set.imtest +++ b/mysql-test/t/im_options_set.imtest @@ -38,7 +38,6 @@ ########################################################################### ---source include/im_check_os.inc --source include/im_check_env.inc ########################################################################### diff --git a/mysql-test/t/im_options_unset.imtest b/mysql-test/t/im_options_unset.imtest index 06f59e79ffe..074c9a3b869 100644 --- a/mysql-test/t/im_options_unset.imtest +++ b/mysql-test/t/im_options_unset.imtest @@ -45,7 +45,6 @@ ########################################################################### ---source include/im_check_os.inc --source include/im_check_env.inc ########################################################################### diff --git a/mysql-test/t/im_utils.imtest b/mysql-test/t/im_utils.imtest index 4c05b342af5..52878f6c2b5 100644 --- a/mysql-test/t/im_utils.imtest +++ b/mysql-test/t/im_utils.imtest @@ -6,7 +6,6 @@ # ########################################################################### ---source include/im_check_os.inc --source include/im_check_env.inc ########################################################################### diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test index 6df865278f6..cf7789428b2 100644 --- a/mysql-test/t/limit.test +++ b/mysql-test/t/limit.test @@ -60,4 +60,14 @@ select 1 as a from t1 union all select 1 from dual limit 1; (select 1 as a from t1) union all (select 1 from dual) limit 1; drop table t1; +# +# Bug #21787: COUNT(*) + ORDER BY + LIMIT returns wrong result +# +create table t1 (a int); +insert into t1 values (1),(2),(3),(4),(5),(6),(7); +explain select count(*) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +select count(*) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +explain select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; + # End of 4.1 tests diff --git a/mysql-test/t/loaddata_autocom_innodb.test b/mysql-test/t/loaddata_autocom_innodb.test new file mode 100644 index 00000000000..d7f152cb286 --- /dev/null +++ b/mysql-test/t/loaddata_autocom_innodb.test @@ -0,0 +1,4 @@ +--source include/have_innodb.inc +let $engine_type= InnoDB; + +--source include/loaddata_autocom.inc diff --git a/mysql-test/t/loaddata_autocom_ndb.test b/mysql-test/t/loaddata_autocom_ndb.test new file mode 100644 index 00000000000..f4a6743aabe --- /dev/null +++ b/mysql-test/t/loaddata_autocom_ndb.test @@ -0,0 +1,4 @@ +--source include/have_ndb.inc +let $engine_type=ndbcluster; + +--source include/loaddata_autocom.inc diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 385c59d1503..cf4e6f4047c 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -52,8 +52,8 @@ drop table t1; --exec $MYSQL --default-character-set=cp932 test -e "charset utf8;" # its usage to switch internally in mysql to requested charset ---exec $MYSQL --default-character-set=utf8 test -e "charset cp932; set @@session.character_set_client= cp932; select 'ƒ\'; create table t1 (c_cp932 TEXT CHARACTER SET cp932); insert into t1 values('ƒ\'); select * from t1; drop table t1;" ---exec $MYSQL --default-character-set=utf8 test -e "charset cp932; set character_set_client= cp932; select 'ƒ\'" +--exec $MYSQL --default-character-set=utf8 test -e "charset cp932; select 'ƒ\'; create table t1 (c_cp932 TEXT CHARACTER SET cp932); insert into t1 values('ƒ\'); select * from t1; drop table t1;" +--exec $MYSQL --default-character-set=utf8 test -e "charset cp932; select 'ƒ\'" --exec $MYSQL --default-character-set=utf8 test -e "/*charset cp932 */; set character_set_client= cp932; select 'ƒ\'" --exec $MYSQL --default-character-set=utf8 test -e "/*!\C cp932 */; set character_set_client= cp932; select 'ƒ\'" diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 848c5360db7..9766ee8d9c8 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -548,71 +548,6 @@ INSERT INTO t1 VALUES (1),(2),(3); --exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test DROP TABLE t1; - -# -# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) -# - -create database db1; -use db1; - -CREATE TABLE t2 ( - a varchar(30) default NULL, - KEY a (a(5)) -); - -INSERT INTO t2 VALUES ('alfred'); -INSERT INTO t2 VALUES ('angie'); -INSERT INTO t2 VALUES ('bingo'); -INSERT INTO t2 VALUES ('waffle'); -INSERT INTO t2 VALUES ('lemon'); -create view v2 as select * from t2 where a like 'a%' with check option; ---exec $MYSQL_DUMP --skip-comments db1 -drop table t2; -drop view v2; -drop database db1; - -# -# Bug 10713 mysqldump includes database in create view and referenced tables -# - -# create table and views in db2 -create database db2; -use db2; -create table t1 (a int); -create table t2 (a int, b varchar(10), primary key(a)); -insert into t2 values (1, "on"), (2, "off"), (10, "pol"), (12, "meg"); -insert into t1 values (289), (298), (234), (456), (789); -create view v1 as select * from t2; -create view v2 as select * from t1; - -# dump tables and view from db2 ---exec $MYSQL_DUMP db2 > $MYSQLTEST_VARDIR/tmp/bug10713.sql - -# drop the db, tables and views -drop table t1, t2; -drop view v1, v2; -drop database db2; - -# create db1 and reload dump -create database db1; -use db1; ---exec $MYSQL db1 < $MYSQLTEST_VARDIR/tmp/bug10713.sql - -# check that all tables and views could be created -show tables; -select * from t2 order by a; - -drop table t1, t2; -drop database db1; - -# -# BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence -# - ---exec $MYSQL_MY_PRINT_DEFAULTS --config-file=$MYSQL_TEST_DIR/std_data/bug15328.cnf mysqldump - - # # Bug #9558 mysqldump --no-data db t1 t2 format still dumps data # @@ -720,6 +655,12 @@ select * from t1; drop table t1; # +# BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence +# + +--exec $MYSQL_MY_PRINT_DEFAULTS --config-file=$MYSQL_TEST_DIR/std_data/bug15328.cnf mysqldump + +# # BUG #19025 mysqldump doesn't correctly dump "auto_increment = [int]" # create table `t1` ( @@ -748,9 +689,88 @@ show create table `t1`; drop table `t1`; +# +# Bug #18536: wrong table order +# + +create table t1(a int); +create table t2(a int); +create table t3(a int); +--error 6 +--exec $MYSQL_DUMP --skip-comments --force --no-data test t3 t1 non_existing t2 +drop table t1, t2, t3; + +# +# Bug #21288: mysqldump segmentation fault when using --where +# +create table t1 (a int); +--error 2 +--exec $MYSQL_DUMP --skip-comments --force test t1 --where='xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 2>&1 +drop table t1; + --echo End of 4.1 tests # +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# + +create database db1; +use db1; + +CREATE TABLE t2 ( + a varchar(30) default NULL, + KEY a (a(5)) +); + +INSERT INTO t2 VALUES ('alfred'); +INSERT INTO t2 VALUES ('angie'); +INSERT INTO t2 VALUES ('bingo'); +INSERT INTO t2 VALUES ('waffle'); +INSERT INTO t2 VALUES ('lemon'); +create view v2 as select * from t2 where a like 'a%' with check option; +--exec $MYSQL_DUMP --skip-comments db1 +drop table t2; +drop view v2; +drop database db1; +use test; + +# +# Bug 10713 mysqldump includes database in create view and referenced tables +# + +# create table and views in db2 +create database db2; +use db2; +create table t1 (a int); +create table t2 (a int, b varchar(10), primary key(a)); +insert into t2 values (1, "on"), (2, "off"), (10, "pol"), (12, "meg"); +insert into t1 values (289), (298), (234), (456), (789); +create view v1 as select * from t2; +create view v2 as select * from t1; + +# dump tables and view from db2 +--exec $MYSQL_DUMP db2 > $MYSQLTEST_VARDIR/tmp/bug10713.sql + +# drop the db, tables and views +drop table t1, t2; +drop view v1, v2; +drop database db2; +use test; + +# create db1 and reload dump +create database db1; +use db1; +--exec $MYSQL db1 < $MYSQLTEST_VARDIR/tmp/bug10713.sql + +# check that all tables and views could be created +show tables; +select * from t2 order by a; + +drop table t1, t2; +drop database db1; +use test; + +# # dump of view # create table t1(a int); @@ -813,6 +833,7 @@ select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; drop view v1, v2, v3; drop table t1; + # # Test for dumping triggers # @@ -1073,19 +1094,6 @@ insert into t1 values ('',''); drop table t1; # -# Bug #18536: wrong table order -# - -create table t1(a int); -create table t2(a int); -create table t3(a int); ---error 6 ---exec $MYSQL_DUMP --skip-comments --force --no-data test t3 t1 non_existing t2 -drop table t1, t2, t3; - ---echo End of 4.1 tests - -# # Bug 14871 Invalid view dump output # @@ -1266,11 +1274,11 @@ use mysqldump_dbb; drop view v1; drop table t1; drop database mysqldump_dbb; +use test; # # Bug#21215 mysqldump creating incomplete backups without warning # -use test; # Create user without sufficient privs to perform the requested operation create user mysqltest_1@localhost; @@ -1309,3 +1317,36 @@ grant REPLICATION CLIENT on *.* to mysqltest_1@localhost; # Clean up drop table t1; drop user mysqltest_1@localhost; + +# +# Bug #21527 mysqldump incorrectly tries to LOCK TABLES on the +# information_schema database. +# +connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); +connection root; +create database mysqldump_myDB; +use mysqldump_myDB; +create user myDB_User; +grant create view, select on mysqldump_myDB.* to myDB_User@localhost; +create table t1 (c1 int); +insert into t1 values (3); + +connect (user1,localhost,myDB_User,,mysqldump_myDB,$MASTER_MYPORT,$MASTER_MYSOCK); +connection user1; +use mysqldump_myDB; +create view v1 (c1) as select * from t1; + +# Backup should not fail. +--exec $MYSQL_DUMP --all-databases --add-drop-table > $MYSQLTEST_VARDIR/tmp/bug21527.sql + +# Clean up +connection root; +use mysqldump_myDB; +drop view v1; +drop table t1; +revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; +drop user myDB_User; +drop database mysqldump_myDB; +use test; + +--echo End of 5.0 tests diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index d0f31087c8f..5b2e37ecc94 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1329,4 +1329,33 @@ create temporary table t1 (i int); # Restore the old environemnt # use test; -# End of 5.0 tests + + +# +# BUG#21166: Prepared statement causes signal 11 on second execution +# +# Changes in an item tree done by optimizer weren't properly +# registered and went unnoticed, which resulted in preliminary freeing +# of used memory. +# +--disable_warnings +DROP TABLE IF EXISTS t1, t2, t3; +--enable_warnings + +CREATE TABLE t1 (i BIGINT, j BIGINT); +CREATE TABLE t2 (i BIGINT); +CREATE TABLE t3 (i BIGINT, j BIGINT); + +PREPARE stmt FROM "SELECT * FROM t1 JOIN t2 ON (t2.i = t1.i) + LEFT JOIN t3 ON ((t3.i, t3.j) = (t1.i, t1.j)) + WHERE t1.i = ?"; + +SET @a= 1; +EXECUTE stmt USING @a; +EXECUTE stmt USING @a; + +DEALLOCATE PREPARE stmt; +DROP TABLE IF EXISTS t1, t2, t3; + + +--echo End of 5.0 tests. diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index 776c1a466ca..240851e6ac4 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -709,5 +709,34 @@ EXPLAIN SELECT * FROM t1 WHERE 0 NOT BETWEEN b AND c; DROP TABLE t1; +# +# Bug #16249: different results for a range with an without index +# when a range condition use an invalid datetime constant +# + +CREATE TABLE t1 ( + item char(20) NOT NULL default '', + started datetime NOT NULL default '0000-00-00 00:00:00', + price decimal(16,3) NOT NULL default '0.000', + PRIMARY KEY (item,started) +) ENGINE=MyISAM; + +INSERT INTO t1 VALUES +('A1','2005-11-01 08:00:00',1000), +('A1','2005-11-15 00:00:00',2000), +('A1','2005-12-12 08:00:00',3000), +('A2','2005-12-01 08:00:00',1000); + +EXPLAIN SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; +SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; +SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-02 00:00:00'; + +DROP INDEX `PRIMARY` ON t1; + +EXPLAIN SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; +SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; +SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-02 00:00:00'; + +DROP TABLE t1; # End of 5.0 tests diff --git a/mysql-test/t/rpl_ndb_innodb_trans-slave.opt b/mysql-test/t/rpl_ndb_innodb_trans-slave.opt new file mode 100644 index 00000000000..627becdbfb5 --- /dev/null +++ b/mysql-test/t/rpl_ndb_innodb_trans-slave.opt @@ -0,0 +1 @@ +--innodb diff --git a/mysql-test/t/rpl_ndb_innodb_trans.test b/mysql-test/t/rpl_ndb_innodb_trans.test new file mode 100644 index 00000000000..127c2464570 --- /dev/null +++ b/mysql-test/t/rpl_ndb_innodb_trans.test @@ -0,0 +1,66 @@ +# Test of a transaction mixing the two engines + +-- source include/have_ndb.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc + +create table t1 (a int, unique(a)) engine=ndbcluster; +create table t2 (a int, unique(a)) engine=innodb; + + +begin; +insert into t1 values(1); +insert into t2 values(1); +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +delete from t1; +delete from t2; +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +delete from t1; +delete from t2; +begin; +insert into t2 values(3),(4); +insert into t1 values(3),(4); +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +drop table t1,t2; +sync_slave_with_master; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 2abb923efbb..abb36f040d2 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -899,6 +899,45 @@ begin flush tables; return 5; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin reset query cache; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin reset master; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin reset slave; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush hosts; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush privileges; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush tables with read lock; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush tables; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush logs; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush status; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush slave; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush master; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush des_key_file; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush user_resources; +return 1; end| # diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index ba30699b1d0..4b0f463a9e3 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6147,6 +6147,104 @@ use test| DROP DATABASE mysqltest1| # +# BUG#8153: Stored procedure with subquery and continue handler, wrong result +# + +--disable_warnings +drop table if exists t3| +drop table if exists t4| +drop procedure if exists bug8153_subselect| +drop procedure if exists bug8153_subselect_a| +drop procedure if exists bug8153_subselect_b| +drop procedure if exists bug8153_proc_a| +drop procedure if exists bug8153_proc_b| +--enable_warnings + +create table t3 (a int)| +create table t4 (a int)| +insert into t3 values (1), (1), (2), (3)| +insert into t4 values (1), (1)| + +## Testing the use case reported in Bug#8153 + +create procedure bug8153_subselect() +begin + declare continue handler for sqlexception + begin + select 'statement failed'; + end; + update t3 set a=a+1 where (select a from t4 where a=1) is null; + select 'statement after update'; +end| + +call bug8153_subselect()| +select * from t3| + +call bug8153_subselect()| +select * from t3| + +drop procedure bug8153_subselect| + +## Testing a subselect with a non local handler + +create procedure bug8153_subselect_a() +begin + declare continue handler for sqlexception + begin + select 'in continue handler'; + end; + + select 'reachable code a1'; + call bug8153_subselect_b(); + select 'reachable code a2'; +end| + +create procedure bug8153_subselect_b() +begin + select 'reachable code b1'; + update t3 set a=a+1 where (select a from t4 where a=1) is null; + select 'unreachable code b2'; +end| + +call bug8153_subselect_a()| +select * from t3| + +call bug8153_subselect_a()| +select * from t3| + +drop procedure bug8153_subselect_a| +drop procedure bug8153_subselect_b| + +## Testing extra use cases, found while investigating +## This is related to BUG#18787, with a non local handler + +create procedure bug8153_proc_a() +begin + declare continue handler for sqlexception + begin + select 'in continue handler'; + end; + + select 'reachable code a1'; + call bug8153_proc_b(); + select 'reachable code a2'; +end| + +create procedure bug8153_proc_b() +begin + select 'reachable code b1'; + select no_such_function(); + select 'unreachable code b2'; +end| + +call bug8153_proc_a()| + +drop procedure bug8153_proc_a| +drop procedure bug8153_proc_b| +drop table t3| +drop table t4| + +# # BUG#19862: Sort with filesort by function evaluates function twice # --disable_warnings @@ -6188,6 +6286,42 @@ select * from (select 1 as a) as t1 natural join (select * from test.t3) as t2| use test| drop table t3| + +# +# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause. +# + +# Prepare. + +--disable_warnings +DROP PROCEDURE IF EXISTS bug16899_p1| +DROP FUNCTION IF EXISTS bug16899_f1| +--enable_warnings + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=1234567890abcdefGHIKL@localhost PROCEDURE bug16899_p1() +BEGIN + SET @a = 1; +END| + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY + FUNCTION bug16899_f1() RETURNS INT +BEGIN + RETURN 1; +END| + + +# +# BUG#21416: SP: Recursion level higher than zero needed for non-recursive call +# +--disable_warnings +drop procedure if exists bug21416| +--enable_warnings +create procedure bug21416() show create procedure bug21416| +call bug21416()| +drop procedure bug21416| + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/system_mysql_db_fix.test b/mysql-test/t/system_mysql_db_fix.test index 0a2ab180806..fa44b454b4f 100644 --- a/mysql-test/t/system_mysql_db_fix.test +++ b/mysql-test/t/system_mysql_db_fix.test @@ -1,6 +1,9 @@ # Embedded server doesn't support external clients --source include/not_embedded.inc +# Windows doesn't support execution of shell scripts (to fix!!) +--source include/not_windows.inc + # # This is the test for mysql_fix_privilege_tables # diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 95e8eaae83e..2a145e1eeaa 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -651,17 +651,105 @@ drop table t1; # of functions and triggers. create table t1 (id int); --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row reset query cache; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row reset master; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row reset slave; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush hosts; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush tables with read lock; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush logs; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush status; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush slave; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush master; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush des_key_file; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush user_resources; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG create trigger t1_ai after insert on t1 for each row flush tables; --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG create trigger t1_ai after insert on t1 for each row flush privileges; -create procedure p1() flush tables; +--disable_warnings +drop procedure if exists p1; +--enable_warnings + create trigger t1_ai after insert on t1 for each row call p1(); +create procedure p1() flush tables; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() reset query cache; --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG insert into t1 values (0); + +drop procedure p1; +create procedure p1() reset master; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() reset slave; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush hosts; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + drop procedure p1; create procedure p1() flush privileges; --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush tables with read lock; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush tables; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush logs; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush status; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush slave; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush master; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush des_key_file; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush user_resources; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + drop procedure p1; drop table t1; @@ -1301,6 +1389,36 @@ create trigger wont_work after update on event for each row begin set @a:= 1; end| +use test| delimiter ;| + +# +# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause. +# + +# Prepare. + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +--enable_warnings + +CREATE TABLE t1(c INT); +CREATE TABLE t2(c INT); + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=1234567890abcdefGHIKL@localhost + TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a = 1; + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY + TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW SET @a = 2; + +# Cleanup. + +DROP TABLE t1; +DROP TABLE t2; + + --echo End of 5.0 tests diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test index e5614afe4f6..439e98471b2 100644 --- a/mysql-test/t/type_varchar.test +++ b/mysql-test/t/type_varchar.test @@ -146,3 +146,44 @@ DROP TABLE IF EXISTS t1; CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); DROP TABLE IF EXISTS t1; + +# +# Bug#14897 "ResultSet.getString("table.column") sometimes doesn't find the +# column" +# Test that after upgrading an old 4.1 VARCHAR column to 5.0 VARCHAR we preserve +# the original column metadata. +# +--disable_warnings +drop table if exists t1, t2, t3; +--enable_warnings + +create table t3 ( + id int(11), + en varchar(255) character set utf8, + cz varchar(255) character set utf8 +); +system cp $MYSQL_TEST_DIR/std_data/14897.frm $MYSQLTEST_VARDIR/master-data/test/t3.frm; +truncate table t3; +insert into t3 (id, en, cz) values +(1,'en string 1','cz string 1'), +(2,'en string 2','cz string 2'), +(3,'en string 3','cz string 3'); + +create table t1 ( + id int(11), + name_id int(11) +); +insert into t1 (id, name_id) values (1,1), (2,3), (3,3); + +create table t2 (id int(11)); +insert into t2 (id) values (1), (2), (3); + +# max_length is different for varchar fields in ps-protocol and we can't +# replace a single metadata column, disable PS protocol +--disable_ps_protocol +--enable_metadata +select t1.*, t2.id, t3.en, t3.cz from t1 left join t2 on t1.id=t2.id +left join t3 on t1.id=t3.id order by t3.id; +--disable_metadata +--enable_ps_protocol +drop table t1, t2, t3; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 68efcafd1e0..d855b4d8266 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -585,6 +585,16 @@ show variables like 'ssl%'; select @@log_queries_not_using_indexes; show variables like 'log_queries_not_using_indexes'; +# +# Bug#20908: Crash if select @@"" +# +--error ER_PARSE_ERROR +select @@""; +--error ER_PARSE_ERROR +select @@&; +--error ER_PARSE_ERROR +select @@@; + --echo End of 5.0 tests # This is at the very after the versioned tests, since it involves doing @@ -620,3 +630,4 @@ set global server_id =@my_server_id; set global slow_launch_time =@my_slow_launch_time; set global storage_engine =@my_storage_engine; set global thread_cache_size =@my_thread_cache_size; + diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index fae3f856cb8..edff38274c4 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2760,3 +2760,78 @@ create view v1 as select * from t1 where f1 between now() and now() + interval 1 show create view v1; drop view v1; drop table t1; +# +# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause. +# + +# Prepare. + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP VIEW IF EXISTS v1; +DROP VIEW IF EXISTS v2; +--enable_warnings + +CREATE TABLE t1(a INT, b INT); + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=1234567890abcdefGHIKL@localhost + VIEW v1 AS SELECT a FROM t1; + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY + VIEW v2 AS SELECT b FROM t1; + +# Cleanup. + +DROP TABLE t1; + + +# +# BUG#17591: Updatable view not possible with trigger or stored +# function +# +# During prelocking phase we didn't update lock type of view tables, +# hence READ lock was always requested. +# +--disable_warnings +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP VIEW IF EXISTS v1, v2; +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (i INT); + +CREATE VIEW v1 AS SELECT * FROM t1; + +delimiter |; +CREATE FUNCTION f1() RETURNS INT +BEGIN + INSERT INTO v1 VALUES (0); + RETURN 0; +END | +delimiter ;| + +SELECT f1(); + +CREATE ALGORITHM=TEMPTABLE VIEW v2 AS SELECT * FROM t1; + +delimiter |; +CREATE FUNCTION f2() RETURNS INT +BEGIN + INSERT INTO v2 VALUES (0); + RETURN 0; +END | +delimiter ;| + +--error ER_NON_UPDATABLE_TABLE +SELECT f2(); + +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP VIEW v1, v2; +DROP TABLE t1; + + +--echo End of 5.0 tests. diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt new file mode 100755 index 00000000000..7926cb916c1 --- /dev/null +++ b/mysys/CMakeLists.txt @@ -0,0 +1,29 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +# Need to set USE_TLS, since mysys is linked into libmysql.dll and +# libmysqld.dll, and __declspec(thread) approach to thread local storage does +# not work properly in DLLs. +# Currently, USE_TLS crashes in Debug builds, so until that is fixed Debug +# .dlls cannot be loaded at runtime. +SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DUSE_TLS") +SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DUSE_TLS") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/mysys ) +ADD_LIBRARY(mysys array.c charset-def.c charset.c checksum.c default.c default_modify.c + errors.c hash.c list.c md5.c mf_brkhant.c mf_cache.c mf_dirname.c mf_fn_ext.c + mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c + mf_keycaches.c mf_loadpath.c mf_pack.c mf_path.c mf_qsort.c mf_qsort2.c + mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_strip.c mf_tempdir.c + mf_tempfile.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_access.c + my_aes.c my_alarm.c my_alloc.c my_append.c my_bit.c my_bitmap.c my_chsize.c + my_clock.c my_compress.c my_conio.c my_copy.c my_crc32.c my_create.c my_delete.c + my_div.c my_error.c my_file.c my_fopen.c my_fstream.c my_gethostbyname.c + my_gethwaddr.c my_getopt.c my_getsystime.c my_getwd.c my_handler.c my_init.c + my_lib.c my_lock.c my_lockmem.c my_lread.c my_lwrite.c my_malloc.c my_messnc.c + my_mkdir.c my_mmap.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c + my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_sleep.c + my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c + my_windac.c my_winsem.c my_winthread.c my_write.c ptr_cmp.c queues.c + rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c + thr_rwlock.c tree.c typelib.c base64.c my_memmem.c) diff --git a/mysys/Makefile.am b/mysys/Makefile.am index bc84f44cd29..041130fdf5c 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -58,7 +58,8 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ my_memmem.c \ my_windac.c my_access.c base64.c my_libwrap.c EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ - thr_mutex.c thr_rwlock.c + thr_mutex.c thr_rwlock.c mf_soundex.c my_conio.c \ + my_wincond.c my_winsem.c my_winthread.c CMakeLists.txt libmysys_a_LIBADD = @THREAD_LOBJECTS@ # test_dir_DEPENDENCIES= $(LIBRARIES) # testhash_DEPENDENCIES= $(LIBRARIES) diff --git a/mysys/my_read.c b/mysys/my_read.c index 9de070e772d..2e23f2175f8 100644 --- a/mysys/my_read.c +++ b/mysys/my_read.c @@ -36,48 +36,51 @@ uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags) { - uint readbytes,save_count; + uint readbytes, save_count; DBUG_ENTER("my_read"); DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d", - Filedes, Buffer, Count, MyFlags)); - save_count=Count; + Filedes, Buffer, Count, MyFlags)); + save_count= Count; for (;;) { - errno=0; /* Linux doesn't reset this */ - if ((readbytes = (uint) read(Filedes, Buffer, Count)) != Count) + errno= 0; /* Linux doesn't reset this */ + if ((readbytes= (uint) read(Filedes, Buffer, Count)) != Count) { - my_errno=errno ? errno : -1; + my_errno= errno ? errno : -1; DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d", - readbytes,Count,Filedes,my_errno)); + readbytes, Count, Filedes, my_errno)); #ifdef THREAD - if (readbytes == 0 && errno == EINTR) - continue; /* Interrupted */ + if ((int) readbytes <= 0 && errno == EINTR) + { + DBUG_PRINT("debug", ("my_read() was interrupted and returned %d", (int) readbytes)); + continue; /* Interrupted */ + } #endif if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { - if ((int) readbytes == -1) - my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),my_errno); - else if (MyFlags & (MY_NABP | MY_FNABP)) - my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),my_errno); + if ((int) readbytes == -1) + my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); + else if (MyFlags & (MY_NABP | MY_FNABP)) + my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); } if ((int) readbytes == -1 || - ((MyFlags & (MY_FNABP | MY_NABP)) && !(MyFlags & MY_FULL_IO))) - DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ + ((MyFlags & (MY_FNABP | MY_NABP)) && !(MyFlags & MY_FULL_IO))) + DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ if (readbytes > 0 && (MyFlags & MY_FULL_IO)) { - Buffer+=readbytes; - Count-=readbytes; - continue; + Buffer+= readbytes; + Count-= readbytes; + continue; } } if (MyFlags & (MY_NABP | MY_FNABP)) - readbytes=0; /* Ok on read */ + readbytes= 0; /* Ok on read */ else if (MyFlags & MY_FULL_IO) - readbytes=save_count; + readbytes= save_count; break; } DBUG_RETURN(readbytes); diff --git a/mysys/my_seek.c b/mysys/my_seek.c index 6af65d70fd0..8035312496d 100644 --- a/mysys/my_seek.c +++ b/mysys/my_seek.c @@ -29,7 +29,8 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, whence, MyFlags)); DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */ - newpos=lseek(fd, pos, whence); + if (-1 != fd) + newpos=lseek(fd, pos, whence); if (newpos == (os_off_t) -1) { my_errno=errno; diff --git a/ndb/include/kernel/signaldata/CreateIndx.hpp b/ndb/include/kernel/signaldata/CreateIndx.hpp index a9dc653f349..4163583dbd2 100644 --- a/ndb/include/kernel/signaldata/CreateIndx.hpp +++ b/ndb/include/kernel/signaldata/CreateIndx.hpp @@ -192,6 +192,7 @@ public: enum ErrorCode { NoError = 0, Busy = 701, + BusyWithNR = 711, NotMaster = 702, TriggerNotFound = 4238, TriggerExists = 4239, diff --git a/ndb/include/kernel/signaldata/DropIndx.hpp b/ndb/include/kernel/signaldata/DropIndx.hpp index fd2ea7f0b7b..41ee50082f7 100644 --- a/ndb/include/kernel/signaldata/DropIndx.hpp +++ b/ndb/include/kernel/signaldata/DropIndx.hpp @@ -168,6 +168,7 @@ public: NoError = 0, InvalidIndexVersion = 241, Busy = 701, + BusyWithNR = 711, NotMaster = 702, IndexNotFound = 4243, BadRequestType = 4247, diff --git a/ndb/include/ndbapi/NdbOperation.hpp b/ndb/include/ndbapi/NdbOperation.hpp index 4db541f7fe4..dbc343d2238 100644 --- a/ndb/include/ndbapi/NdbOperation.hpp +++ b/ndb/include/ndbapi/NdbOperation.hpp @@ -477,7 +477,7 @@ public: /** * Interpreted program instruction: - * Substract RegSource1 from RegSource2 and put the result in RegDest. + * Substract RegSource2 from RegSource1 and put the result in RegDest. * * @param RegSource1 First register. * @param RegSource2 Second register. diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt index 7fee2e92f2b..c8c9e82efc2 100644 --- a/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/ndb/src/kernel/blocks/ERROR_codes.txt @@ -6,7 +6,7 @@ Next DBTUP 4014 Next DBLQH 5043 Next DBDICT 6007 Next DBDIH 7177 -Next DBTC 8037 +Next DBTC 8038 Next CMVMI 9000 Next BACKUP 10022 Next DBUTIL 11002 @@ -283,6 +283,7 @@ ABORT OF TCKEYREQ 8032: No free TC records any more +8037 : Invalid schema version in TCINDXREQ CMVMI ----- diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index 43c1de5e2b3..10318e5f52d 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -274,36 +274,48 @@ Backup::execCONTINUEB(Signal* signal) BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptr_I); - TablePtr tabPtr; - ptr.p->tables.getPtr(tabPtr, tabPtr_I); - FragmentPtr fragPtr; - tabPtr.p->fragments.getPtr(fragPtr, fragPtr_I); - BackupFilePtr filePtr; - ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); - - const Uint32 sz = sizeof(BackupFormat::CtlFile::FragmentInfo) >> 2; - Uint32 * dst; - if (!filePtr.p->operation.dataBuffer.getWritePtr(&dst, sz)) + if (tabPtr_I == RNIL) { - sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 4); + closeFiles(signal, ptr); return; } + jam(); + TablePtr tabPtr; + ptr.p->tables.getPtr(tabPtr, tabPtr_I); + jam(); + if(tabPtr.p->fragments.getSize()) + { + FragmentPtr fragPtr; + tabPtr.p->fragments.getPtr(fragPtr, fragPtr_I); - BackupFormat::CtlFile::FragmentInfo * fragInfo = - (BackupFormat::CtlFile::FragmentInfo*)dst; - fragInfo->SectionType = htonl(BackupFormat::FRAGMENT_INFO); - fragInfo->SectionLength = htonl(sz); - fragInfo->TableId = htonl(fragPtr.p->tableId); - fragInfo->FragmentNo = htonl(fragPtr_I); - fragInfo->NoOfRecordsLow = htonl(fragPtr.p->noOfRecords & 0xFFFFFFFF); - fragInfo->NoOfRecordsHigh = htonl(fragPtr.p->noOfRecords >> 32); - fragInfo->FilePosLow = htonl(0 & 0xFFFFFFFF); - fragInfo->FilePosHigh = htonl(0 >> 32); + BackupFilePtr filePtr; + ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); - filePtr.p->operation.dataBuffer.updateWritePtr(sz); + const Uint32 sz = sizeof(BackupFormat::CtlFile::FragmentInfo) >> 2; + Uint32 * dst; + if (!filePtr.p->operation.dataBuffer.getWritePtr(&dst, sz)) + { + sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 4); + return; + } + + BackupFormat::CtlFile::FragmentInfo * fragInfo = + (BackupFormat::CtlFile::FragmentInfo*)dst; + fragInfo->SectionType = htonl(BackupFormat::FRAGMENT_INFO); + fragInfo->SectionLength = htonl(sz); + fragInfo->TableId = htonl(fragPtr.p->tableId); + fragInfo->FragmentNo = htonl(fragPtr_I); + fragInfo->NoOfRecordsLow = htonl(fragPtr.p->noOfRecords & 0xFFFFFFFF); + fragInfo->NoOfRecordsHigh = htonl(fragPtr.p->noOfRecords >> 32); + fragInfo->FilePosLow = htonl(0 & 0xFFFFFFFF); + fragInfo->FilePosHigh = htonl(0 >> 32); + + filePtr.p->operation.dataBuffer.updateWritePtr(sz); + + fragPtr_I++; + } - fragPtr_I++; if (fragPtr_I == tabPtr.p->fragments.getSize()) { signal->theData[0] = tabPtr.p->tableId; @@ -4243,6 +4255,12 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal) TablePtr tabPtr; ptr.p->tables.first(tabPtr); + if (tabPtr.i == RNIL) + { + closeFiles(signal, ptr); + return; + } + signal->theData[0] = BackupContinueB::BACKUP_FRAGMENT_INFO; signal->theData[1] = ptr.i; signal->theData[2] = tabPtr.i; diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index efd519339f7..a79ddd05fae 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -6520,9 +6520,18 @@ Dbdict::execCREATE_INDX_REQ(Signal* signal) } if (signal->getLength() == CreateIndxReq::SignalLength) { jam(); + CreateIndxRef::ErrorCode tmperr = CreateIndxRef::NoError; if (getOwnNodeId() != c_masterNodeId) { jam(); - + tmperr = CreateIndxRef::NotMaster; + } else if (c_blockState == BS_NODE_RESTART) { + jam(); + tmperr = CreateIndxRef::BusyWithNR; + } else if (c_blockState != BS_IDLE) { + jam(); + tmperr = CreateIndxRef::Busy; + } + if (tmperr != CreateIndxRef::NoError) { releaseSections(signal); OpCreateIndex opBusy; opPtr.p = &opBusy; @@ -6530,13 +6539,12 @@ Dbdict::execCREATE_INDX_REQ(Signal* signal) opPtr.p->m_isMaster = (senderRef == reference()); opPtr.p->key = 0; opPtr.p->m_requestType = CreateIndxReq::RT_DICT_PREPARE; - opPtr.p->m_errorCode = CreateIndxRef::NotMaster; + opPtr.p->m_errorCode = tmperr; opPtr.p->m_errorLine = __LINE__; opPtr.p->m_errorNode = c_masterNodeId; createIndex_sendReply(signal, opPtr, true); return; } - // forward initial request plus operation key to all req->setOpKey(++c_opRecordSequence); NodeReceiverGroup rg(DBDICT, c_aliveNodes); @@ -7082,10 +7090,19 @@ Dbdict::execDROP_INDX_REQ(Signal* signal) jam(); if (signal->getLength() == DropIndxReq::SignalLength) { jam(); + DropIndxRef::ErrorCode tmperr = DropIndxRef::NoError; if (getOwnNodeId() != c_masterNodeId) { jam(); - - err = DropIndxRef::NotMaster; + tmperr = DropIndxRef::NotMaster; + } else if (c_blockState == BS_NODE_RESTART) { + jam(); + tmperr = DropIndxRef::BusyWithNR; + } else if (c_blockState != BS_IDLE) { + jam(); + tmperr = DropIndxRef::Busy; + } + if (tmperr != DropIndxRef::NoError) { + err = tmperr; goto error; } // forward initial request plus operation key to all @@ -10130,6 +10147,17 @@ Dbdict::execDICT_LOCK_REQ(Signal* signal) sendDictLockInfoEvent(lockPtr, "lock request by node"); } +// only table and index ops are checked +bool +Dbdict::hasDictLockSchemaOp() +{ + return + ! c_opCreateTable.isEmpty() || + ! c_opDropTable.isEmpty() || + ! c_opCreateIndex.isEmpty() || + ! c_opDropIndex.isEmpty(); +} + void Dbdict::checkDictLockQueue(Signal* signal, bool poll) { @@ -10150,7 +10178,7 @@ Dbdict::checkDictLockQueue(Signal* signal, bool poll) break; } - if (c_opRecordPool.getNoOfFree() != c_opRecordPool.getSize()) { + if (hasDictLockSchemaOp()) { jam(); break; } @@ -10183,7 +10211,7 @@ Dbdict::execDICT_UNLOCK_ORD(Signal* signal) if (lockPtr.p->locked) { jam(); ndbrequire(c_blockState == lockPtr.p->lt->blockState); - ndbrequire(c_opRecordPool.getNoOfFree() == c_opRecordPool.getSize()); + ndbrequire(! hasDictLockSchemaOp()); ndbrequire(! c_dictLockQueue.hasPrev(lockPtr)); c_blockState = BS_IDLE; @@ -10279,7 +10307,7 @@ Dbdict::removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes) if (lockPtr.p->locked) { jam(); ndbrequire(c_blockState == lockPtr.p->lt->blockState); - ndbrequire(c_opRecordPool.getNoOfFree() == c_opRecordPool.getSize()); + ndbrequire(! hasDictLockSchemaOp()); ndbrequire(! c_dictLockQueue.hasPrev(lockPtr)); c_blockState = BS_IDLE; diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp index ed8b7e3b822..82644826d5b 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp @@ -1650,6 +1650,9 @@ private: void sendDictLockInfoEvent(Uint32 pollCount); void sendDictLockInfoEvent(DictLockPtr lockPtr, const char* text); + // check if any schema op exists (conflicting with dict lock) + bool hasDictLockSchemaOp(); + void checkDictLockQueue(Signal* signal, bool poll); void sendDictLockConf(Signal* signal, DictLockPtr lockPtr); void sendDictLockRef(Signal* signal, DictLockReq req, Uint32 errorCode); diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 491aa0849b9..1c1fdb41d51 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -8252,11 +8252,21 @@ void Dbdih::openingTableErrorLab(Signal* signal, FileRecordPtr filePtr) /* WE FAILED IN OPENING A FILE. IF THE FIRST FILE THEN TRY WITH THE */ /* DUPLICATE FILE, OTHERWISE WE REPORT AN ERROR IN THE SYSTEM RESTART. */ /* ---------------------------------------------------------------------- */ - ndbrequire(filePtr.i == tabPtr.p->tabFile[0]); - filePtr.i = tabPtr.p->tabFile[1]; - ptrCheckGuard(filePtr, cfileFileSize, fileRecord); - openFileRw(signal, filePtr); - filePtr.p->reqStatus = FileRecord::OPENING_TABLE; + if (filePtr.i == tabPtr.p->tabFile[0]) + { + filePtr.i = tabPtr.p->tabFile[1]; + ptrCheckGuard(filePtr, cfileFileSize, fileRecord); + openFileRw(signal, filePtr); + filePtr.p->reqStatus = FileRecord::OPENING_TABLE; + } + else + { + char buf[256]; + BaseString::snprintf(buf, sizeof(buf), + "Error opening DIH schema files for table: %d", + tabPtr.i); + progError(__LINE__, NDBD_EXIT_AFS_NO_SUCH_FILE, buf); + } }//Dbdih::openingTableErrorLab() void Dbdih::readingTableLab(Signal* signal, FileRecordPtr filePtr) @@ -8422,6 +8432,7 @@ Dbdih::resetReplicaSr(TabRecordPtr tabPtr){ } replicaPtr.i = nextReplicaPtrI; }//while + updateNodeInfo(fragPtr); } } diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 0ea49e47fc7..7286481002f 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -6470,6 +6470,7 @@ void Dblqh::execACC_ABORTCONF(Signal* signal) * A NORMAL EVENT DURING CREATION OF A FRAGMENT. WE NOW NEED TO CONTINUE * WITH NORMAL COMMIT PROCESSING. * ---------------------------------------------------------------------- */ + regTcPtr->totSendlenAi = regTcPtr->totReclenAi; if (regTcPtr->currTupAiLen == regTcPtr->totReclenAi) { jam(); regTcPtr->abortState = TcConnectionrec::ABORT_IDLE; @@ -12579,19 +12580,17 @@ void Dblqh::lastWriteInFileLab(Signal* signal) void Dblqh::writePageZeroLab(Signal* signal) { - if (false && logPartPtr.p->logPartState == LogPartRecord::FILE_CHANGE_PROBLEM) + if (logPartPtr.p->logPartState == LogPartRecord::FILE_CHANGE_PROBLEM) { if (logPartPtr.p->firstLogQueue == RNIL) { jam(); logPartPtr.p->logPartState = LogPartRecord::IDLE; - ndbout_c("resetting logPartState to IDLE"); } else { jam(); logPartPtr.p->logPartState = LogPartRecord::ACTIVE; - ndbout_c("resetting logPartState to ACTIVE"); } } @@ -14623,6 +14622,8 @@ void Dblqh::execSr(Signal* signal) LogFileRecordPtr nextLogFilePtr; LogPageRecordPtr tmpLogPagePtr; Uint32 logWord; + Uint32 line; + const char * crash_msg = 0; jamEntry(); logPartPtr.i = signal->theData[0]; @@ -14833,8 +14834,14 @@ void Dblqh::execSr(Signal* signal) /* PLACE THAN IN THE FIRST PAGE OF A NEW FILE IN THE FIRST POSITION AFTER THE*/ /* HEADER. */ /*---------------------------------------------------------------------------*/ - ndbrequire(logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] == - (ZPAGE_HEADER_SIZE + ZPOS_NO_FD)); + if (unlikely(logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] != + (ZPAGE_HEADER_SIZE + ZPOS_NO_FD))) + { + line = __LINE__; + logWord = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]; + crash_msg = "ZFD_TYPE at incorrect position!"; + goto crash; + } { Uint32 noFdDescriptors = logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_NO_FD]; @@ -14871,19 +14878,10 @@ void Dblqh::execSr(Signal* signal) /*---------------------------------------------------------------------------*/ /* SEND A SIGNAL TO THE SIGNAL LOG AND THEN CRASH THE SYSTEM. */ /*---------------------------------------------------------------------------*/ - signal->theData[0] = RNIL; - signal->theData[1] = logPartPtr.i; - Uint32 tmp = logFilePtr.p->fileName[3]; - tmp = (tmp >> 8) & 0xff;// To get the Directory, DXX. - signal->theData[2] = tmp; - signal->theData[3] = logFilePtr.p->fileNo; - signal->theData[4] = logFilePtr.p->currentFilepage; - signal->theData[5] = logFilePtr.p->currentMbyte; - signal->theData[6] = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]; - signal->theData[7] = ~0; - signal->theData[8] = __LINE__; - sendSignal(cownref, GSN_DEBUG_SIG, signal, 9, JBA); - return; + line = __LINE__; + logWord = ZNEXT_MBYTE_TYPE; + crash_msg = "end of log wo/ having found last GCI"; + goto crash; }//if }//if /*---------------------------------------------------------------------------*/ @@ -14938,19 +14936,9 @@ void Dblqh::execSr(Signal* signal) /*---------------------------------------------------------------------------*/ /* SEND A SIGNAL TO THE SIGNAL LOG AND THEN CRASH THE SYSTEM. */ /*---------------------------------------------------------------------------*/ - signal->theData[0] = RNIL; - signal->theData[1] = logPartPtr.i; - Uint32 tmp = logFilePtr.p->fileName[3]; - tmp = (tmp >> 8) & 0xff;// To get the Directory, DXX. - signal->theData[2] = tmp; - signal->theData[3] = logFilePtr.p->fileNo; - signal->theData[4] = logFilePtr.p->currentMbyte; - signal->theData[5] = logFilePtr.p->currentFilepage; - signal->theData[6] = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]; - signal->theData[7] = logWord; - signal->theData[8] = __LINE__; - sendSignal(cownref, GSN_DEBUG_SIG, signal, 9, JBA); - return; + line = __LINE__; + crash_msg = "Invalid logword"; + goto crash; break; }//switch /*---------------------------------------------------------------------------*/ @@ -14958,6 +14946,35 @@ void Dblqh::execSr(Signal* signal) // that we reach a new page. /*---------------------------------------------------------------------------*/ } while (1); + return; + +crash: + signal->theData[0] = RNIL; + signal->theData[1] = logPartPtr.i; + Uint32 tmp = logFilePtr.p->fileName[3]; + tmp = (tmp >> 8) & 0xff;// To get the Directory, DXX. + signal->theData[2] = tmp; + signal->theData[3] = logFilePtr.p->fileNo; + signal->theData[4] = logFilePtr.p->currentMbyte; + signal->theData[5] = logFilePtr.p->currentFilepage; + signal->theData[6] = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]; + signal->theData[7] = logWord; + signal->theData[8] = line; + + char buf[255]; + BaseString::snprintf(buf, sizeof(buf), + "Error while reading REDO log. from %d\n" + "D=%d, F=%d Mb=%d FP=%d W1=%d W2=%d : %s", + signal->theData[8], + signal->theData[2], + signal->theData[3], + signal->theData[4], + signal->theData[5], + signal->theData[6], + signal->theData[7], + crash_msg ? crash_msg : ""); + + progError(__LINE__, NDBD_EXIT_SR_REDOLOG, buf); }//Dblqh::execSr() /*---------------------------------------------------------------------------*/ @@ -14973,8 +14990,8 @@ void Dblqh::execDEBUG_SIG(Signal* signal) UintR tdebug; jamEntry(); - logPagePtr.i = signal->theData[0]; - tdebug = logPagePtr.p->logPageWord[0]; + //logPagePtr.i = signal->theData[0]; + //tdebug = logPagePtr.p->logPageWord[0]; char buf[100]; BaseString::snprintf(buf, 100, diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp index ac7fca9cf93..bf6ce7129ba 100644 --- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp +++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp @@ -720,7 +720,7 @@ public: // Index data - bool isIndexOp; // Used to mark on-going TcKeyReq as indx table access + Uint8 isIndexOp; // Used to mark on-going TcKeyReq as indx table access bool indexOpReturn; UintR noIndexOp; // No outstanding index ops @@ -808,7 +808,7 @@ public: UintR savedState[LqhKeyConf::SignalLength]; // Index data - bool isIndexOp; // Used to mark on-going TcKeyReq as index table access + Uint8 isIndexOp; // Used to mark on-going TcKeyReq as index table access UintR indexOp; UintR currentIndexId; UintR attrInfoLen; diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 71f3aff05d4..dda743616f4 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -1775,8 +1775,7 @@ void Dbtc::execKEYINFO(Signal* signal) apiConnectptr.i = signal->theData[0]; tmaxData = 20; if (apiConnectptr.i >= capiConnectFilesize) { - jam(); - warningHandlerLab(signal, __LINE__); + TCKEY_abort(signal, 18); return; }//if ptrAss(apiConnectptr, apiConnectRecord); @@ -1785,9 +1784,7 @@ void Dbtc::execKEYINFO(Signal* signal) compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2]; compare_transid1 = compare_transid1 | compare_transid2; if (compare_transid1 != 0) { - jam(); - printState(signal, 10); - sendSignalErrorRefuseLab(signal); + TCKEY_abort(signal, 19); return; }//if switch (apiConnectptr.p->apiConnectstate) { @@ -2531,7 +2528,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) Uint32 TstartFlag = tcKeyReq->getStartFlag(Treqinfo); Uint32 TexecFlag = TcKeyReq::getExecuteFlag(Treqinfo); - bool isIndexOp = regApiPtr->isIndexOp; + Uint8 isIndexOp = regApiPtr->isIndexOp; bool isIndexOpReturn = regApiPtr->indexOpReturn; regApiPtr->isIndexOp = false; // Reset marker regApiPtr->m_exec_flag |= TexecFlag; @@ -3277,7 +3274,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal, sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16); sig2 = regApiPtr->transid[0]; sig3 = regApiPtr->transid[1]; - sig4 = regApiPtr->ndbapiBlockref; + sig4 = (regTcPtr->isIndexOp == 2) ? reference() : regApiPtr->ndbapiBlockref; sig5 = regTcPtr->clientData; sig6 = regCachePtr->scanInfo; @@ -8619,6 +8616,7 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) // left over from simple/dirty read } else { jam(); + jamLine(transP->apiConnectstate); errCode = ZSTATE_ERROR; goto SCAN_TAB_error_no_state_change; } @@ -12036,14 +12034,18 @@ void Dbtc::readIndexTable(Signal* signal, opType == ZREAD ? ZREAD : ZREAD_EX); TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 1); // Allways send one AttrInfo TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0); - BlockReference originalReceiver = regApiPtr->ndbapiBlockref; - regApiPtr->ndbapiBlockref = reference(); // Send result to me tcKeyReq->senderData = indexOp->indexOpId; indexOp->indexOpState = IOS_INDEX_ACCESS; regApiPtr->executingIndexOp = regApiPtr->accumulatingIndexOp; regApiPtr->accumulatingIndexOp = RNIL; - regApiPtr->isIndexOp = true; + regApiPtr->isIndexOp = 2; + if (ERROR_INSERTED(8037)) + { + ndbout_c("shifting index version"); + tcKeyReq->tableSchemaVersion = ~(Uint32)indexOp->tcIndxReq.tableSchemaVersion; + } + Uint32 remainingKey = indexOp->keyInfo.getSize(); bool moreKeyData = indexOp->keyInfo.first(keyIter); // *********** KEYINFO in TCKEYREQ *********** @@ -12062,21 +12064,13 @@ void Dbtc::readIndexTable(Signal* signal, ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0); ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0); EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength); - - /** - * "Fool" TC not to start commiting transaction since it always will - * have one outstanding lqhkeyreq - * This is later decreased when the index read is complete - */ - regApiPtr->lqhkeyreqrec++; + jamEntry(); - /** - * Remember ptr to index read operation - * (used to set correct save point id on index operation later) - */ - indexOp->indexReadTcConnect = regApiPtr->lastTcConnect; + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + goto err; + } - jamEntry(); // *********** KEYINFO *********** if (moreKeyData) { jam(); @@ -12096,6 +12090,10 @@ void Dbtc::readIndexTable(Signal* signal, EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + goto err; + } dataPos = 0; dataPtr = (Uint32 *) &keyInfo->keyData; } @@ -12106,10 +12104,32 @@ void Dbtc::readIndexTable(Signal* signal, EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal, KeyInfo::HeaderLength + dataPos); jamEntry(); + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + goto err; + } } } - regApiPtr->ndbapiBlockref = originalReceiver; // reset original receiver + /** + * "Fool" TC not to start commiting transaction since it always will + * have one outstanding lqhkeyreq + * This is later decreased when the index read is complete + */ + regApiPtr->lqhkeyreqrec++; + + /** + * Remember ptr to index read operation + * (used to set correct save point id on index operation later) + */ + indexOp->indexReadTcConnect = regApiPtr->lastTcConnect; + +done: + return; + +err: + jam(); + goto done; } /** @@ -12160,7 +12180,7 @@ void Dbtc::executeIndexOperation(Signal* signal, tcKeyReq->transId2 = regApiPtr->transid[1]; tcKeyReq->senderData = tcIndxReq->senderData; // Needed for TRANSID_AI to API indexOp->indexOpState = IOS_INDEX_OPERATION; - regApiPtr->isIndexOp = true; + regApiPtr->isIndexOp = 1; regApiPtr->executingIndexOp = indexOp->indexOpId;; regApiPtr->noIndexOp++; // Increase count @@ -12233,9 +12253,16 @@ void Dbtc::executeIndexOperation(Signal* signal, const Uint32 currSavePointId = regApiPtr->currSavePointId; regApiPtr->currSavePointId = tmp.p->savePointId; EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength); + jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + regApiPtr->currSavePointId = currSavePointId; - jamEntry(); // *********** KEYINFO *********** if (moreKeyData) { jam(); @@ -12256,6 +12283,13 @@ void Dbtc::executeIndexOperation(Signal* signal, EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPos = 0; dataPtr = (Uint32 *) &keyInfo->keyData; } @@ -12266,6 +12300,12 @@ void Dbtc::executeIndexOperation(Signal* signal, EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal, KeyInfo::HeaderLength + dataPos); jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } } } @@ -12295,6 +12335,13 @@ void Dbtc::executeIndexOperation(Signal* signal, EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal, AttrInfo::HeaderLength + AttrInfo::DataLength); jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + attrInfoPos = 0; dataPtr = (Uint32 *) &attrInfo->attrData; } @@ -12694,9 +12741,16 @@ void Dbtc::insertIntoIndexTable(Signal* signal, const Uint32 currSavePointId = regApiPtr->currSavePointId; regApiPtr->currSavePointId = opRecord->savePointId; EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength); + jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + regApiPtr->currSavePointId = currSavePointId; tcConnectptr.p->currentIndexId = indexData->indexId; - jamEntry(); // *********** KEYINFO *********** if (moreKeyData) { @@ -12726,6 +12780,12 @@ void Dbtc::insertIntoIndexTable(Signal* signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &keyInfo->keyData; dataPos = 0; } @@ -12761,6 +12821,13 @@ void Dbtc::insertIntoIndexTable(Signal* signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); #endif + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &keyInfo->keyData; dataPos = 0; } @@ -12778,6 +12845,11 @@ void Dbtc::insertIntoIndexTable(Signal* signal, KeyInfo::HeaderLength + dataPos); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } } } @@ -12813,6 +12885,12 @@ void Dbtc::insertIntoIndexTable(Signal* signal, AttrInfo::HeaderLength + AttrInfo::DataLength); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &attrInfo->attrData; attrInfoPos = 0; } @@ -12849,6 +12927,12 @@ void Dbtc::insertIntoIndexTable(Signal* signal, AttrInfo::HeaderLength + AttrInfo::DataLength); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &attrInfo->attrData; attrInfoPos = 0; } @@ -12994,9 +13078,16 @@ void Dbtc::deleteFromIndexTable(Signal* signal, const Uint32 currSavePointId = regApiPtr->currSavePointId; regApiPtr->currSavePointId = opRecord->savePointId; EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength); + jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + regApiPtr->currSavePointId = currSavePointId; tcConnectptr.p->currentIndexId = indexData->indexId; - jamEntry(); // *********** KEYINFO *********** if (moreKeyData) { @@ -13027,6 +13118,12 @@ void Dbtc::deleteFromIndexTable(Signal* signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &keyInfo->keyData; dataPos = 0; } @@ -13063,6 +13160,12 @@ void Dbtc::deleteFromIndexTable(Signal* signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &keyInfo->keyData; dataPos = 0; } diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index f83f21f14d8..13c0bad9c7a 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -1113,14 +1113,16 @@ Dbtup::updateStartLab(Signal* signal, regOperPtr->pageOffset, &cinBuffer[0], regOperPtr->attrinbufLen); - if (retValue == -1) { - tupkeyErrorLab(signal); - return -1; - }//if } else { jam(); retValue = interpreterStartLab(signal, pagePtr, regOperPtr->pageOffset); }//if + + if (retValue == -1) { + tupkeyErrorLab(signal); + return -1; + }//if + ndbrequire(regOperPtr->tupVersion != ZNIL); pagePtr->pageWord[regOperPtr->pageOffset + 1] = regOperPtr->tupVersion; if (regTabPtr->checksumIndicator) { diff --git a/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp b/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp index 9722aa437c0..8a18fddae19 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp @@ -184,24 +184,28 @@ void Dbtup::allocConsPages(Uint32 noOfPagesToAllocate, /* PROPER AMOUNT OF PAGES WERE NOT FOUND. FIND AS MUCH AS */ /* POSSIBLE. */ /* ---------------------------------------------------------------- */ - for (Uint32 j = firstListToCheck; (Uint32)~j; j--) { + if (firstListToCheck) + { ljam(); - if (cfreepageList[j] != RNIL) { + for (Uint32 j = firstListToCheck - 1; (Uint32)~j; j--) { ljam(); + if (cfreepageList[j] != RNIL) { + ljam(); /* ---------------------------------------------------------------- */ /* SOME AREA WAS FOUND, ALLOCATE ALL OF IT. */ /* ---------------------------------------------------------------- */ - allocPageRef = cfreepageList[j]; - removeCommonArea(allocPageRef, j); - noOfPagesAllocated = 1 << j; - findFreeLeftNeighbours(allocPageRef, noOfPagesAllocated, - noOfPagesToAllocate); - findFreeRightNeighbours(allocPageRef, noOfPagesAllocated, - noOfPagesToAllocate); - - return; - }//if - }//for + allocPageRef = cfreepageList[j]; + removeCommonArea(allocPageRef, j); + noOfPagesAllocated = 1 << j; + findFreeLeftNeighbours(allocPageRef, noOfPagesAllocated, + noOfPagesToAllocate); + findFreeRightNeighbours(allocPageRef, noOfPagesAllocated, + noOfPagesToAllocate); + + return; + }//if + }//for + } /* ---------------------------------------------------------------- */ /* NO FREE AREA AT ALL EXISTED. RETURN ZERO PAGES */ /* ---------------------------------------------------------------- */ diff --git a/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp b/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp index acdb73704cb..0bb7c8a1e41 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp @@ -397,12 +397,12 @@ void Dbtup::allocMoreFragPages(Fragrecord* const regFragPtr) Uint32 noAllocPages = regFragPtr->noOfPagesToGrow >> 3; // 12.5% noAllocPages += regFragPtr->noOfPagesToGrow >> 4; // 6.25% noAllocPages += 2; - regFragPtr->noOfPagesToGrow += noAllocPages; /* -----------------------------------------------------------------*/ // We will grow by 18.75% plus two more additional pages to grow // a little bit quicker in the beginning. /* -----------------------------------------------------------------*/ - allocFragPages(regFragPtr, noAllocPages); + Uint32 allocated = allocFragPages(regFragPtr, noAllocPages); + regFragPtr->noOfPagesToGrow += allocated; }//Dbtup::allocMoreFragPages() Uint32 Dbtup::leafPageRangeFull(Fragrecord* const regFragPtr, PageRangePtr currPageRangePtr) diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index e6bb4d4f14f..fe6caf04d8c 100644 --- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -181,10 +181,9 @@ void Ndbcntr::execSYSTEM_ERROR(Signal* signal) case SystemError::CopyFragRefError: BaseString::snprintf(buf, sizeof(buf), - "Node %d killed this node because " - "it could not copy a fragment during node restart. " - "Copy fragment error code: %u.", - killingNode, data1); + "Killed by node %d as " + "copyfrag failed, error: %u", + killingNode, data1); break; default: @@ -2043,6 +2042,11 @@ void Ndbcntr::execSET_VAR_REQ(Signal* signal) { void Ndbcntr::updateNodeState(Signal* signal, const NodeState& newState) const{ NodeStateRep * const stateRep = (NodeStateRep *)&signal->theData[0]; + if (newState.startLevel == NodeState::SL_STARTED) + { + CRASH_INSERTION(1000); + } + stateRep->nodeState = newState; stateRep->nodeState.masterNodeId = cmasterNodeId; stateRep->nodeState.setNodeGroup(c_nodeGroup); @@ -2843,7 +2847,7 @@ void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){ cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB); } } - + signal->theData[0] = NDB_LE_NDBStartCompleted; signal->theData[1] = NDB_VERSION; cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); diff --git a/ndb/src/kernel/vm/DLHashTable2.hpp b/ndb/src/kernel/vm/DLHashTable2.hpp index 6b166331631..1018b053e2a 100644 --- a/ndb/src/kernel/vm/DLHashTable2.hpp +++ b/ndb/src/kernel/vm/DLHashTable2.hpp @@ -147,6 +147,8 @@ public: * @param iter - An "uninitialized" iterator */ bool next(Uint32 bucket, Iterator & iter) const; + + inline bool isEmpty() const { Iterator iter; return ! first(iter); } private: Uint32 mask; diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index 4428b158b6b..9bf19dda3a4 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -1389,7 +1389,7 @@ ndb_mgm_listen_event_internal(NdbMgmHandle handle, const int filter[], MGM_END() }; CHECK_HANDLE(handle, -1); - + const char *hostname= ndb_mgm_get_connected_host(handle); int port= ndb_mgm_get_connected_port(handle); SocketClient s(hostname, port); @@ -1411,19 +1411,20 @@ ndb_mgm_listen_event_internal(NdbMgmHandle handle, const int filter[], } args.put("filter", tmp.c_str()); } - + int tmp = handle->socket; handle->socket = sockfd; - + const Properties *reply; reply = ndb_mgm_call(handle, stat_reply, "listen event", &args); - + handle->socket = tmp; - + if(reply == NULL) { close(sockfd); CHECK_REPLY(reply, -1); } + delete reply; return sockfd; } diff --git a/ndb/src/mgmapi/ndb_logevent.cpp b/ndb/src/mgmapi/ndb_logevent.cpp index a90d5658506..2472a434590 100644 --- a/ndb/src/mgmapi/ndb_logevent.cpp +++ b/ndb/src/mgmapi/ndb_logevent.cpp @@ -68,6 +68,13 @@ ndb_mgm_create_logevent_handle(NdbMgmHandle mh, } extern "C" +int +ndb_logevent_get_fd(const NdbLogEventHandle h) +{ + return h->socket; +} + +extern "C" void ndb_mgm_destroy_logevent_handle(NdbLogEventHandle * h) { if( !h ) diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index 58b98671b14..ba68f6e4f0a 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -173,8 +173,15 @@ private: bool rep_connected; #endif struct NdbThread* m_event_thread; + NdbMutex *m_print_mutex; }; +struct event_thread_param { + NdbMgmHandle *m; + NdbMutex **p; +}; + +NdbMutex* print_mutex; /* * Facade object for CommandInterpreter @@ -395,6 +402,7 @@ CommandInterpreter::CommandInterpreter(const char *_host,int verbose) m_connected= false; m_event_thread= 0; try_reconnect = 0; + m_print_mutex= NdbMutex_Create(); #ifdef HAVE_GLOBAL_REPLICATION rep_host = NULL; m_repserver = NULL; @@ -408,6 +416,7 @@ CommandInterpreter::CommandInterpreter(const char *_host,int verbose) CommandInterpreter::~CommandInterpreter() { disconnect(); + NdbMutex_Destroy(m_print_mutex); } static bool @@ -444,11 +453,13 @@ CommandInterpreter::printError() static int do_event_thread; static void* -event_thread_run(void* m) +event_thread_run(void* p) { DBUG_ENTER("event_thread_run"); - NdbMgmHandle handle= *(NdbMgmHandle*)m; + struct event_thread_param param= *(struct event_thread_param*)p; + NdbMgmHandle handle= *(param.m); + NdbMutex* printmutex= *(param.p); int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 1, NDB_MGM_EVENT_CATEGORY_STARTUP, @@ -466,7 +477,11 @@ event_thread_run(void* m) { const char ping_token[]= "<PING>"; if (memcmp(ping_token,tmp,sizeof(ping_token)-1)) - ndbout << tmp; + if(tmp && strlen(tmp)) + { + Guard g(printmutex); + ndbout << tmp; + } } } while(do_event_thread); NDB_CLOSE_SOCKET(fd); @@ -519,8 +534,11 @@ CommandInterpreter::connect() assert(m_event_thread == 0); assert(do_event_thread == 0); do_event_thread= 0; + struct event_thread_param p; + p.m= &m_mgmsrv2; + p.p= &m_print_mutex; m_event_thread = NdbThread_Create(event_thread_run, - (void**)&m_mgmsrv2, + (void**)&p, 32768, "CommandInterpreted_event_thread", NDB_THREAD_PRIO_LOW); @@ -607,6 +625,7 @@ CommandInterpreter::execute(const char *_line, int _try_reconnect, int result= execute_impl(_line); if (error) *error= m_error; + return result; } @@ -686,6 +705,7 @@ CommandInterpreter::execute_impl(const char *_line) DBUG_RETURN(true); if (strcasecmp(firstToken, "SHOW") == 0) { + Guard g(m_print_mutex); executeShow(allAfterFirstToken); DBUG_RETURN(true); } @@ -920,6 +940,7 @@ CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun, ndbout_c("Trying to start all nodes of system."); ndbout_c("Use ALL STATUS to see the system start-up phases."); } else { + Guard g(m_print_mutex); struct ndb_mgm_cluster_state *cl= ndb_mgm_get_status(m_mgmsrv); if(cl == 0){ ndbout_c("Unable get status from management server"); @@ -1224,6 +1245,7 @@ CommandInterpreter::executeShow(char* parameters) if(it == 0){ ndbout_c("Unable to create config iterator"); + ndb_mgm_destroy_configuration(conf); return; } NdbAutoPtr<ndb_mgm_configuration_iterator> ptr(it); @@ -1270,6 +1292,7 @@ CommandInterpreter::executeShow(char* parameters) print_nodes(state, it, "ndb_mgmd", mgm_nodes, NDB_MGM_NODE_TYPE_MGM, 0); print_nodes(state, it, "mysqld", api_nodes, NDB_MGM_NODE_TYPE_API, 0); // ndbout << helpTextShow; + ndb_mgm_destroy_configuration(conf); return; } else if (strcasecmp(parameters, "PROPERTIES") == 0 || strcasecmp(parameters, "PROP") == 0) { diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index 69c0286a1de..5fabb84adb7 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -77,7 +77,6 @@ }\ } -extern int global_flag_send_heartbeat_now; extern int g_no_nodeid_checks; extern my_bool opt_core; @@ -1455,6 +1454,12 @@ MgmtSrvr::exitSingleUser(int * stopCount, bool abort) #include <ClusterMgr.hpp> +void +MgmtSrvr::updateStatus() +{ + theFacade->theClusterMgr->forceHB(); +} + int MgmtSrvr::status(int nodeId, ndb_mgm_node_status * _status, @@ -2153,7 +2158,7 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId, if (found_matching_type && !found_free_node) { // we have a temporary error which might be due to that // we have got the latest connect status from db-nodes. Force update. - global_flag_send_heartbeat_now= 1; + updateStatus(); } BaseString type_string, type_c_string; @@ -2507,7 +2512,7 @@ MgmtSrvr::Allocated_resources::~Allocated_resources() if (!m_reserved_nodes.isclear()) { m_mgmsrv.m_reserved_nodes.bitANDC(m_reserved_nodes); // node has been reserved, force update signal to ndb nodes - global_flag_send_heartbeat_now= 1; + m_mgmsrv.updateStatus(); char tmp_str[128]; m_mgmsrv.m_reserved_nodes.getText(tmp_str); diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp index 187f225470a..17debb19f50 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -490,6 +490,8 @@ public: void get_connected_nodes(NodeBitmask &connected_nodes) const; SocketServer *get_socket_server() { return m_socket_server; } + void updateStatus(); + //************************************************************************** private: //************************************************************************** diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index 0524aba4c32..7f5b0e29442 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -982,6 +982,7 @@ printNodeStatus(OutputStream *output, MgmtSrvr &mgmsrv, enum ndb_mgm_node_type type) { NodeId nodeId = 0; + mgmsrv.updateStatus(); while(mgmsrv.getNextNodeId(&nodeId, type)) { enum ndb_mgm_node_status status; Uint32 startPhase = 0, diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp index fbff57d3168..475561af225 100644 --- a/ndb/src/ndbapi/ClusterMgr.cpp +++ b/ndb/src/ndbapi/ClusterMgr.cpp @@ -37,7 +37,7 @@ #include <mgmapi_configuration.hpp> #include <mgmapi_config_parameters.h> -int global_flag_send_heartbeat_now= 0; +//#define DEBUG_REG // Just a C wrapper for threadMain extern "C" @@ -67,6 +67,8 @@ ClusterMgr::ClusterMgr(TransporterFacade & _facade): DBUG_ENTER("ClusterMgr::ClusterMgr"); ndbSetOwnVersion(); clusterMgrThreadMutex = NdbMutex_Create(); + waitForHBCond= NdbCondition_Create(); + waitingForHB= false; noOfAliveNodes= 0; noOfConnectedNodes= 0; theClusterMgrThread= 0; @@ -77,7 +79,8 @@ ClusterMgr::ClusterMgr(TransporterFacade & _facade): ClusterMgr::~ClusterMgr() { DBUG_ENTER("ClusterMgr::~ClusterMgr"); - doStop(); + doStop(); + NdbCondition_Destroy(waitForHBCond); NdbMutex_Destroy(clusterMgrThreadMutex); DBUG_VOID_RETURN; } @@ -164,6 +167,70 @@ ClusterMgr::doStop( ){ } void +ClusterMgr::forceHB() +{ + theFacade.lock_mutex(); + + if(waitingForHB) + { + NdbCondition_WaitTimeout(waitForHBCond, theFacade.theMutexPtr, 1000); + theFacade.unlock_mutex(); + return; + } + + waitingForHB= true; + + NodeBitmask ndb_nodes; + ndb_nodes.clear(); + waitForHBFromNodes.clear(); + for(Uint32 i = 0; i < MAX_NODES; i++) + { + if(!theNodes[i].defined) + continue; + if(theNodes[i].m_info.m_type == NodeInfo::DB) + { + ndb_nodes.set(i); + const ClusterMgr::Node &node= getNodeInfo(i); + waitForHBFromNodes.bitOR(node.m_state.m_connected_nodes); + } + } + waitForHBFromNodes.bitAND(ndb_nodes); + +#ifdef DEBUG_REG + char buf[128]; + ndbout << "Waiting for HB from " << waitForHBFromNodes.getText(buf) << endl; +#endif + NdbApiSignal signal(numberToRef(API_CLUSTERMGR, theFacade.ownId())); + + signal.theVerId_signalNumber = GSN_API_REGREQ; + signal.theReceiversBlockNumber = QMGR; + signal.theTrace = 0; + signal.theLength = ApiRegReq::SignalLength; + + ApiRegReq * req = CAST_PTR(ApiRegReq, signal.getDataPtrSend()); + req->ref = numberToRef(API_CLUSTERMGR, theFacade.ownId()); + req->version = NDB_VERSION; + + int nodeId= 0; + for(int i=0; + NodeBitmask::NotFound!=(nodeId= waitForHBFromNodes.find(i)); + i= nodeId+1) + { +#ifdef DEBUG_REG + ndbout << "FORCE HB to " << nodeId << endl; +#endif + theFacade.sendSignalUnCond(&signal, nodeId); + } + + NdbCondition_WaitTimeout(waitForHBCond, theFacade.theMutexPtr, 1000); + waitingForHB= false; +#ifdef DEBUG_REG + ndbout << "Still waiting for HB from " << waitForHBFromNodes.getText(buf) << endl; +#endif + theFacade.unlock_mutex(); +} + +void ClusterMgr::threadMain( ){ NdbApiSignal signal(numberToRef(API_CLUSTERMGR, theFacade.ownId())); @@ -184,9 +251,6 @@ ClusterMgr::threadMain( ){ /** * Start of Secure area for use of Transporter */ - int send_heartbeat_now= global_flag_send_heartbeat_now; - global_flag_send_heartbeat_now= 0; - theFacade.lock_mutex(); for (int i = 1; i < MAX_NODES; i++){ /** @@ -209,8 +273,7 @@ ClusterMgr::threadMain( ){ } theNode.hbCounter += timeSlept; - if (theNode.hbCounter >= theNode.hbFrequency || - send_heartbeat_now) { + if (theNode.hbCounter >= theNode.hbFrequency) { /** * It is now time to send a new Heartbeat */ @@ -226,7 +289,7 @@ ClusterMgr::threadMain( ){ if (theNode.m_info.m_type == NodeInfo::REP) { signal.theReceiversBlockNumber = API_CLUSTERMGR; } -#if 0 +#ifdef DEBUG_REG ndbout_c("ClusterMgr: Sending API_REGREQ to node %d", (int)nodeId); #endif theFacade.sendSignalUnCond(&signal, nodeId); @@ -278,7 +341,7 @@ ClusterMgr::execAPI_REGREQ(const Uint32 * theData){ const ApiRegReq * const apiRegReq = (ApiRegReq *)&theData[0]; const NodeId nodeId = refToNode(apiRegReq->ref); -#if 0 +#ifdef DEBUG_REG ndbout_c("ClusterMgr: Recd API_REGREQ from node %d", nodeId); #endif @@ -319,7 +382,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){ const ApiRegConf * const apiRegConf = (ApiRegConf *)&theData[0]; const NodeId nodeId = refToNode(apiRegConf->qmgrRef); -#if 0 +#ifdef DEBUG_REG ndbout_c("ClusterMgr: Recd API_REGCONF from node %d", nodeId); #endif @@ -351,6 +414,17 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){ if (node.m_info.m_type != NodeInfo::REP) { node.hbFrequency = (apiRegConf->apiHeartbeatFrequency * 10) - 50; } + + if(waitingForHB) + { + waitForHBFromNodes.clear(nodeId); + + if(waitForHBFromNodes.isclear()) + { + waitingForHB= false; + NdbCondition_Broadcast(waitForHBCond); + } + } } void @@ -379,6 +453,10 @@ ClusterMgr::execAPI_REGREF(const Uint32 * theData){ default: break; } + + waitForHBFromNodes.clear(nodeId); + if(waitForHBFromNodes.isclear()) + NdbCondition_Signal(waitForHBCond); } void diff --git a/ndb/src/ndbapi/ClusterMgr.hpp b/ndb/src/ndbapi/ClusterMgr.hpp index 1a1e622a889..d2bcc52f7e8 100644 --- a/ndb/src/ndbapi/ClusterMgr.hpp +++ b/ndb/src/ndbapi/ClusterMgr.hpp @@ -49,7 +49,9 @@ public: void doStop(); void startThread(); - + + void forceHB(); + private: void threadMain(); @@ -85,7 +87,11 @@ private: Uint32 noOfConnectedNodes; Node theNodes[MAX_NODES]; NdbThread* theClusterMgrThread; - + + NodeBitmask waitForHBFromNodes; // used in forcing HBs + NdbCondition* waitForHBCond; + bool waitingForHB; + /** * Used for controlling start/stop of the thread */ diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index 90e3a63c53d..c5a0ebbaf60 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -475,6 +475,8 @@ int NdbScanOperation::nextResultImpl(bool fetchAllowed, bool forceSend) idx = m_current_api_receiver; last = m_api_receivers_count; + + Uint32 timeout = tp->m_waitfor_timeout; do { if(theError.code){ @@ -502,7 +504,7 @@ int NdbScanOperation::nextResultImpl(bool fetchAllowed, bool forceSend) */ theNdb->theImpl->theWaiter.m_node = nodeId; theNdb->theImpl->theWaiter.m_state = WAIT_SCAN; - int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + int return_code = theNdb->receiveResponse(3*timeout); if (return_code == 0 && seq == tp->getNodeSequence(nodeId)) { continue; } else { @@ -1365,6 +1367,7 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed, return -1; Uint32 seq = theNdbCon->theNodeSequence; Uint32 nodeId = theNdbCon->theDBnode; + Uint32 timeout = tp->m_waitfor_timeout; if(seq == tp->getNodeSequence(nodeId) && !send_next_scan_ordered(s_idx, forceSend)){ Uint32 tmp = m_sent_receivers_count; @@ -1372,7 +1375,7 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed, while(m_sent_receivers_count > 0 && !theError.code){ theNdb->theImpl->theWaiter.m_node = nodeId; theNdb->theImpl->theWaiter.m_state = WAIT_SCAN; - int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + int return_code = theNdb->receiveResponse(3*timeout); if (return_code == 0 && seq == tp->getNodeSequence(nodeId)) { continue; } @@ -1513,6 +1516,8 @@ NdbScanOperation::close_impl(TransporterFacade* tp, bool forceSend){ return -1; } + Uint32 timeout = tp->m_waitfor_timeout; + /** * Wait for outstanding */ @@ -1520,7 +1525,7 @@ NdbScanOperation::close_impl(TransporterFacade* tp, bool forceSend){ { theNdb->theImpl->theWaiter.m_node = nodeId; theNdb->theImpl->theWaiter.m_state = WAIT_SCAN; - int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + int return_code = theNdb->receiveResponse(3*timeout); switch(return_code){ case 0: break; @@ -1590,7 +1595,7 @@ NdbScanOperation::close_impl(TransporterFacade* tp, bool forceSend){ { theNdb->theImpl->theWaiter.m_node = nodeId; theNdb->theImpl->theWaiter.m_state = WAIT_SCAN; - int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + int return_code = theNdb->receiveResponse(3*timeout); switch(return_code){ case 0: break; diff --git a/ndb/test/include/NDBT_Tables.hpp b/ndb/test/include/NDBT_Tables.hpp index fb0df8aa35b..a6973861af8 100644 --- a/ndb/test/include/NDBT_Tables.hpp +++ b/ndb/test/include/NDBT_Tables.hpp @@ -42,6 +42,8 @@ public: static const NdbDictionary::Table* getTable(int _num); static int getNumTables(); + static const char** getIndexes(const char* table); + private: static const NdbDictionary::Table* tableWithPkSize(const char* _nam, Uint32 pkSize); }; diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp index b992d492ad6..ba05bbad7bb 100644 --- a/ndb/test/ndbapi/testDict.cpp +++ b/ndb/test/ndbapi/testDict.cpp @@ -1022,8 +1022,8 @@ int verifyTablesAreEqual(const NdbDictionary::Table* pTab, const NdbDictionary:: if (!pTab->equal(*pTab2)){ g_err << "equal failed" << endl; - g_info << *pTab; - g_info << *pTab2; + g_info << *(NDBT_Table*)pTab; // gcc-4.1.2 + g_info << *(NDBT_Table*)pTab2; return NDBT_FAILED; } return NDBT_OK; @@ -1033,7 +1033,7 @@ int runGetPrimaryKey(NDBT_Context* ctx, NDBT_Step* step){ Ndb* pNdb = GETNDB(step); const NdbDictionary::Table* pTab = ctx->getTab(); ndbout << "|- " << pTab->getName() << endl; - g_info << *pTab; + g_info << *(NDBT_Table*)pTab; // Try to create table in db if (pTab->createTableInDb(pNdb) != 0){ return NDBT_FAILED; @@ -1890,6 +1890,52 @@ runDictOps(NDBT_Context* ctx, NDBT_Step* step) // replace by the Retrieved table pTab = pTab2; + // create indexes + const char** indlist = NDBT_Tables::getIndexes(tabName); + uint indnum = 0; + while (*indlist != 0) { + uint count = 0; + try_create_index: + count++; + if (count == 1) + g_info << "2: create index " << indnum << " " << *indlist << endl; + NdbDictionary::Index ind; + char indName[200]; + sprintf(indName, "%s_X%u", tabName, indnum); + ind.setName(indName); + ind.setTable(tabName); + if (strcmp(*indlist, "UNIQUE") == 0) { + ind.setType(NdbDictionary::Index::UniqueHashIndex); + ind.setLogging(pTab->getLogging()); + } else if (strcmp(*indlist, "ORDERED") == 0) { + ind.setType(NdbDictionary::Index::OrderedIndex); + ind.setLogging(false); + } else { + assert(false); + } + const char** indtemp = indlist; + while (*++indtemp != 0) { + ind.addColumn(*indtemp); + } + if (pDic->createIndex(ind) != 0) { + const NdbError err = pDic->getNdbError(); + if (count == 1) + g_err << "2: " << indName << ": create failed: " << err << endl; + if (err.code != 711) { + result = NDBT_FAILED; + break; + } + NdbSleep_MilliSleep(myRandom48(maxsleep)); + goto try_create_index; + } + indlist = ++indtemp; + indnum++; + } + if (result == NDBT_FAILED) + break; + + uint indcount = indnum; + int records = myRandom48(ctx->getNumRecords()); g_info << "2: load " << records << " records" << endl; HugoTransactions hugoTrans(*pTab); @@ -1901,6 +1947,32 @@ runDictOps(NDBT_Context* ctx, NDBT_Step* step) } NdbSleep_MilliSleep(myRandom48(maxsleep)); + // drop indexes + indnum = 0; + while (indnum < indcount) { + uint count = 0; + try_drop_index: + count++; + if (count == 1) + g_info << "2: drop index " << indnum << endl; + char indName[200]; + sprintf(indName, "%s_X%u", tabName, indnum); + if (pDic->dropIndex(indName, tabName) != 0) { + const NdbError err = pDic->getNdbError(); + if (count == 1) + g_err << "2: " << indName << ": drop failed: " << err << endl; + if (err.code != 711) { + result = NDBT_FAILED; + break; + } + NdbSleep_MilliSleep(myRandom48(maxsleep)); + goto try_drop_index; + } + indnum++; + } + if (result == NDBT_FAILED) + break; + g_info << "2: drop" << endl; { uint count = 0; diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp index 5785db232c4..c25aae55897 100644 --- a/ndb/test/ndbapi/testIndex.cpp +++ b/ndb/test/ndbapi/testIndex.cpp @@ -1199,6 +1199,48 @@ int runLQHKEYREF(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int +runBug21384(NDBT_Context* ctx, NDBT_Step* step) +{ + Ndb* pNdb = GETNDB(step); + HugoTransactions hugoTrans(*ctx->getTab()); + NdbRestarter restarter; + + int loops = ctx->getNumLoops(); + const int rows = ctx->getNumRecords(); + const int batchsize = ctx->getProperty("BatchSize", 50); + + while (loops--) + { + if(restarter.insertErrorInAllNodes(8037) != 0) + { + g_err << "Failed to error insert(8037)" << endl; + return NDBT_FAILED; + } + + if (hugoTrans.indexReadRecords(pNdb, pkIdxName, rows, batchsize) == 0) + { + g_err << "Index succeded (it should have failed" << endl; + return NDBT_FAILED; + } + + if(restarter.insertErrorInAllNodes(0) != 0) + { + g_err << "Failed to error insert(0)" << endl; + return NDBT_FAILED; + } + + if (hugoTrans.indexReadRecords(pNdb, pkIdxName, rows, batchsize) != 0){ + g_err << "Index read failed" << endl; + return NDBT_FAILED; + } + } + + return NDBT_OK; +} + + + NDBT_TESTSUITE(testIndex); TESTCASE("CreateAll", "Test that we can create all various indexes on each table\n" @@ -1512,6 +1554,16 @@ TESTCASE("UniqueNull", FINALIZER(createPkIndex_Drop); FINALIZER(runClearTable); } +TESTCASE("Bug21384", + "Test that unique indexes and nulls"){ + TC_PROPERTY("LoggedIndexes", (unsigned)0); + INITIALIZER(runClearTable); + INITIALIZER(createPkIndex); + INITIALIZER(runLoadTable); + STEP(runBug21384); + FINALIZER(createPkIndex_Drop); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testIndex); int main(int argc, const char** argv){ diff --git a/ndb/test/ndbapi/testSystemRestart.cpp b/ndb/test/ndbapi/testSystemRestart.cpp index 30f7aca9b06..8a0100ff3e4 100644 --- a/ndb/test/ndbapi/testSystemRestart.cpp +++ b/ndb/test/ndbapi/testSystemRestart.cpp @@ -1121,6 +1121,46 @@ int runClearTable(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int +runBug21536(NDBT_Context* ctx, NDBT_Step* step) +{ + NdbRestarter restarter; + const Uint32 nodeCount = restarter.getNumDbNodes(); + if(nodeCount != 2){ + g_info << "Bug21536 - 2 nodes to test" << endl; + return NDBT_OK; + } + + int node1 = restarter.getDbNodeId(rand() % nodeCount); + int node2 = restarter.getRandomNodeSameNodeGroup(node1, rand()); + + if (node1 == -1 || node2 == -1) + return NDBT_OK; + + int result = NDBT_OK; + do { + CHECK(restarter.restartOneDbNode(node1, false, true, true) == 0); + CHECK(restarter.waitNodesNoStart(&node1, 1) == 0); + CHECK(restarter.insertErrorInNode(node1, 1000) == 0); + int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 }; + CHECK(restarter.dumpStateOneNode(node1, val2, 2) == 0); + CHECK(restarter.startNodes(&node1, 1) == 0); + restarter.waitNodesStartPhase(&node1, 1, 3, 120); + CHECK(restarter.waitNodesNoStart(&node1, 1) == 0); + + CHECK(restarter.restartOneDbNode(node2, true, true, true) == 0); + CHECK(restarter.waitNodesNoStart(&node2, 1) == 0); + CHECK(restarter.startNodes(&node1, 1) == 0); + CHECK(restarter.waitNodesStarted(&node1, 1) == 0); + CHECK(restarter.startNodes(&node2, 1) == 0); + CHECK(restarter.waitClusterStarted() == 0); + + } while(0); + + g_info << "Bug21536 finished" << endl; + + return result; +} NDBT_TESTSUITE(testSystemRestart); TESTCASE("SR1", @@ -1287,6 +1327,13 @@ TESTCASE("Bug18385", STEP(runBug18385); FINALIZER(runClearTable); } +TESTCASE("Bug21536", + "Perform partition system restart with other nodes with higher GCI"){ + INITIALIZER(runWaitStarted); + INITIALIZER(runClearTable); + STEP(runBug21536); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testSystemRestart); int main(int argc, const char** argv){ diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index cbb8a9a2574..a2edc568426 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -449,6 +449,10 @@ max-time: 1000 cmd: testNodeRestart args: -n Bug20185 T1 +max-time: 1000 +cmd: testIndex +args: -n Bug21384 + # OLD FLEX max-time: 500 cmd: flexBench diff --git a/ndb/test/src/NDBT_Tables.cpp b/ndb/test/src/NDBT_Tables.cpp index 5a5fecd85c1..d72dfcc5031 100644 --- a/ndb/test/src/NDBT_Tables.cpp +++ b/ndb/test/src/NDBT_Tables.cpp @@ -799,6 +799,17 @@ NDBT_Tables::getNumTables(){ return numTestTables; } +const char** +NDBT_Tables::getIndexes(const char* table) +{ + Uint32 i = 0; + for (i = 0; indexes[i].m_table != 0; i++) { + if (strcmp(indexes[i].m_table, table) == 0) + return indexes[i].m_indexes; + } + return 0; +} + int NDBT_Tables::createAllTables(Ndb* pNdb, bool _temp, bool existsOk){ diff --git a/ndb/tools/ndb_config.cpp b/ndb/tools/ndb_config.cpp index 27ab6a182bb..135bec7ef72 100644 --- a/ndb/tools/ndb_config.cpp +++ b/ndb/tools/ndb_config.cpp @@ -145,7 +145,7 @@ struct Match struct HostMatch : public Match { - virtual int eval(NdbMgmHandle, const Iter&); + virtual int eval(const Iter&); }; struct Apply @@ -402,7 +402,7 @@ Match::eval(const Iter& iter) } int -HostMatch::eval(NdbMgmHandle h, const Iter& iter) +HostMatch::eval(const Iter& iter) { const char* valc; diff --git a/regex/CMakeLists.txt b/regex/CMakeLists.txt new file mode 100755 index 00000000000..796481a62d5 --- /dev/null +++ b/regex/CMakeLists.txt @@ -0,0 +1,5 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/mysys}) +ADD_LIBRARY(regex debug.c regcomp.c regerror.c regexec.c regfree.c reginit.c split.c) diff --git a/regex/Makefile.am b/regex/Makefile.am index 7e8478e8123..1f496fcec62 100644 --- a/regex/Makefile.am +++ b/regex/Makefile.am @@ -25,7 +25,7 @@ re_SOURCES = split.c debug.c main.c re_LDFLAGS= @NOINST_LDFLAGS@ EXTRA_DIST = tests CHANGES COPYRIGHT WHATSNEW regexp.c \ debug.ih engine.ih main.ih regcomp.ih regerror.ih \ - regex.3 regex.7 + regex.3 regex.7 CMakeLists.txt test: re tests ./re < tests diff --git a/scripts/Makefile.am b/scripts/Makefile.am index a339ebc5b8f..dd4c133ff94 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -66,7 +66,8 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \ EXTRA_DIST = $(EXTRA_SCRIPTS) \ mysqlaccess.conf \ - mysqlbug + mysqlbug \ + make_win_bin_dist dist_pkgdata_DATA = fill_help_tables.sql mysql_fix_privilege_tables.sql diff --git a/scripts/make_win_bin_dist b/scripts/make_win_bin_dist new file mode 100755 index 00000000000..cc75245e5d9 --- /dev/null +++ b/scripts/make_win_bin_dist @@ -0,0 +1,345 @@ +#!/bin/sh + +# Exit if failing to copy, we want exact specifications, not +# just "what happen to be built". +set -e + +# ---------------------------------------------------------------------- +# Read first argument that is the base name of the resulting TAR file. +# See usage() function below for a description on the arguments. +# +# NOTE: We will read the rest of the command line later on. +# NOTE: Pattern matching with "{..,..}" can't be used, not portable. +# ---------------------------------------------------------------------- + +# FIXME FIXME "debug", own build or handled here? +# FIXME FIXME add way to copy from other builds executables + +usage() +{ + echo <<EOF +Usage: make_win_bin_dist [ options ] package-base-name [ copy-defs... ] + +This is a script to run from the top of a source tree built on Windows. +The "package-base-name" argument should be something like + + mysql-noinstall-5.0.25-win32 (or winx64) + +and will be the name of the directory of the unpacked ZIP (stripping +away the "noinstall" part of the ZIP file name if any) and the base +for the resulting package name. + +Options are + + --embedded Pack the embedded server and give error if not built. + The default is to pack it if it is built. + + --no-embedded Don't pack the embedded server even if built + + --debug Pack the debug binaries and give error if not built. + + --no-debug Don't pack the debug binaries even if built + + --only-debug The target for this build was "Debug", and we just + want to replace the normal binaries with debug + versions, i.e. no separate "debug" directories. + + --exe-suffix=SUF Add a suffix to the "mysqld" binary. + +As you might want to include files of directories from other builds +(like a "mysqld-max.exe" server), you can instruct this script do copy +them in for you. This is the "copy-def" arguments, and they are of the +form + + relative-dest-name=source-name ..... + +i.e. can be something like + + bin/mysqld-max.exe=../my-max-build/sql/release/mysqld.exe + +If you specify a directory the whole directory will be copied. + +EOF + exit 1 +} + +# ---------------------------------------------------------------------- +# We need to be at the top of a source tree, check that we are +# ---------------------------------------------------------------------- + +if [ ! -d "sql" ] ; then + echo "You need to run this script from inside the source tree" + usage +fi + +# ---------------------------------------------------------------------- +# Actual argument processing, first part +# ---------------------------------------------------------------------- + +NOINST_NAME="" +TARGET="release" +PACK_EMBEDDED="" # Could be "no", "yes" or empty +PACK_DEBUG="" # Could be "no", "yes" or empty +EXE_SUFFIX="" + +for arg do + shift + case "$arg" in + --embedded) PACK_EMBEDDED="yes" ;; + --no-embedded) PACK_EMBEDDED="no" ;; + --debug) PACK_DEBUG="yes" ;; + --no-debug) PACK_DEBUG="no" ;; + --only-debug) TARGET="debug" ; PACK_DEBUG="no" ;; + --exe-suffix=*) EXE_SUFFIX=`echo "$arg" | sed -e "s,--exe-suffix=,,"` ;; + -*) + echo "Unknown argument '$arg'" + usage + ;; + *) + NOINST_NAME="$arg" + break + esac +done + +if [ x"$NOINST_NAME" = x"" ] ; then + echo "No base package name given" + usage +fi +DESTDIR=`echo $NOINST_NAME | sed 's/-noinstall-/-/'` + +if [ -e $DESTDIR ] ; then + echo "Please remove the old $DESTDIR before running this script" + usage +fi + +# ---------------------------------------------------------------------- +# Copy executables, and client DLL (FIXME why?) +# ---------------------------------------------------------------------- + +trap 'echo "Clearning up and exiting..." ; rm -fr $DESTDIR; exit 1' ERR + +mkdir $DESTDIR +mkdir $DESTDIR/bin +cp client/$TARGET/*.exe $DESTDIR/bin/ +cp extra/$TARGET/*.exe $DESTDIR/bin/ +cp myisam/$TARGET/*.exe $DESTDIR/bin/ +cp server-tools/instance-manager/$TARGET/*.exe $DESTDIR/bin/ +cp tests/$TARGET/*.exe $DESTDIR/bin/ +cp libmysql/$TARGET/*.exe $DESTDIR/bin/ +cp libmysql/$TARGET/libmysql.dll $DESTDIR/bin/ + +# FIXME really needed?! +mv $DESTDIR/bin/comp_err.exe $DESTDIR/bin/comp-err.exe + +cp sql/$TARGET/mysqld.exe $DESTDIR/bin/mysqld$EXE_SUFFIX.exe + +if [ x"$PACK_DEBUG" = "" -a -f "sql/debug/mysqld.exe" -o \ + x"$PACK_DEBUG" = "yes" ] ; then + cp sql/debug/mysqld.exe $DESTDIR/bin/mysqld-debug.exe + cp sql/debug/mysqld.pdb $DESTDIR/bin/mysqld-debug.pdb + cp sql/debug/mysqld.map $DESTDIR/bin/mysqld-debug.map +fi + +# ---------------------------------------------------------------------- +# Copy data directory, readme files etc +# ---------------------------------------------------------------------- + +cp COPYING EXCEPTIONS-CLIENT $DESTDIR/ + +# FIXME is there ever a data directory to copy? +if [ -d win/data ] ; then + cp -pR win/data $DESTDIR/data +fi + +# FIXME maybe a flag to define "release build", or do the +# check from the calling script that all these are there, +# and with the correct content. + +mkdir $DESTDIR/Docs +cp Docs/INSTALL-BINARY $DESTDIR/Docs/ +cp Docs/manual.chm $DESTDIR/Docs/ || /bin/true +cp ChangeLog $DESTDIR/Docs/ || /bin/true +cp COPYING $DESTDIR/Docs/ +cp support-files/my-*.ini $DESTDIR/ + +# ---------------------------------------------------------------------- +# These will be filled in when we enable embedded. Note that if no +# argument is given, it is copied if exists, else a check is done. +# ---------------------------------------------------------------------- + +copy_embedded() +{ + mkdir -p $DESTDIR/Embedded/DLL/release \ + $DESTDIR/Embedded/static/release + cp libmysqld/libmysqld.def $DESTDIR/include/ + cp libmysqld/$TARGET/mysqlserver.lib $DESTDIR/Embedded/static/release/ + cp libmysqld/$TARGET/libmysqld.dll $DESTDIR/Embedded/DLL/release/ + cp libmysqld/$TARGET/libmysqld.exp $DESTDIR/Embedded/DLL/release/ + cp libmysqld/$TARGET/libmysqld.lib $DESTDIR/Embedded/DLL/release/ + + if [ x"$PACK_DEBUG" = "" -a -f "libmysqld/debug/libmysqld.lib" -o \ + x"$PACK_DEBUG" = "yes" ] ; then + mkdir -p $DESTDIR/Embedded/DLL/debug + cp libmysqld/debug/libmysqld.dll $DESTDIR/Embedded/DLL/debug/ + cp libmysqld/debug/libmysqld.exp $DESTDIR/Embedded/DLL/debug/ + cp libmysqld/debug/libmysqld.lib $DESTDIR/Embedded/DLL/debug/ + fi +} + +if [ x"$PACK_EMBEDDED" = "" -a \ + -f "libmysqld/$TARGET/mysqlserver.lib" -a \ + -f "libmysqld/$TARGET/libmysqld.lib" -o \ + x"$PACK_EMBEDDED" = "yes" ] ; then + copy_embedded +fi + +# ---------------------------------------------------------------------- +# FIXME test stuff that is useless garbage? +# ---------------------------------------------------------------------- + +mkdir -p $DESTDIR/examples/libmysqltest/release +cp libmysql/mytest.c libmysql/myTest.vcproj libmysql/$TARGET/myTest.exe \ + $DESTDIR/examples/libmysqltest/ +cp libmysql/$TARGET/myTest.exe $DESTDIR/examples/libmysqltest/release/ + +if [ x"$PACK_DEBUG" = "" -a -f "libmysql/debug/myTest.exe" -o \ + x"$PACK_DEBUG" = "yes" ] ; then + mkdir -p $DESTDIR/examples/libmysqltest/debug + cp libmysql/debug/myTest.exe $DESTDIR/examples/libmysqltest/debug/ +fi + +mkdir -p $DESTDIR/examples/tests +cp tests/*.res tests/*.tst tests/*.pl tests/*.c $DESTDIR/examples/tests/ + +# ---------------------------------------------------------------------- +# FIXME why not copy it all in "include"?! +# ---------------------------------------------------------------------- + +mkdir -p $DESTDIR/include +cp include/conf*.h \ + include/mysql*.h \ + include/errmsg.h \ + include/my_alloc.h \ + include/my_getopt.h \ + include/my_sys.h \ + include/my_list.h \ + include/my_pthread.h \ + include/my_dbug.h \ + include/m_string.h \ + include/m_ctype.h \ + include/my_global.h \ + include/typelib.h $DESTDIR/include/ +cp libmysql/libmysql.def $DESTDIR/include/ + +# ---------------------------------------------------------------------- +# Client libraries, and other libraries +# FIXME why "libmysql.dll" installed both in "bin" and "lib/opt"? +# ---------------------------------------------------------------------- + +mkdir -p $DESTDIR/lib/opt +cp libmysql/$TARGET/libmysql.dll \ + libmysql/$TARGET/libmysql.lib \ + client/$TARGET/mysqlclient.lib \ + regex/$TARGET/regex.lib \ + strings/$TARGET/strings.lib \ + zlib/$TARGET/zlib.lib $DESTDIR/lib/opt/ + +if [ x"$PACK_DEBUG" = "" -a -f "libmysql/debug/libmysql.lib" -o \ + x"$PACK_DEBUG" = "yes" ] ; then + mkdir -p $DESTDIR/lib/debug + cp libmysql/debug/libmysql.dll \ + libmysql/debug/libmysql.lib \ + client/debug/mysqlclient.lib \ + mysys/debug/mysys.lib \ + regex/debug/regex.lib \ + strings/debug/strings.lib \ + zlib/debug/zlib.lib $DESTDIR/lib/debug/ +fi + +# FIXME sort this out... +cp mysys/$TARGET/mysys.lib $DESTDIR/lib/opt/mysys_tls.lib + +# ---------------------------------------------------------------------- +# Copy the test directory +# ---------------------------------------------------------------------- + +mkdir -p $DESTDIR/mysql-test/include $DESTDIR/mysql-test/lib \ + $DESTDIR/mysql-test/r $DESTDIR/mysql-test/std_data \ + $DESTDIR/mysql-test/t +cp mysql-test/mysql-test-run.pl $DESTDIR/mysql-test/ +cp mysql-test/README $DESTDIR/mysql-test/ +cp mysql-test/install_test_db.sh $DESTDIR/mysql-test/install_test_db +cp mysql-test/include/*.inc $DESTDIR/mysql-test/include/ +cp mysql-test/lib/*.pl $DESTDIR/mysql-test/lib/ +cp mysql-test/lib/*.sql $DESTDIR/mysql-test/lib/ +cp mysql-test/r/*.require $DESTDIR/mysql-test/r/ +# Need this trick, or we get "argument list too long". +ABS_DST=`pwd`/$DESTDIR +(cd mysql-test/r/ && cp *.result $ABS_DST/mysql-test/r/) +cp mysql-test/std_data/* $DESTDIR/mysql-test/std_data/ +cp mysql-test/t/*.opt $DESTDIR/mysql-test/t/ +cp mysql-test/t/*.sh $DESTDIR/mysql-test/t/ +cp mysql-test/t/*.slave-mi $DESTDIR/mysql-test/t/ +cp mysql-test/t/*.sql $DESTDIR/mysql-test/t/ +cp mysql-test/t/*.def $DESTDIR/mysql-test/t/ +(cd mysql-test/t/ && cp *.test $ABS_DST/mysql-test/t/) + +# Note that this will not copy "extra" if a soft link +if [ -d mysql-test/extra ] ; then + mkdir -p $DESTDIR/mysql-test/extra + cp -pR mysql-test/extra/* $DESTDIR/mysql-test/extra/ +fi + +# ---------------------------------------------------------------------- +# Copy what could be usable in the "scripts" directory. Currently +# only SQL files, others are bourne shell scripts or Perl scripts +# not really usable on Windows. +# +# But to be nice to the few Cygwin users we might have in 5.0 we +# continue to copy the stuff, but don't include it include it in +# the WiX install. +# ---------------------------------------------------------------------- + +mkdir -p $DESTDIR/scripts + +# Uncomment and remove the for loop in 5.1 +#cp scripts/*.sql $DESTDIR/scripts/ + +for i in `cd scripts && ls`; do \ + if echo $i | grep -q '\.sh'; then \ + cp scripts/$i $DESTDIR/scripts/`echo $i | sed -e 's/\.sh$//'`; \ + elif [ $i = Makefile.am -o $i = Makefile.in -o -e scripts/$i.sh ] ; then \ + : ; \ + else \ + cp scripts/$i $DESTDIR/scripts/$i; \ + fi; \ +done + +cp -pR sql/share $DESTDIR/ +cp -pR sql-bench $DESTDIR/ +rm -f $DESTDIR/sql-bench/*.sh $DESTDIR/sql-bench/Makefile* + +# ---------------------------------------------------------------------- +# Copy other files specified on command line DEST=SOURCE +# ---------------------------------------------------------------------- + +for arg do + dst=`echo $arg | sed 's/=.*$//'` + src=`echo $arg | sed 's/^.*=//'` + + if [ x"$dst" = x"" -o x"$src" = x"" ] ; then + echo "Invalid specification of what to copy" + usage + fi + + mkdir -p `dirname $DESTDIR/$dst` + cp -pR "$src" $DESTDIR/$dst +done + +# ---------------------------------------------------------------------- +# Finally creat the ZIP archive +# ---------------------------------------------------------------------- + +rm -f $NOINST_NAME.zip +zip -r $NOINST_NAME.zip $DESTDIR +rm -Rf $DESTDIR diff --git a/server-tools/CMakeLists.txt b/server-tools/CMakeLists.txt new file mode 100755 index 00000000000..1983d459ce2 --- /dev/null +++ b/server-tools/CMakeLists.txt @@ -0,0 +1,18 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +ADD_DEFINITIONS(-DMYSQL_SERVER -DMYSQL_INSTANCE_MANAGER) +INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/sql + ${PROJECT_SOURCE_DIR}/extra/yassl/include) + +ADD_EXECUTABLE(mysqlmanager buffer.cc command.cc commands.cc guardian.cc instance.cc instance_map.cc + instance_options.cc listener.cc log.cc manager.cc messages.cc mysql_connection.cc + mysqlmanager.cc options.cc parse.cc parse_output.cc priv.cc protocol.cc + thread_registry.cc user_map.cc imservice.cpp windowsservice.cpp + user_management_commands.cc + ../../sql/net_serv.cc ../../sql-common/pack.c ../../sql/password.c + ../../sql/sql_state.c ../../sql-common/client.c ../../libmysql/get_password.c + ../../libmysql/errmsg.c) + +ADD_DEPENDENCIES(mysqlmanager GenError) +TARGET_LINK_LIBRARIES(mysqlmanager dbug mysys strings taocrypt vio yassl zlib wsock32) diff --git a/server-tools/Makefile.am b/server-tools/Makefile.am index ed316b9ac38..573bf07ccff 100644 --- a/server-tools/Makefile.am +++ b/server-tools/Makefile.am @@ -1 +1,2 @@ SUBDIRS= instance-manager +DIST_SUBDIRS= instance-manager diff --git a/server-tools/instance-manager/CMakeLists.txt b/server-tools/instance-manager/CMakeLists.txt new file mode 100755 index 00000000000..fafc3df4108 --- /dev/null +++ b/server-tools/instance-manager/CMakeLists.txt @@ -0,0 +1,17 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +ADD_DEFINITIONS(-DMYSQL_SERVER -DMYSQL_INSTANCE_MANAGER) +INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/sql + ${PROJECT_SOURCE_DIR}/extra/yassl/include) + +ADD_EXECUTABLE(mysqlmanager buffer.cc command.cc commands.cc guardian.cc instance.cc instance_map.cc + instance_options.cc listener.cc log.cc manager.cc messages.cc mysql_connection.cc + mysqlmanager.cc options.cc parse.cc parse_output.cc priv.cc protocol.cc + thread_registry.cc user_map.cc IMService.cpp WindowsService.cpp + ../../sql/net_serv.cc ../../sql-common/pack.c ../../sql/password.c + ../../sql/sql_state.c ../../sql-common/client.c ../../libmysql/get_password.c + ../../libmysql/errmsg.c) + +ADD_DEPENDENCIES(mysqlmanager GenError) +TARGET_LINK_LIBRARIES(mysqlmanager dbug mysys strings taocrypt vio yassl zlib wsock32) diff --git a/server-tools/instance-manager/Makefile.am b/server-tools/instance-manager/Makefile.am index 6b5d80a99af..b1d77506efa 100644 --- a/server-tools/instance-manager/Makefile.am +++ b/server-tools/instance-manager/Makefile.am @@ -18,7 +18,8 @@ INCLUDES= @ZLIB_INCLUDES@ -I$(top_srcdir)/include \ @openssl_includes@ -I$(top_builddir)/include DEFS= -DMYSQL_INSTANCE_MANAGER -DMYSQL_SERVER - +EXTRA_DIST = IMService.cpp IMService.h WindowsService.cpp WindowsService.h \ + CMakeLists.txt # As all autoconf variables depend from ${prefix} and being resolved only when # make is run, we can not put these defines to a header file (e.g. to # default_options.h, generated from default_options.h.in) diff --git a/sql-common/client.c b/sql-common/client.c index 6819caddf35..fc483e7b4c7 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1514,7 +1514,6 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , mysql->options.ssl_ca= strdup_if_not_null(ca); mysql->options.ssl_capath= strdup_if_not_null(capath); mysql->options.ssl_cipher= strdup_if_not_null(cipher); - mysql->options.ssl_verify_server_cert= FALSE; /* Off by default */ #endif /* HAVE_OPENSSL */ DBUG_RETURN(0); } @@ -1759,7 +1758,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, const char *passwd, const char *db, uint port, const char *unix_socket,ulong client_flag) { - char buff[NAME_LEN+USERNAME_LENGTH+100]; + char buff[NAME_BYTE_LEN+USERNAME_BYTE_LENGTH+100]; char *end,*host_info; my_socket sock; in_addr_t ip_addr; @@ -2203,7 +2202,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, DBUG_PRINT("info", ("IO layer change done!")); /* Verify server cert */ - if (mysql->options.ssl_verify_server_cert && + if ((client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) && ssl_verify_server_cert(mysql->net.vio, mysql->host)) { set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); @@ -2218,7 +2217,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, mysql->server_status, client_flag)); /* This needs to be changed as it's not useful with big packets */ if (user && user[0]) - strmake(end,user,USERNAME_LENGTH); /* Max user name */ + strmake(end,user,USERNAME_BYTE_LENGTH); /* Max user name */ else read_user_name((char*) end); @@ -2248,7 +2247,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, /* Add database if needed */ if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) { - end= strmake(end, db, NAME_LEN) + 1; + end= strmake(end, db, NAME_BYTE_LEN) + 1; mysql->db= my_strdup(db,MYF(MY_WME)); db= 0; } @@ -2950,7 +2949,10 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) mysql->reconnect= *(my_bool *) arg; break; case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: - mysql->options.ssl_verify_server_cert= *(my_bool *) arg; + if (!arg || test(*(uint*) arg)) + mysql->options.client_flag|= CLIENT_SSL_VERIFY_SERVER_CERT; + else + mysql->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT; break; default: DBUG_RETURN(1); diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt new file mode 100755 index 00000000000..b01871872ce --- /dev/null +++ b/sql/CMakeLists.txt @@ -0,0 +1,114 @@ +SET(CMAKE_CXX_FLAGS_DEBUG + "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR /Zi") +SET(CMAKE_C_FLAGS_DEBUG + "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR /Zi") +SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /MAP /MAPINFO:EXPORTS") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/extra/yassl/include + ${CMAKE_SOURCE_DIR}/sql + ${CMAKE_SOURCE_DIR}/regex + ${CMAKE_SOURCE_DIR}/zlib + ${CMAKE_SOURCE_DIR}/bdb/build_win32 + ${CMAKE_SOURCE_DIR}/bdb/dbinc) + +SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/sql/message.rc + ${CMAKE_SOURCE_DIR}/sql/message.h + ${CMAKE_SOURCE_DIR}/sql/sql_yacc.h + ${CMAKE_SOURCE_DIR}/sql/sql_yacc.cc + ${CMAKE_SOURCE_DIR}/include/mysql_version.h + ${CMAKE_SOURCE_DIR}/sql/lex_hash.h + ${PROJECT_SOURCE_DIR}/include/mysqld_error.h + ${PROJECT_SOURCE_DIR}/include/mysqld_ername.h + ${PROJECT_SOURCE_DIR}/include/sql_state.h + PROPERTIES GENERATED 1) + +ADD_DEFINITIONS(-DHAVE_INNOBASE -DMYSQL_SERVER + -D_CONSOLE -DHAVE_DLOPEN) + +ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc + discover.cc ../libmysql/errmsg.c field.cc field_conv.cc + filesort.cc gstream.cc ha_blackhole.cc + ha_archive.cc ha_heap.cc ha_myisam.cc ha_myisammrg.cc + ha_innodb.cc ha_federated.cc ha_berkeley.cc ha_blackhole.cc + handler.cc hash_filo.cc hash_filo.h + hostname.cc init.cc item.cc item_buff.cc item_cmpfunc.cc + item_create.cc item_func.cc item_geofunc.cc item_row.cc + item_strfunc.cc item_subselect.cc item_sum.cc item_timefunc.cc + item_uniq.cc key.cc log.cc lock.cc log_event.cc message.rc + message.h mf_iocache.cc my_decimal.cc ../sql-common/my_time.c + ../myisammrg/myrg_rnext_same.c mysqld.cc net_serv.cc + nt_servc.cc nt_servc.h opt_range.cc opt_range.h opt_sum.cc + ../sql-common/pack.c parse_file.cc password.c procedure.cc + protocol.cc records.cc repl_failsafe.cc set_var.cc + slave.cc sp.cc sp_cache.cc sp_head.cc sp_pcontext.cc + sp_rcontext.cc spatial.cc sql_acl.cc sql_analyse.cc sql_base.cc + sql_cache.cc sql_class.cc sql_client.cc sql_crypt.cc sql_crypt.h + sql_cursor.cc sql_db.cc sql_delete.cc sql_derived.cc sql_do.cc + sql_error.cc sql_handler.cc sql_help.cc sql_insert.cc sql_lex.cc + sql_list.cc sql_load.cc sql_manager.cc sql_map.cc sql_parse.cc + sql_prepare.cc sql_rename.cc + sql_repl.cc sql_select.cc sql_show.cc sql_state.c sql_string.cc + sql_table.cc sql_test.cc sql_trigger.cc sql_udf.cc sql_union.cc + sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc + time.cc tztime.cc uniques.cc unireg.cc + ../sql-common/my_user.c + sql_locale.cc + ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc + ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h + ${PROJECT_SOURCE_DIR}/include/mysqld_error.h + ${PROJECT_SOURCE_DIR}/include/mysqld_ername.h + ${PROJECT_SOURCE_DIR}/include/sql_state.h + ${PROJECT_SOURCE_DIR}/include/mysql_version.h + ${PROJECT_SOURCE_DIR}/sql/lex_hash.h) + +TARGET_LINK_LIBRARIES(mysqld heap myisam myisammrg mysys yassl zlib dbug yassl + taocrypt strings vio regex wsock32) + +IF(WITH_EXAMPLE_STORAGE_ENGINE) + TARGET_LINK_LIBRARIES(mysqld example) +ENDIF(WITH_EXAMPLE_STORAGE_ENGINE) + +IF(WITH_INNOBASE_STORAGE_ENGINE) + TARGET_LINK_LIBRARIES(mysqld innobase) +ENDIF(WITH_INNOBASE_STORAGE_ENGINE) + +IF(WITH_BERKELEY_STORAGE_ENGINE) + TARGET_LINK_LIBRARIES(mysqld bdb) +ENDIF(WITH_BERKELEY_STORAGE_ENGINE) + + +ADD_DEPENDENCIES(mysqld GenError) + +# Sql Parser custom command +ADD_CUSTOM_COMMAND( + SOURCE ${PROJECT_SOURCE_DIR}/sql/sql_yacc.yy + OUTPUT ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc + COMMAND bison.exe ARGS -y -p MYSQL --defines=sql_yacc.h + --output=sql_yacc.cc sql_yacc.yy + DEPENDS ${PROJECT_SOURCE_DIR}/sql/sql_yacc.yy) + +ADD_CUSTOM_COMMAND( + OUTPUT ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h + COMMAND echo + DEPENDS ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc +) + +# Windows message file +ADD_CUSTOM_COMMAND( + SOURCE ${PROJECT_SOURCE_DIR}/sql/message.mc + OUTPUT message.rc message.h + COMMAND mc ARGS ${PROJECT_SOURCE_DIR}/sql/message.mc + DEPENDS ${PROJECT_SOURCE_DIR}/sql/message.mc) + +# Gen_lex_hash +ADD_EXECUTABLE(gen_lex_hash gen_lex_hash.cc) +TARGET_LINK_LIBRARIES(gen_lex_hash dbug mysqlclient wsock32) +GET_TARGET_PROPERTY(GEN_LEX_HASH_EXE gen_lex_hash LOCATION) +ADD_CUSTOM_COMMAND( + OUTPUT ${PROJECT_SOURCE_DIR}/sql/lex_hash.h + COMMAND ${GEN_LEX_HASH_EXE} ARGS > lex_hash.h + DEPENDS ${GEN_LEX_HASH_EXE} +) + +ADD_DEPENDENCIES(mysqld gen_lex_hash) diff --git a/sql/Makefile.am b/sql/Makefile.am index 8428d6401b5..98c8fe784eb 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -116,9 +116,11 @@ DEFS = -DMYSQL_SERVER \ @DEFS@ BUILT_SOURCES = sql_yacc.cc sql_yacc.h lex_hash.h -EXTRA_DIST = $(BUILT_SOURCES) -DISTCLEANFILES = lex_hash.h -AM_YFLAGS = -d +EXTRA_DIST = $(BUILT_SOURCES) nt_servc.cc nt_servc.h \ + message.mc examples/CMakeLists.txt CMakeLists.txt +DISTCLEANFILES = lex_hash.h sql_yacc.output + +AM_YFLAGS = -d --debug --verbose mysql_tzinfo_to_sql.cc: rm -f mysql_tzinfo_to_sql.cc diff --git a/sql/examples/CMakeLists.txt b/sql/examples/CMakeLists.txt new file mode 100755 index 00000000000..d3cc430ef40 --- /dev/null +++ b/sql/examples/CMakeLists.txt @@ -0,0 +1,11 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql + ${CMAKE_SOURCE_DIR}/extra/yassl/include + ${CMAKE_SOURCE_DIR}/regex) + +IF(WITH_EXAMPLE_STORAGE_ENGINE) +ADD_LIBRARY(example ha_example.cc) +ADD_DEPENDENCIES(example GenError) +ENDIF(WITH_EXAMPLE_STORAGE_ENGINE) diff --git a/sql/field.cc b/sql/field.cc index 4fea6a085bb..4860f6ea3da 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6154,15 +6154,26 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table, Field *new_field; if (type() != MYSQL_TYPE_VAR_STRING || keep_type) - return Field::new_field(root, new_table, keep_type); + new_field= Field::new_field(root, new_table, keep_type); + else + { - /* - Old VARCHAR field which should be modified to a VARCHAR on copy - This is done to ensure that ALTER TABLE will convert old VARCHAR fields - to now VARCHAR fields. - */ - return new Field_varstring(field_length, maybe_null(), - field_name, new_table, charset()); + /* + Old VARCHAR field which should be modified to a VARCHAR on copy + This is done to ensure that ALTER TABLE will convert old VARCHAR fields + to now VARCHAR fields. + */ + new_field= new Field_varstring(field_length, maybe_null(), + field_name, new_table, charset()); + /* + Normally orig_table is different from table only if field was created + via ::new_field. Here we alter the type of field, so ::new_field is + not applicable. But we still need to preserve the original field + metadata for the client-server protocol. + */ + new_field->orig_table= orig_table; + } + return new_field; } /**************************************************************************** diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 7e0b178f7af..5a8bd48d699 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -442,13 +442,17 @@ int main(int argc,char **argv) if (get_options(argc,(char **) argv)) exit(1); + /* Broken up to indicate that it's not advice to you, gentle reader. */ + printf("/*\n\n Do " "not " "edit " "this " "file " "directly!\n\n*/\n"); + printf("/* Copyright (C) 2001-2004 MySQL AB\n\ This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\ and you are welcome to modify and redistribute it under the GPL license\n\ \n*/\n\n"); - printf("/* This code is generated by gen_lex_hash.cc that seeks for\ - a perfect\nhash function */\n\n"); + /* Broken up to indicate that it's not advice to you, gentle reader. */ + printf("/* Do " "not " "edit " "this " "file! This is generated by " + "gen_lex_hash.cc\nthat seeks for a perfect hash function */\n\n"); printf("#include \"lex.h\"\n\n"); calc_length(); @@ -468,6 +472,14 @@ static inline SYMBOL *get_hash_symbol(const char *s,\n\ {\n\ register uchar *hash_map;\n\ register const char *cur_str= s;\n\ +\n\ + if (len == 0) {\n\ + DBUG_PRINT(\"warning\", (\"get_hash_symbol() received a request for a zero-length symbol, which is probably a mistake.\"));\ + return(NULL);\n\ + }\n" +); + + printf("\ if (function){\n\ if (len>sql_functions_max_len) return 0;\n\ hash_map= sql_functions_map;\n\ @@ -498,7 +510,10 @@ static inline SYMBOL *get_hash_symbol(const char *s,\n\ cur_struct= uint4korr(hash_map+\n\ (((uint16)cur_struct + cur_char - first_char)*4));\n\ cur_str++;\n\ - }\n\ + }\n" +); + + printf("\ }else{\n\ if (len>symbols_max_len) return 0;\n\ hash_map= symbols_map;\n\ diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc index 0fb0bc9f791..bb94a99e700 100644 --- a/sql/ha_archive.cc +++ b/sql/ha_archive.cc @@ -614,7 +614,7 @@ int ha_archive::create(const char *name, TABLE *table_arg, error= my_errno; goto error; } - if ((archive= gzdopen(create_file, "wb")) == NULL) + if ((archive= gzdopen(dup(create_file), "wb")) == NULL) { error= errno; goto error2; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 5d6fe5f984f..9c4a2c20ca0 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -35,6 +35,7 @@ // options from from mysqld.cc extern my_bool opt_ndb_optimized_node_selection; extern const char *opt_ndbcluster_connectstring; +extern ulong opt_ndb_cache_check_time; // Default value for parallelism static const int parallelism= 0; @@ -3525,7 +3526,14 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) if (lock_type != F_UNLCK) { DBUG_PRINT("info", ("lock_type != F_UNLCK")); - if (!thd->transaction.on) + if (thd->lex->sql_command == SQLCOM_LOAD) + { + m_transaction_on= FALSE; + /* Would be simpler if has_transactions() didn't always say "yes" */ + thd->options|= OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update= TRUE; + } + else if (!thd->transaction.on) m_transaction_on= FALSE; else m_transaction_on= thd->variables.ndb_use_transactions; @@ -4175,10 +4183,15 @@ static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length) acc_row_size+= 4 + /*safety margin*/ 4; #endif ulonglong acc_fragment_size= 512*1024*1024; + /* + * if not --with-big-tables then max_rows is ulong + * the warning in this case is misleading though + */ + ulonglong big_max_rows = (ulonglong)max_rows; #if MYSQL_VERSION_ID >= 50100 - no_fragments= (max_rows*acc_row_size)/acc_fragment_size+1; + no_fragments= (big_max_rows*acc_row_size)/acc_fragment_size+1; #else - no_fragments= ((max_rows*acc_row_size)/acc_fragment_size+1 + no_fragments= ((big_max_rows*acc_row_size)/acc_fragment_size+1 +1/*correct rounding*/)/2; #endif } @@ -5238,6 +5251,7 @@ bool ndbcluster_init() pthread_cond_init(&COND_ndb_util_thread, NULL); + ndb_cache_check_time = opt_ndb_cache_check_time; // Create utility thread pthread_t tmp; if (pthread_create(&tmp, &connection_attrib, ndb_util_thread_func, 0)) diff --git a/sql/item.cc b/sql/item.cc index 96b20d0f0bb..34e5e2da165 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -422,6 +422,49 @@ void Item::rename(char *new_name) } +/* + Traverse item tree possibly transforming it (replacing items). + + SYNOPSIS + Item::transform() + transformer functor that performs transformation of a subtree + arg opaque argument passed to the functor + + DESCRIPTION + This function is designed to ease transformation of Item trees. + + Re-execution note: every such transformation is registered for + rollback by THD::change_item_tree() and is rolled back at the end + of execution by THD::rollback_item_tree_changes(). + + Therefore: + + - this function can not be used at prepared statement prepare + (in particular, in fix_fields!), as only permanent + transformation of Item trees are allowed at prepare. + + - the transformer function shall allocate new Items in execution + memory root (thd->mem_root) and not anywhere else: allocated + items will be gone in the end of execution. + + If you don't need to transform an item tree, but only traverse + it, please use Item::walk() instead. + + + RETURN VALUE + Returns pointer to the new subtree root. THD::change_item_tree() + should be called for it if transformation took place, i.e. if a + pointer to newly allocated item is returned. +*/ + +Item* Item::transform(Item_transformer transformer, byte *arg) +{ + DBUG_ASSERT(!current_thd->is_stmt_prepare()); + + return (this->*transformer)(arg); +} + + Item_ident::Item_ident(Name_resolution_context *context_arg, const char *db_name_arg,const char *table_name_arg, const char *field_name_arg) @@ -3802,11 +3845,11 @@ Item *Item_field::equal_fields_propagator(byte *arg) See comments in Arg_comparator::set_compare_func() for details */ -Item *Item_field::set_no_const_sub(byte *arg) +bool Item_field::set_no_const_sub(byte *arg) { if (field->charset() != &my_charset_bin) no_const_subst=1; - return this; + return FALSE; } @@ -5308,6 +5351,31 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) } +/* + This method like the walk method traverses the item tree, but at the + same time it can replace some nodes in the tree +*/ + +Item *Item_default_value::transform(Item_transformer transformer, byte *args) +{ + DBUG_ASSERT(!current_thd->is_stmt_prepare()); + + Item *new_item= arg->transform(transformer, args); + if (!new_item) + return 0; + + /* + THD::change_item_tree() should be called only if the tree was + really transformed, i.e. when a new item has been created. + Otherwise we'll be allocating a lot of unnecessary memory for + change records at each execution. + */ + if (arg != new_item) + current_thd->change_item_tree(&arg, new_item); + return (this->*transformer)(args); +} + + bool Item_insert_value::eq(const Item *item, bool binary_cmp) const { return item->type() == INSERT_VALUE_ITEM && diff --git a/sql/item.h b/sql/item.h index e3df0fdf389..58a3bfd0d75 100644 --- a/sql/item.h +++ b/sql/item.h @@ -734,10 +734,7 @@ public: return (this->*processor)(arg); } - virtual Item* transform(Item_transformer transformer, byte *arg) - { - return (this->*transformer)(arg); - } + virtual Item* transform(Item_transformer transformer, byte *arg); virtual void traverse_cond(Cond_traverser traverser, void *arg, traverse_order order) @@ -755,7 +752,7 @@ public: virtual bool is_expensive_processor(byte *arg) { return 0; } virtual Item *equal_fields_propagator(byte * arg) { return this; } - virtual Item *set_no_const_sub(byte *arg) { return this; } + virtual bool set_no_const_sub(byte *arg) { return FALSE; } virtual Item *replace_equal_field(byte * arg) { return this; } /* @@ -1255,7 +1252,7 @@ public: } Item_equal *find_item_equal(COND_EQUAL *cond_equal); Item *equal_fields_propagator(byte *arg); - Item *set_no_const_sub(byte *arg); + bool set_no_const_sub(byte *arg); Item *replace_equal_field(byte *arg); inline uint32 max_disp_length() { return field->max_length(); } Item_field *filed_for_view_update() { return this; } @@ -2116,18 +2113,7 @@ public: (this->*processor)(args); } - /* - This method like the walk method traverses the item tree, but - at the same time it can replace some nodes in the tree - */ - Item *transform(Item_transformer transformer, byte *args) - { - Item *new_item= arg->transform(transformer, args); - if (!new_item) - return 0; - arg= new_item; - return (this->*transformer)(args); - } + Item *transform(Item_transformer transformer, byte *args); }; /* diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index dbf380232c4..919a23ed65d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -511,8 +511,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) which would be transformed to: WHERE col= 'j' */ - (*a)->transform(&Item::set_no_const_sub, (byte*) 0); - (*b)->transform(&Item::set_no_const_sub, (byte*) 0); + (*a)->walk(&Item::set_no_const_sub, (byte*) 0); + (*b)->walk(&Item::set_no_const_sub, (byte*) 0); } break; } @@ -2765,6 +2765,8 @@ bool Item_cond::walk(Item_processor processor, byte *arg) Item *Item_cond::transform(Item_transformer transformer, byte *arg) { + DBUG_ASSERT(!current_thd->is_stmt_prepare()); + List_iterator<Item> li(list); Item *item; while ((item= li++)) @@ -2772,8 +2774,15 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg) Item *new_item= item->transform(transformer, arg); if (!new_item) return 0; + + /* + THD::change_item_tree() should be called only if the tree was + really transformed, i.e. when a new item has been created. + Otherwise we'll be allocating a lot of unnecessary memory for + change records at each execution. + */ if (new_item != item) - li.replace(new_item); + current_thd->change_item_tree(li.ref(), new_item); } return Item_func::transform(transformer, arg); } @@ -4018,6 +4027,8 @@ bool Item_equal::walk(Item_processor processor, byte *arg) Item *Item_equal::transform(Item_transformer transformer, byte *arg) { + DBUG_ASSERT(!current_thd->is_stmt_prepare()); + List_iterator<Item_field> it(fields); Item *item; while ((item= it++)) @@ -4025,8 +4036,15 @@ Item *Item_equal::transform(Item_transformer transformer, byte *arg) Item *new_item= item->transform(transformer, arg); if (!new_item) return 0; + + /* + THD::change_item_tree() should be called only if the tree was + really transformed, i.e. when a new item has been created. + Otherwise we'll be allocating a lot of unnecessary memory for + change records at each execution. + */ if (new_item != item) - it.replace((Item_field *) new_item); + current_thd->change_item_tree((Item **) it.ref(), new_item); } return Item_func::transform(transformer, arg); } diff --git a/sql/item_func.cc b/sql/item_func.cc index e699669dcc5..579e7f88ee6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -258,6 +258,8 @@ void Item_func::traverse_cond(Cond_traverser traverser, Item *Item_func::transform(Item_transformer transformer, byte *argument) { + DBUG_ASSERT(!current_thd->is_stmt_prepare()); + if (arg_count) { Item **arg,**arg_end; @@ -266,6 +268,13 @@ Item *Item_func::transform(Item_transformer transformer, byte *argument) Item *new_item= (*arg)->transform(transformer, argument); if (!new_item) return 0; + + /* + THD::change_item_tree() should be called only if the tree was + really transformed, i.e. when a new item has been created. + Otherwise we'll be allocating a lot of unnecessary memory for + change records at each execution. + */ if (*arg != new_item) current_thd->change_item_tree(arg, new_item); } diff --git a/sql/item_row.cc b/sql/item_row.cc index f5c8d511025..d7591b9865d 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -154,12 +154,22 @@ bool Item_row::walk(Item_processor processor, byte *arg) Item *Item_row::transform(Item_transformer transformer, byte *arg) { + DBUG_ASSERT(!current_thd->is_stmt_prepare()); + for (uint i= 0; i < arg_count; i++) { Item *new_item= items[i]->transform(transformer, arg); if (!new_item) return 0; - items[i]= new_item; + + /* + THD::change_item_tree() should be called only if the tree was + really transformed, i.e. when a new item has been created. + Otherwise we'll be allocating a lot of unnecessary memory for + change records at each execution. + */ + if (items[i] != new_item) + current_thd->change_item_tree(&items[i], new_item); } return (this->*transformer)(arg); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 0cd0ffcc38b..2acd1371ce5 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -124,6 +124,7 @@ String *Item_func_md5::val_str(String *str) { DBUG_ASSERT(fixed == 1); String * sptr= args[0]->val_str(str); + str->set_charset(&my_charset_bin); if (sptr) { my_MD5_CTX context; @@ -170,6 +171,7 @@ String *Item_func_sha::val_str(String *str) { DBUG_ASSERT(fixed == 1); String * sptr= args[0]->val_str(str); + str->set_charset(&my_charset_bin); if (sptr) /* If we got value different from NULL */ { SHA1_CONTEXT context; /* Context used to generate SHA1 hash */ @@ -1605,7 +1607,7 @@ String *Item_func_encrypt::val_str(String *str) null_value= 1; return 0; } - str->set(tmp,(uint) strlen(tmp),res->charset()); + str->set(tmp, (uint) strlen(tmp), &my_charset_bin); str->copy(); pthread_mutex_unlock(&LOCK_crypt); return str; @@ -2041,7 +2043,7 @@ String *Item_func_make_set::val_str(String *str) return &my_empty_string; result= &tmp_str; } - if (tmp_str.append(',') || tmp_str.append(*res)) + if (tmp_str.append(STRING_WITH_LEN(","), &my_charset_bin) || tmp_str.append(*res)) return &my_empty_string; } } @@ -2051,6 +2053,26 @@ String *Item_func_make_set::val_str(String *str) } +Item *Item_func_make_set::transform(Item_transformer transformer, byte *arg) +{ + DBUG_ASSERT(!current_thd->is_stmt_prepare()); + + Item *new_item= item->transform(transformer, arg); + if (!new_item) + return 0; + + /* + THD::change_item_tree() should be called only if the tree was + really transformed, i.e. when a new item has been created. + Otherwise we'll be allocating a lot of unnecessary memory for + change records at each execution. + */ + if (item != new_item) + current_thd->change_item_tree(&item, new_item); + return Item_str_func::transform(transformer, arg); +} + + void Item_func_make_set::print(String *str) { str->append(STRING_WITH_LEN("make_set(")); @@ -2699,8 +2721,12 @@ String* Item_func_export_set::val_str(String* str) } break; case 3: - sep_buf.set(STRING_WITH_LEN(","), default_charset()); - sep = &sep_buf; + { + /* errors is not checked - assume "," can always be converted */ + uint errors; + sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin, collation.collation, &errors); + sep = &sep_buf; + } break; default: DBUG_ASSERT(0); // cannot happen diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index eae7272835d..528180b803d 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -43,7 +43,10 @@ class Item_func_md5 :public Item_str_func { String tmp_value; public: - Item_func_md5(Item *a) :Item_str_func(a) {} + Item_func_md5(Item *a) :Item_str_func(a) + { + collation.set(&my_charset_bin); + } String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "md5"; } @@ -53,7 +56,10 @@ public: class Item_func_sha :public Item_str_func { public: - Item_func_sha(Item *a) :Item_str_func(a) {} + Item_func_sha(Item *a) :Item_str_func(a) + { + collation.set(&my_charset_bin); + } String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "sha"; } @@ -325,9 +331,21 @@ public: class Item_func_encrypt :public Item_str_func { String tmp_value; + + /* Encapsulate common constructor actions */ + void constructor_helper() + { + collation.set(&my_charset_bin); + } public: - Item_func_encrypt(Item *a) :Item_str_func(a) {} - Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b) {} + Item_func_encrypt(Item *a) :Item_str_func(a) + { + constructor_helper(); + } + Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b) + { + constructor_helper(); + } String *val_str(String *); void fix_length_and_dec() { maybe_null=1; max_length = 13; } const char *func_name() const { return "encrypt"; } @@ -475,14 +493,7 @@ public: return item->walk(processor, arg) || Item_str_func::walk(processor, arg); } - Item *transform(Item_transformer transformer, byte *arg) - { - Item *new_item= item->transform(transformer, arg); - if (!new_item) - return 0; - item= new_item; - return Item_str_func::transform(transformer, arg); - } + Item *transform(Item_transformer transformer, byte *arg); void print(String *str); }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 0d2a5b3b080..bcd8270e52f 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -290,7 +290,9 @@ Item_sum::Item_sum(THD *thd, Item_sum *item): void Item_sum::mark_as_sum_func() { - current_thd->lex->current_select->with_sum_func= 1; + SELECT_LEX *cur_select= current_thd->lex->current_select; + cur_select->n_sum_items++; + cur_select->with_sum_func= 1; with_sum_func= 1; } diff --git a/sql/lock.cc b/sql/lock.cc index 97a080c5634..90ddcc957a2 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -854,6 +854,7 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) TABLE *table; char key[MAX_DBKEY_LENGTH]; char *db= table_list->db; + int table_in_key_offset; uint key_length; HASH_SEARCH_STATE state; DBUG_ENTER("lock_table_name"); @@ -861,8 +862,9 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) safe_mutex_assert_owner(&LOCK_open); - key_length=(uint) (strmov(strmov(key,db)+1,table_list->table_name) - -key)+ 1; + table_in_key_offset= strmov(key, db) - key + 1; + key_length= (uint)(strmov(key + table_in_key_offset, table_list->table_name) + - key) + 1; /* Only insert the table if we haven't insert it already */ @@ -883,6 +885,7 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) table->s= &table->share_not_to_be_used; memcpy((table->s->table_cache_key= (char*) (table+1)), key, key_length); table->s->db= table->s->table_cache_key; + table->s->table_name= table->s->table_cache_key + table_in_key_offset; table->s->key_length=key_length; table->in_use=thd; table->locked_by_name=1; diff --git a/sql/log.cc b/sql/log.cc index ebd1d10d8b7..1cd01865f9f 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -723,13 +723,18 @@ shutdown the MySQL server and restart it.", name, errno); int MYSQL_LOG::get_current_log(LOG_INFO* linfo) { pthread_mutex_lock(&LOCK_log); + int ret = raw_get_current_log(linfo); + pthread_mutex_unlock(&LOCK_log); + return ret; +} + +int MYSQL_LOG::raw_get_current_log(LOG_INFO* linfo) +{ strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1); linfo->pos = my_b_tell(&log_file); - pthread_mutex_unlock(&LOCK_log); return 0; } - /* Move all data up in a file in an filename index file @@ -2385,6 +2390,12 @@ void print_buffer_to_nt_eventlog(enum loglevel level, char *buff, void */ +#ifdef EMBEDDED_LIBRARY +void vprint_msg_to_log(enum loglevel level __attribute__((unused)), + const char *format __attribute__((unused)), + va_list argsi __attribute__((unused))) +{} +#else /*!EMBEDDED_LIBRARY*/ void vprint_msg_to_log(enum loglevel level, const char *format, va_list args) { char buff[1024]; @@ -2400,6 +2411,7 @@ void vprint_msg_to_log(enum loglevel level, const char *format, va_list args) DBUG_VOID_RETURN; } +#endif /*EMBEDDED_LIBRARY*/ void sql_print_error(const char *format, ...) diff --git a/sql/message.mc b/sql/message.mc new file mode 100644 index 00000000000..a1a7c8cff7e --- /dev/null +++ b/sql/message.mc @@ -0,0 +1,8 @@ +MessageId = 100 +Severity = Error +Facility = Application +SymbolicName = MSG_DEFAULT +Language = English +%1For more information, see Help and Support Center at http://www.mysql.com. + + diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3178569abc6..d73b1f1aac0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -566,6 +566,8 @@ void get_default_definer(THD *thd, LEX_USER *definer); LEX_USER *create_default_definer(THD *thd); LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name); LEX_USER *get_current_user(THD *thd, LEX_USER *user); +bool check_string_length(CHARSET_INFO *cs, LEX_STRING *str, + const char *err_msg, uint max_length); enum enum_mysql_completiontype { ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7, @@ -1511,6 +1513,9 @@ void free_list(I_List <i_string> *list); /* sql_yacc.cc */ extern int MYSQLparse(void *thd); +#ifndef DBUG_OFF +extern void turn_parser_debug_on(); +#endif /* frm_crypt.cc */ #ifdef HAVE_CRYPTED_FRM diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5ef98eded95..075a3851dbd 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2392,10 +2392,8 @@ static int my_message_sql(uint error, const char *str, myf MyFlags) if ((thd= current_thd)) { if (thd->spcont && - thd->spcont->find_handler(error, MYSQL_ERROR::WARN_LEVEL_ERROR)) + thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd)) { - if (! thd->spcont->found_handler_here()) - thd->net.report_error= 1; /* Make "select" abort correctly */ DBUG_RETURN(0); } @@ -7045,10 +7043,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } switch (method-1) { case 0: - method_conv= MI_STATS_METHOD_NULLS_EQUAL; + method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; break; case 1: - method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; + method_conv= MI_STATS_METHOD_NULLS_EQUAL; break; case 2: method_conv= MI_STATS_METHOD_IGNORE_NULLS; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index cf9dc6e3f60..1601f7e5177 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -96,8 +96,11 @@ extern uint test_flags; extern ulong bytes_sent, bytes_received, net_big_packet_count; extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received; #ifndef MYSQL_INSTANCE_MANAGER -extern void query_cache_insert(NET *net, const char *packet, ulong length); +#ifdef HAVE_QUERY_CACHE #define USE_QUERY_CACHE +extern void query_cache_init_query(NET *net); +extern void query_cache_insert(NET *net, const char *packet, ulong length); +#endif // HAVE_QUERY_CACHE #define update_statistics(A) A #endif /* MYSQL_INSTANCE_MANGER */ #endif /* defined(MYSQL_SERVER) && !defined(MYSQL_INSTANCE_MANAGER) */ @@ -133,7 +136,11 @@ my_bool my_net_init(NET *net, Vio* vio) net->compress=0; net->reading_or_writing=0; net->where_b = net->remain_in_buf=0; net->last_errno=0; - net->query_cache_query=0; +#ifdef USE_QUERY_CACHE + query_cache_init_query(net); +#else + net->query_cache_query= 0; +#endif net->report_error= 0; if (vio != 0) /* If real connection */ @@ -552,10 +559,8 @@ net_real_write(NET *net,const char *packet,ulong len) my_bool net_blocking = vio_is_blocking(net->vio); DBUG_ENTER("net_real_write"); -#if defined(MYSQL_SERVER) && defined(HAVE_QUERY_CACHE) \ - && !defined(MYSQL_INSTANCE_MANAGER) - if (net->query_cache_query != 0) - query_cache_insert(net, packet, len); +#if defined(MYSQL_SERVER) && defined(USE_QUERY_CACHE) + query_cache_insert(net, packet, len); #endif if (net->error == 2) @@ -855,7 +860,7 @@ my_real_read(NET *net, ulong *complen) #endif /* EXTRA_DEBUG */ } #if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) - if (vio_should_retry(net->vio)) + if (vio_errno(net->vio) == SOCKET_EINTR) { DBUG_PRINT("warning",("Interrupted read. Retrying...")); continue; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 71ba63dcf98..6189d0412b3 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -4129,6 +4129,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, MEM_ROOT *alloc= param->mem_root; char *str; ulong orig_sql_mode; + int err; DBUG_ENTER("get_mm_leaf"); /* @@ -4280,7 +4281,13 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, (field->type() == FIELD_TYPE_DATE || field->type() == FIELD_TYPE_DATETIME)) field->table->in_use->variables.sql_mode|= MODE_INVALID_DATES; - if (value->save_in_field_no_warnings(field, 1) < 0) + err= value->save_in_field_no_warnings(field, 1); + if (err > 0 && field->cmp_type() != value->result_type()) + { + tree= 0; + goto end; + } + if (err < 0) { field->table->in_use->variables.sql_mode= orig_sql_mode; /* This happens when we try to insert a NULL field in a not null column */ diff --git a/sql/protocol.cc b/sql/protocol.cc index f4efb8004ee..5de24ebdcb3 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -53,8 +53,18 @@ bool Protocol_prep::net_store_data(const char *from, uint length) } - /* Send a error string to client */ +/* + Send a error string to client + + Design note: + net_printf_error and net_send_error are low-level functions + that shall be used only when a new connection is being + established or at server startup. + For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's + critical that every error that can be intercepted is issued in one + place only, my_message_sql. +*/ void net_send_error(THD *thd, uint sql_errno, const char *err) { NET *net= &thd->net; @@ -64,19 +74,15 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) err ? err : net->last_error[0] ? net->last_error : "NULL")); + DBUG_ASSERT(!thd->spcont); + if (net && net->no_send_error) { thd->clear_error(); DBUG_PRINT("info", ("sending error messages prohibited")); DBUG_VOID_RETURN; } - if (thd->spcont && thd->spcont->find_handler(sql_errno, - MYSQL_ERROR::WARN_LEVEL_ERROR)) - { - if (! thd->spcont->found_handler_here()) - thd->net.report_error= 1; /* Make "select" abort correctly */ - DBUG_VOID_RETURN; - } + thd->query_error= 1; // needed to catch query errors during replication if (!err) { @@ -117,6 +123,15 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) Write error package and flush to client It's a little too low level, but I don't want to use another buffer for this + + Design note: + + net_printf_error and net_send_error are low-level functions + that shall be used only when a new connection is being + established or at server startup. + For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's + critical that every error that can be intercepted is issued in one + place only, my_message_sql. */ void @@ -136,6 +151,8 @@ net_printf_error(THD *thd, uint errcode, ...) DBUG_ENTER("net_printf_error"); DBUG_PRINT("enter",("message: %u",errcode)); + DBUG_ASSERT(!thd->spcont); + if (net && net->no_send_error) { thd->clear_error(); @@ -143,13 +160,6 @@ net_printf_error(THD *thd, uint errcode, ...) DBUG_VOID_RETURN; } - if (thd->spcont && thd->spcont->find_handler(errcode, - MYSQL_ERROR::WARN_LEVEL_ERROR)) - { - if (! thd->spcont->found_handler_here()) - thd->net.report_error= 1; /* Make "select" abort correctly */ - DBUG_VOID_RETURN; - } thd->query_error= 1; // needed to catch query errors during replication #ifndef EMBEDDED_LIBRARY query_cache_abort(net); // Safety diff --git a/sql/set_var.cc b/sql/set_var.cc index b61f6d58347..c667e2f2bcc 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -870,8 +870,8 @@ struct show_var_st init_vars[]= { {"have_geometry", (char*) &have_geometry, SHOW_HAVE}, {"have_innodb", (char*) &have_innodb, SHOW_HAVE}, {"have_isam", (char*) &have_isam, SHOW_HAVE}, - {"have_ndbcluster", (char*) &have_ndbcluster, SHOW_HAVE}, {"have_merge_engine", (char*) &have_merge_db, SHOW_HAVE}, + {"have_ndbcluster", (char*) &have_ndbcluster, SHOW_HAVE}, {"have_openssl", (char*) &have_openssl, SHOW_HAVE}, {"have_query_cache", (char*) &have_query_cache, SHOW_HAVE}, {"have_raid", (char*) &have_raid, SHOW_HAVE}, diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index e90f54608e1..d10f66e3878 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5623,3 +5623,9 @@ ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA eng "Triggers can not be created on system tables" ER_REMOVED_SPACES eng "Leading spaces are removed from name '%s'" +ER_USERNAME + eng "user name" +ER_HOSTNAME + eng "host name" +ER_WRONG_STRING_LENGTH + eng "String '%-.70s' is too long for %s (should be no longer than %d)" diff --git a/sql/slave.h b/sql/slave.h index c355f7172a9..dee134aaa0c 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -406,7 +406,7 @@ typedef struct st_master_info /* the variables below are needed because we can change masters on the fly */ char master_log_name[FN_REFLEN]; char host[HOSTNAME_LENGTH+1]; - char user[USERNAME_LENGTH+1]; + char user[USERNAME_BYTE_LENGTH+1]; char password[MAX_PASSWORD_LENGTH+1]; my_bool ssl; // enables use of SSL connection if true char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN]; diff --git a/sql/sp.cc b/sql/sp.cc index b7bf049cb1d..63175b110fa 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -404,16 +404,16 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, { LEX *old_lex= thd->lex, newlex; String defstr; - char old_db_buf[NAME_LEN+1]; + char old_db_buf[NAME_BYTE_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; ulong old_sql_mode= thd->variables.sql_mode; ha_rows old_select_limit= thd->variables.select_limit; sp_rcontext *old_spcont= thd->spcont; - char definer_user_name_holder[USERNAME_LENGTH + 1]; + char definer_user_name_holder[USERNAME_BYTE_LENGTH + 1]; LEX_STRING_WITH_INIT definer_user_name(definer_user_name_holder, - USERNAME_LENGTH); + USERNAME_BYTE_LENGTH); char definer_host_name_holder[HOSTNAME_LENGTH + 1]; LEX_STRING_WITH_INIT definer_host_name(definer_host_name_holder, @@ -511,7 +511,7 @@ db_create_routine(THD *thd, int type, sp_head *sp) int ret; TABLE *table; char definer[USER_HOST_BUFF_SIZE]; - char old_db_buf[NAME_LEN+1]; + char old_db_buf[NAME_BYTE_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; DBUG_ENTER("db_create_routine"); @@ -1006,6 +1006,12 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, } DBUG_RETURN(sp->m_first_free_instance); } + /* + Actually depth could be +1 than the actual value in case a SP calls + SHOW CREATE PROCEDURE. Hence, the linked list could hold up to one more + instance. + */ + level= sp->m_last_cached_sp->m_recursion_level + 1; if (level > depth) { @@ -1175,19 +1181,22 @@ sp_update_procedure(THD *thd, sp_name *name, st_sp_chistics *chistics) int sp_show_create_procedure(THD *thd, sp_name *name) { + int ret= SP_KEY_NOT_FOUND; sp_head *sp; DBUG_ENTER("sp_show_create_procedure"); DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str)); + /* + Increase the recursion limit for this statement. SHOW CREATE PROCEDURE + does not do actual recursion. + */ + thd->variables.max_sp_recursion_depth++; if ((sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name, &thd->sp_proc_cache, FALSE))) - { - int ret= sp->show_create_procedure(thd); + ret= sp->show_create_procedure(thd); - DBUG_RETURN(ret); - } - - DBUG_RETURN(SP_KEY_NOT_FOUND); + thd->variables.max_sp_recursion_depth--; + DBUG_RETURN(ret); } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index eec6e0fc3cd..e5b0b1e606e 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -230,6 +230,12 @@ sp_get_flags_for_command(LEX *lex) else flags= sp_head::HAS_COMMIT_OR_ROLLBACK; break; + case SQLCOM_FLUSH: + flags= sp_head::HAS_SQLCOM_FLUSH; + break; + case SQLCOM_RESET: + flags= sp_head::HAS_SQLCOM_RESET; + break; case SQLCOM_CREATE_INDEX: case SQLCOM_CREATE_DB: case SQLCOM_CREATE_VIEW: @@ -918,7 +924,7 @@ bool sp_head::execute(THD *thd) { DBUG_ENTER("sp_head::execute"); - char old_db_buf[NAME_LEN+1]; + char old_db_buf[NAME_BYTE_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; sp_rcontext *ctx; @@ -1951,8 +1957,8 @@ sp_head::set_info(longlong created, longlong modified, void sp_head::set_definer(const char *definer, uint definerlen) { - char user_name_holder[USERNAME_LENGTH + 1]; - LEX_STRING_WITH_INIT user_name(user_name_holder, USERNAME_LENGTH); + char user_name_holder[USERNAME_BYTE_LENGTH + 1]; + LEX_STRING_WITH_INIT user_name(user_name_holder, USERNAME_BYTE_LENGTH); char host_name_holder[HOSTNAME_LENGTH + 1]; LEX_STRING_WITH_INIT host_name(host_name_holder, HOSTNAME_LENGTH); diff --git a/sql/sp_head.h b/sql/sp_head.h index 4cd34bc9e20..7f2da69aa0c 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -115,7 +115,9 @@ public: IS_INVOKED= 32, // Is set if this sp_head is being used HAS_SET_AUTOCOMMIT_STMT= 64,// Is set if a procedure with 'set autocommit' /* Is set if a procedure with COMMIT (implicit or explicit) | ROLLBACK */ - HAS_COMMIT_OR_ROLLBACK= 128 + HAS_COMMIT_OR_ROLLBACK= 128, + HAS_SQLCOM_RESET= 2048, + HAS_SQLCOM_FLUSH= 4096 }; /* TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */ @@ -335,14 +337,16 @@ public: my_error(ER_SP_NO_RETSET, MYF(0), where); else if (m_flags & HAS_SET_AUTOCOMMIT_STMT) my_error(ER_SP_CANT_SET_AUTOCOMMIT, MYF(0)); - else if (m_type != TYPE_ENUM_PROCEDURE && - (m_flags & sp_head::HAS_COMMIT_OR_ROLLBACK)) - { + else if (m_flags & HAS_COMMIT_OR_ROLLBACK) my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - return TRUE; - } + else if (m_flags & HAS_SQLCOM_RESET) + my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "RESET"); + else if (m_flags & HAS_SQLCOM_FLUSH) + my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "FLUSH"); + return test(m_flags & - (CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT)); + (CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT| + HAS_COMMIT_OR_ROLLBACK|HAS_SQLCOM_RESET|HAS_SQLCOM_FLUSH)); } #ifndef DBUG_OFF diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 3bc27a029d0..67ee5459bb4 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -260,6 +260,65 @@ sp_rcontext::find_handler(uint sql_errno, return TRUE; } +/* + Handle the error for a given errno. + The severity of the error is adjusted depending of the current sql_mode. + If an handler is present for the error (see find_handler()), + this function will return true. + If a handler is found and if the severity of the error indicate + that the current instruction executed should abort, + the flag thd->net.report_error is also set. + This will cause the execution of the current instruction in a + sp_instr* to fail, and give control to the handler code itself + in the sp_head::execute() loop. + + SYNOPSIS + sql_errno The error code + level Warning level + thd The current thread + - thd->net.report_error is an optional output. + + RETURN + TRUE if a handler was found. + FALSE if no handler was found. +*/ +bool +sp_rcontext::handle_error(uint sql_errno, + MYSQL_ERROR::enum_warning_level level, + THD *thd) +{ + bool handled= FALSE; + MYSQL_ERROR::enum_warning_level elevated_level= level; + + + /* Depending on the sql_mode of execution, + warnings may be considered errors */ + if ((level == MYSQL_ERROR::WARN_LEVEL_WARN) && + thd->really_abort_on_warning()) + { + elevated_level= MYSQL_ERROR::WARN_LEVEL_ERROR; + } + + if (find_handler(sql_errno, elevated_level)) + { + if (elevated_level == MYSQL_ERROR::WARN_LEVEL_ERROR) + { + /* + Forces to abort the current instruction execution. + NOTE: This code is altering the original meaning of + the net.report_error flag (send an error to the client). + In the context of stored procedures with error handlers, + the flag is reused to cause error propagation, + until the error handler is reached. + No messages will be sent to the client in that context. + */ + thd->net.report_error= 1; + } + handled= TRUE; + } + + return handled; +} void sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i) diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index 30521f6da84..5e03aa60d23 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -128,6 +128,12 @@ class sp_rcontext : public Sql_alloc bool find_handler(uint sql_errno,MYSQL_ERROR::enum_warning_level level); + // If there is an error handler for this error, handle it and return TRUE. + bool + handle_error(uint sql_errno, + MYSQL_ERROR::enum_warning_level level, + THD *thd); + // Returns handler type and sets *ip to location if one was found inline int found_handler(uint *ip, uint *fp) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index b8be4f47d82..010a5c33b96 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -54,7 +54,7 @@ static byte* acl_entry_get_key(acl_entry *entry,uint *length, } #define IP_ADDR_STRLEN (3+1+3+1+3+1+3) -#define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_LEN+1+USERNAME_LENGTH+1) +#define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_BYTE_LEN+1+USERNAME_BYTE_LENGTH+1) static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs; static MEM_ROOT mem, memex; @@ -197,7 +197,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) READ_RECORD read_record_info; my_bool return_val= 1; bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; - char tmp_name[NAME_LEN+1]; + char tmp_name[NAME_BYTE_LEN+1]; int password_length; DBUG_ENTER("acl_load"); @@ -2264,7 +2264,7 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, const char *user, const char *tname, bool exact) { - char helping [NAME_LEN*2+USERNAME_LENGTH+3]; + char helping [NAME_BYTE_LEN*2+USERNAME_BYTE_LENGTH+3]; uint len; GRANT_NAME *grant_name,*found=0; HASH_SEARCH_STATE state; @@ -2903,14 +2903,6 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, result= TRUE; continue; } - if (Str->host.length > HOSTNAME_LENGTH || - Str->user.length > USERNAME_LENGTH) - { - my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER), - MYF(0)); - result= TRUE; - continue; - } /* Create user if needed */ error=replace_user_table(thd, tables[0].table, *Str, 0, revoke_grant, create_new_users, @@ -3115,15 +3107,6 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, result= TRUE; continue; } - if (Str->host.length > HOSTNAME_LENGTH || - Str->user.length > USERNAME_LENGTH) - { - if (!no_error) - my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER), - MYF(0)); - result= TRUE; - continue; - } /* Create user if needed */ error=replace_user_table(thd, tables[0].table, *Str, 0, revoke_grant, create_new_users, @@ -3184,7 +3167,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, { List_iterator <LEX_USER> str_list (list); LEX_USER *Str, *tmp_Str; - char tmp_db[NAME_LEN+1]; + char tmp_db[NAME_BYTE_LEN+1]; bool create_new_users=0; TABLE_LIST tables[2]; DBUG_ENTER("mysql_grant"); @@ -3249,14 +3232,6 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, result= TRUE; continue; } - if (Str->host.length > HOSTNAME_LENGTH || - Str->user.length > USERNAME_LENGTH) - { - my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER), - MYF(0)); - result= -1; - continue; - } if (replace_user_table(thd, tables[0].table, *Str, (!db ? rights : 0), revoke_grant, create_new_users, test(thd->variables.sql_mode & @@ -3892,7 +3867,7 @@ err2: bool check_grant_db(THD *thd,const char *db) { Security_context *sctx= thd->security_ctx; - char helping [NAME_LEN+USERNAME_LENGTH+2]; + char helping [NAME_BYTE_LEN+USERNAME_BYTE_LENGTH+2]; uint len; bool error= 1; @@ -4162,14 +4137,6 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) DBUG_RETURN(TRUE); } - if (lex_user->host.length > HOSTNAME_LENGTH || - lex_user->user.length > USERNAME_LENGTH) - { - my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER), - MYF(0)); - DBUG_RETURN(TRUE); - } - rw_rdlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); @@ -5265,14 +5232,6 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) continue; } - if (user_name->host.length > HOSTNAME_LENGTH || - user_name->user.length > USERNAME_LENGTH) - { - append_user(&wrong_users, user_name); - result= TRUE; - continue; - } - /* Search all in-memory structures and grant tables for a mention of the new user name. @@ -5465,8 +5424,6 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) } if (!find_acl_user(lex_user->host.str, lex_user->user.str, TRUE)) { - sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not " - "exists", lex_user->user.str, lex_user->host.str); result= -1; continue; } diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index f8f7bde3a62..ff033b69f98 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -565,21 +565,62 @@ byte *query_cache_query_get_key(const byte *record, uint *length, *****************************************************************************/ /* + Note on double-check locking (DCL) usage. + + Below, in query_cache_insert(), query_cache_abort() and + query_cache_end_of_result() we use what is called double-check + locking (DCL) for NET::query_cache_query. I.e. we test it first + without a lock, and, if positive, test again under the lock. + + This means that if we see 'NET::query_cache_query == 0' without a + lock we will skip the operation. But this is safe here: when we + started to cache a query, we called Query_cache::store_query(), and + NET::query_cache_query was set to non-zero in this thread (and the + thread always sees results of its memory operations, mutex or not). + If later we see 'NET::query_cache_query == 0' without locking a + mutex, that may only mean that some other thread have reset it by + invalidating the query. Skipping the operation in this case is the + right thing to do, as NET::query_cache_query won't get non-zero for + this query again. + + See also comments in Query_cache::store_query() and + Query_cache::send_result_to_client(). + + NOTE, however, that double-check locking is not applicable in + 'invalidate' functions, as we may erroneously skip invalidation, + because the thread doing invalidation may never see non-zero + NET::query_cache_query. +*/ + + +void query_cache_init_query(NET *net) +{ + /* + It is safe to initialize 'NET::query_cache_query' without a lock + here, because before it will be accessed from different threads it + will be set in this thread under a lock, and access from the same + thread is always safe. + */ + net->query_cache_query= 0; +} + + +/* Insert the packet into the query cache. - This should only be called if net->query_cache_query != 0 */ void query_cache_insert(NET *net, const char *packet, ulong length) { DBUG_ENTER("query_cache_insert"); + /* See the comment on double-check locking usage above. */ + if (net->query_cache_query == 0) + DBUG_VOID_RETURN; + STRUCT_LOCK(&query_cache.structure_guard_mutex); - /* - It is very unlikely that following condition is TRUE (it is possible - only if other thread is resizing cache), so we check it only after guard - mutex lock - */ - if (unlikely(query_cache.query_cache_size == 0)) + + if (unlikely(query_cache.query_cache_size == 0 || + query_cache.flush_in_progress)) { STRUCT_UNLOCK(&query_cache.structure_guard_mutex); DBUG_VOID_RETURN; @@ -616,10 +657,10 @@ void query_cache_insert(NET *net, const char *packet, ulong length) header->result(result); header->last_pkt_nr= net->pkt_nr; BLOCK_UNLOCK_WR(query_block); + DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0);); } else STRUCT_UNLOCK(&query_cache.structure_guard_mutex); - DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0);); DBUG_VOID_RETURN; } @@ -628,33 +669,33 @@ void query_cache_abort(NET *net) { DBUG_ENTER("query_cache_abort"); - if (net->query_cache_query != 0) // Quick check on unlocked structure + /* See the comment on double-check locking usage above. */ + if (net->query_cache_query == 0) + DBUG_VOID_RETURN; + + STRUCT_LOCK(&query_cache.structure_guard_mutex); + + if (unlikely(query_cache.query_cache_size == 0 || + query_cache.flush_in_progress)) { - STRUCT_LOCK(&query_cache.structure_guard_mutex); - /* - It is very unlikely that following condition is TRUE (it is possible - only if other thread is resizing cache), so we check it only after guard - mutex lock - */ - if (unlikely(query_cache.query_cache_size == 0)) - { - STRUCT_UNLOCK(&query_cache.structure_guard_mutex); - DBUG_VOID_RETURN; - } + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); + DBUG_VOID_RETURN; + } - Query_cache_block *query_block = ((Query_cache_block*) - net->query_cache_query); - if (query_block) // Test if changed by other thread - { - DUMP(&query_cache); - BLOCK_LOCK_WR(query_block); - // The following call will remove the lock on query_block - query_cache.free_query(query_block); - } - net->query_cache_query=0; + Query_cache_block *query_block= ((Query_cache_block*) + net->query_cache_query); + if (query_block) // Test if changed by other thread + { + DUMP(&query_cache); + BLOCK_LOCK_WR(query_block); + // The following call will remove the lock on query_block + query_cache.free_query(query_block); + net->query_cache_query= 0; DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1);); - STRUCT_UNLOCK(&query_cache.structure_guard_mutex); } + + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); + DBUG_VOID_RETURN; } @@ -663,60 +704,65 @@ void query_cache_end_of_result(THD *thd) { DBUG_ENTER("query_cache_end_of_result"); - if (thd->net.query_cache_query != 0) // Quick check on unlocked structure - { + /* See the comment on double-check locking usage above. */ + if (thd->net.query_cache_query == 0) + DBUG_VOID_RETURN; + #ifdef EMBEDDED_LIBRARY - query_cache_insert(&thd->net, (char*)thd, - emb_count_querycache_size(thd)); + query_cache_insert(&thd->net, (char*)thd, + emb_count_querycache_size(thd)); #endif - STRUCT_LOCK(&query_cache.structure_guard_mutex); - /* - It is very unlikely that following condition is TRUE (it is possible - only if other thread is resizing cache), so we check it only after guard - mutex lock - */ - if (unlikely(query_cache.query_cache_size == 0)) - { - STRUCT_UNLOCK(&query_cache.structure_guard_mutex); - DBUG_VOID_RETURN; - } - Query_cache_block *query_block = ((Query_cache_block*) - thd->net.query_cache_query); - if (query_block) - { - DUMP(&query_cache); - BLOCK_LOCK_WR(query_block); - Query_cache_query *header = query_block->query(); - Query_cache_block *last_result_block = header->result()->prev; - ulong allign_size = ALIGN_SIZE(last_result_block->used); - ulong len = max(query_cache.min_allocation_unit, allign_size); - if (last_result_block->length >= query_cache.min_allocation_unit + len) - query_cache.split_block(last_result_block,len); - STRUCT_UNLOCK(&query_cache.structure_guard_mutex); + STRUCT_LOCK(&query_cache.structure_guard_mutex); + + if (unlikely(query_cache.query_cache_size == 0 || + query_cache.flush_in_progress)) + { + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); + DBUG_VOID_RETURN; + } + + Query_cache_block *query_block= ((Query_cache_block*) + thd->net.query_cache_query); + if (query_block) + { + DUMP(&query_cache); + BLOCK_LOCK_WR(query_block); + Query_cache_query *header= query_block->query(); + Query_cache_block *last_result_block= header->result()->prev; + ulong allign_size= ALIGN_SIZE(last_result_block->used); + ulong len= max(query_cache.min_allocation_unit, allign_size); + if (last_result_block->length >= query_cache.min_allocation_unit + len) + query_cache.split_block(last_result_block,len); #ifndef DBUG_OFF - if (header->result() == 0) - { - DBUG_PRINT("error", ("end of data whith no result. query '%s'", - header->query())); - query_cache.wreck(__LINE__, ""); - DBUG_VOID_RETURN; - } -#endif - header->found_rows(current_thd->limit_found_rows); - header->result()->type = Query_cache_block::RESULT; - header->writer(0); - BLOCK_UNLOCK_WR(query_block); - } - else + if (header->result() == 0) { - // Cache was flushed or resized and query was deleted => do nothing + DBUG_PRINT("error", ("end of data whith no result. query '%s'", + header->query())); + query_cache.wreck(__LINE__, ""); + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); + + DBUG_VOID_RETURN; } - thd->net.query_cache_query=0; - DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0);); +#endif + header->found_rows(current_thd->limit_found_rows); + header->result()->type= Query_cache_block::RESULT; + header->writer(0); + thd->net.query_cache_query= 0; + DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1);); + + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); + + BLOCK_UNLOCK_WR(query_block); + } + else + { + // Cache was flushed or resized and query was deleted => do nothing + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); } + DBUG_VOID_RETURN; } @@ -762,8 +808,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg) query_cache_size_arg)); DBUG_ASSERT(initialized); STRUCT_LOCK(&structure_guard_mutex); - if (query_cache_size > 0) - free_cache(); + free_cache(); query_cache_size= query_cache_size_arg; ::query_cache_size= init_cache(); STRUCT_UNLOCK(&structure_guard_mutex); @@ -784,7 +829,15 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) TABLE_COUNTER_TYPE local_tables; ulong tot_length; DBUG_ENTER("Query_cache::store_query"); - if (query_cache_size == 0 || thd->locked_tables) + /* + Testing 'query_cache_size' without a lock here is safe: the thing + we may loose is that the query won't be cached, but we save on + mutex locking in the case when query cache is disabled or the + query is uncachable. + + See also a note on double-check locking usage above. + */ + if (thd->locked_tables || query_cache_size == 0) DBUG_VOID_RETURN; uint8 tables_type= 0; @@ -836,9 +889,9 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu", acquiring the query cache mutex. */ ha_release_temporary_latches(thd); - STRUCT_LOCK(&structure_guard_mutex); - if (query_cache_size == 0) + STRUCT_LOCK(&structure_guard_mutex); + if (query_cache_size == 0 || flush_in_progress) { STRUCT_UNLOCK(&structure_guard_mutex); DBUG_VOID_RETURN; @@ -912,11 +965,12 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu", double_linked_list_simple_include(query_block, &queries_blocks); inserts++; queries_in_cache++; - STRUCT_UNLOCK(&structure_guard_mutex); - net->query_cache_query= (gptr) query_block; header->writer(net); header->tables_type(tables_type); + + STRUCT_UNLOCK(&structure_guard_mutex); + // init_n_lock make query block locked BLOCK_UNLOCK_WR(query_block); } @@ -970,12 +1024,16 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) Query_cache_query_flags flags; DBUG_ENTER("Query_cache::send_result_to_client"); - if (query_cache_size == 0 || thd->locked_tables || - thd->variables.query_cache_type == 0) - goto err; + /* + Testing 'query_cache_size' without a lock here is safe: the thing + we may loose is that the query won't be served from cache, but we + save on mutex locking in the case when query cache is disabled. - /* Check that we haven't forgot to reset the query cache variables */ - DBUG_ASSERT(thd->net.query_cache_query == 0); + See also a note on double-check locking usage above. + */ + if (thd->locked_tables || thd->variables.query_cache_type == 0 || + query_cache_size == 0) + goto err; if (!thd->lex->safe_to_cache_query) { @@ -1011,11 +1069,15 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) } STRUCT_LOCK(&structure_guard_mutex); - if (query_cache_size == 0) + if (query_cache_size == 0 || flush_in_progress) { DBUG_PRINT("qcache", ("query cache disabled")); goto err_unlock; } + + /* Check that we haven't forgot to reset the query cache variables */ + DBUG_ASSERT(thd->net.query_cache_query == 0); + Query_cache_block *query_block; tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE; @@ -1241,45 +1303,43 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used, my_bool using_transactions) { DBUG_ENTER("Query_cache::invalidate (table list)"); - if (query_cache_size > 0) + STRUCT_LOCK(&structure_guard_mutex); + if (query_cache_size > 0 && !flush_in_progress) { - STRUCT_LOCK(&structure_guard_mutex); - if (query_cache_size > 0) - { - DUMP(this); + DUMP(this); - using_transactions = using_transactions && - (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); - for (; tables_used; tables_used= tables_used->next_local) - { - DBUG_ASSERT(!using_transactions || tables_used->table!=0); - if (tables_used->derived) - continue; - if (using_transactions && - (tables_used->table->file->table_cache_type() == - HA_CACHE_TBL_TRANSACT)) - /* - Tables_used->table can't be 0 in transaction. - Only 'drop' invalidate not opened table, but 'drop' - force transaction finish. - */ - thd->add_changed_table(tables_used->table); - else - invalidate_table(tables_used); - } + using_transactions= using_transactions && + (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); + for (; tables_used; tables_used= tables_used->next_local) + { + DBUG_ASSERT(!using_transactions || tables_used->table!=0); + if (tables_used->derived) + continue; + if (using_transactions && + (tables_used->table->file->table_cache_type() == + HA_CACHE_TBL_TRANSACT)) + /* + Tables_used->table can't be 0 in transaction. + Only 'drop' invalidate not opened table, but 'drop' + force transaction finish. + */ + thd->add_changed_table(tables_used->table); + else + invalidate_table(tables_used); } - STRUCT_UNLOCK(&structure_guard_mutex); } + STRUCT_UNLOCK(&structure_guard_mutex); + DBUG_VOID_RETURN; } void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) { DBUG_ENTER("Query_cache::invalidate (changed table list)"); - if (query_cache_size > 0 && tables_used) + if (tables_used) { STRUCT_LOCK(&structure_guard_mutex); - if (query_cache_size > 0) + if (query_cache_size > 0 && !flush_in_progress) { DUMP(this); for (; tables_used; tables_used= tables_used->next) @@ -1309,10 +1369,10 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used) { DBUG_ENTER("Query_cache::invalidate_locked_for_write"); - if (query_cache_size > 0 && tables_used) + if (tables_used) { STRUCT_LOCK(&structure_guard_mutex); - if (query_cache_size > 0) + if (query_cache_size > 0 && !flush_in_progress) { DUMP(this); for (; tables_used; tables_used= tables_used->next_local) @@ -1336,21 +1396,19 @@ void Query_cache::invalidate(THD *thd, TABLE *table, { DBUG_ENTER("Query_cache::invalidate (table)"); - if (query_cache_size > 0) + STRUCT_LOCK(&structure_guard_mutex); + if (query_cache_size > 0 && !flush_in_progress) { - STRUCT_LOCK(&structure_guard_mutex); - if (query_cache_size > 0) - { - using_transactions = using_transactions && - (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); - if (using_transactions && - (table->file->table_cache_type() == HA_CACHE_TBL_TRANSACT)) - thd->add_changed_table(table); - else - invalidate_table(table); - } - STRUCT_UNLOCK(&structure_guard_mutex); + using_transactions= using_transactions && + (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); + if (using_transactions && + (table->file->table_cache_type() == HA_CACHE_TBL_TRANSACT)) + thd->add_changed_table(table); + else + invalidate_table(table); } + STRUCT_UNLOCK(&structure_guard_mutex); + DBUG_VOID_RETURN; } @@ -1359,20 +1417,18 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length, { DBUG_ENTER("Query_cache::invalidate (key)"); - if (query_cache_size > 0) + STRUCT_LOCK(&structure_guard_mutex); + if (query_cache_size > 0 && !flush_in_progress) { - using_transactions = using_transactions && + using_transactions= using_transactions && (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); if (using_transactions) // used for innodb => has_transactions() is TRUE thd->add_changed_table(key, key_length); else - { - STRUCT_LOCK(&structure_guard_mutex); - if (query_cache_size > 0) - invalidate_table((byte*)key, key_length); - STRUCT_UNLOCK(&structure_guard_mutex); - } + invalidate_table((byte*)key, key_length); } + STRUCT_UNLOCK(&structure_guard_mutex); + DBUG_VOID_RETURN; } @@ -1383,38 +1439,36 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length, void Query_cache::invalidate(char *db) { DBUG_ENTER("Query_cache::invalidate (db)"); - if (query_cache_size > 0) + STRUCT_LOCK(&structure_guard_mutex); + if (query_cache_size > 0 && !flush_in_progress) { - STRUCT_LOCK(&structure_guard_mutex); - if (query_cache_size > 0) - { - DUMP(this); + DUMP(this); restart_search: - if (tables_blocks) + if (tables_blocks) + { + Query_cache_block *curr= tables_blocks; + Query_cache_block *next; + do { - Query_cache_block *curr= tables_blocks; - Query_cache_block *next; - do - { - next= curr->next; - if (strcmp(db, (char*)(curr->table()->db())) == 0) - invalidate_table(curr); - /* - invalidate_table can freed block on which point 'next' (if - table of this block used only in queries which was deleted - by invalidate_table). As far as we do not allocate new blocks - and mark all headers of freed blocks as 'FREE' (even if they are - merged with other blocks) we can just test type of block - to be sure that block is not deleted - */ - if (next->type == Query_cache_block::FREE) - goto restart_search; - curr= next; - } while (curr != tables_blocks); - } + next= curr->next; + if (strcmp(db, (char*)(curr->table()->db())) == 0) + invalidate_table(curr); + /* + invalidate_table can freed block on which point 'next' (if + table of this block used only in queries which was deleted + by invalidate_table). As far as we do not allocate new blocks + and mark all headers of freed blocks as 'FREE' (even if they are + merged with other blocks) we can just test type of block + to be sure that block is not deleted + */ + if (next->type == Query_cache_block::FREE) + goto restart_search; + curr= next; + } while (curr != tables_blocks); } - STRUCT_UNLOCK(&structure_guard_mutex); } + STRUCT_UNLOCK(&structure_guard_mutex); + DBUG_VOID_RETURN; } @@ -1422,23 +1476,22 @@ void Query_cache::invalidate(char *db) void Query_cache::invalidate_by_MyISAM_filename(const char *filename) { DBUG_ENTER("Query_cache::invalidate_by_MyISAM_filename"); - if (query_cache_size > 0) + + STRUCT_LOCK(&structure_guard_mutex); + if (query_cache_size > 0 && !flush_in_progress) { /* Calculate the key outside the lock to make the lock shorter */ char key[MAX_DBKEY_LENGTH]; uint32 db_length; uint key_length= filename_2_table_key(key, filename, &db_length); - STRUCT_LOCK(&structure_guard_mutex); - if (query_cache_size > 0) // Safety if cache removed - { - Query_cache_block *table_block; - if ((table_block = (Query_cache_block*) hash_search(&tables, - (byte*) key, - key_length))) - invalidate_table(table_block); - } - STRUCT_UNLOCK(&structure_guard_mutex); + Query_cache_block *table_block; + if ((table_block = (Query_cache_block*) hash_search(&tables, + (byte*) key, + key_length))) + invalidate_table(table_block); } + STRUCT_UNLOCK(&structure_guard_mutex); + DBUG_VOID_RETURN; } @@ -1483,7 +1536,12 @@ void Query_cache::destroy() } else { + /* Underlying code expects the lock. */ + STRUCT_LOCK(&structure_guard_mutex); free_cache(); + STRUCT_UNLOCK(&structure_guard_mutex); + + pthread_cond_destroy(&COND_flush_finished); pthread_mutex_destroy(&structure_guard_mutex); initialized = 0; } @@ -1499,6 +1557,8 @@ void Query_cache::init() { DBUG_ENTER("Query_cache::init"); pthread_mutex_init(&structure_guard_mutex,MY_MUTEX_INIT_FAST); + pthread_cond_init(&COND_flush_finished, NULL); + flush_in_progress= FALSE; initialized = 1; DBUG_VOID_RETURN; } @@ -1694,6 +1754,17 @@ void Query_cache::make_disabled() } +/* + free_cache() - free all resources allocated by the cache. + + SYNOPSIS + free_cache() + + DESCRIPTION + This function frees all resources allocated by the cache. You + have to call init_cache() before using the cache again. +*/ + void Query_cache::free_cache() { DBUG_ENTER("Query_cache::free_cache"); @@ -1728,17 +1799,51 @@ void Query_cache::free_cache() Free block data *****************************************************************************/ + /* - The following assumes we have a lock on the cache + flush_cache() - flush the cache. + + SYNOPSIS + flush_cache() + + DESCRIPTION + This function will flush cache contents. It assumes we have + 'structure_guard_mutex' locked. The function sets the + flush_in_progress flag and releases the lock, so other threads may + proceed skipping the cache as if it is disabled. Concurrent + flushes are performed in turn. */ void Query_cache::flush_cache() { + /* + If there is flush in progress, wait for it to finish, and then do + our flush. This is necessary because something could be added to + the cache before we acquire the lock again, and some code (like + Query_cache::free_cache()) depends on the fact that after the + flush the cache is empty. + */ + while (flush_in_progress) + pthread_cond_wait(&COND_flush_finished, &structure_guard_mutex); + + /* + Setting 'flush_in_progress' will prevent other threads from using + the cache while we are in the middle of the flush, and we release + the lock so that other threads won't block. + */ + flush_in_progress= TRUE; + STRUCT_UNLOCK(&structure_guard_mutex); + + my_hash_reset(&queries); while (queries_blocks != 0) { BLOCK_LOCK_WR(queries_blocks); - free_query(queries_blocks); + free_query_internal(queries_blocks); } + + STRUCT_LOCK(&structure_guard_mutex); + flush_in_progress= FALSE; + pthread_cond_signal(&COND_flush_finished); } /* @@ -1784,36 +1889,48 @@ my_bool Query_cache::free_old_query() DBUG_RETURN(1); // Nothing to remove } + /* - Free query from query cache. - query_block must be locked for writing. - This function will remove (and destroy) the lock for the query. + free_query_internal() - free query from query cache. + + SYNOPSIS + free_query_internal() + query_block Query_cache_block representing the query + + DESCRIPTION + This function will remove the query from a cache, and place its + memory blocks to the list of free blocks. 'query_block' must be + locked for writing, this function will release (and destroy) this + lock. + + NOTE + 'query_block' should be removed from 'queries' hash _before_ + calling this method, as the lock will be destroyed here. */ -void Query_cache::free_query(Query_cache_block *query_block) +void Query_cache::free_query_internal(Query_cache_block *query_block) { - DBUG_ENTER("Query_cache::free_query"); + DBUG_ENTER("Query_cache::free_query_internal"); DBUG_PRINT("qcache", ("free query 0x%lx %lu bytes result", (ulong) query_block, query_block->query()->length() )); queries_in_cache--; - hash_delete(&queries,(byte *) query_block); - Query_cache_query *query = query_block->query(); + Query_cache_query *query= query_block->query(); if (query->writer() != 0) { /* Tell MySQL that this query should not be cached anymore */ - query->writer()->query_cache_query = 0; + query->writer()->query_cache_query= 0; query->writer(0); } double_linked_list_exclude(query_block, &queries_blocks); - Query_cache_block_table *table=query_block->table(0); + Query_cache_block_table *table= query_block->table(0); - for (TABLE_COUNTER_TYPE i=0; i < query_block->n_tables; i++) + for (TABLE_COUNTER_TYPE i= 0; i < query_block->n_tables; i++) unlink_table(table++); - Query_cache_block *result_block = query->result(); + Query_cache_block *result_block= query->result(); /* The following is true when query destruction was called and no results @@ -1827,11 +1944,11 @@ void Query_cache::free_query(Query_cache_block *query_block) refused++; inserts--; } - Query_cache_block *block = result_block; + Query_cache_block *block= result_block; do { - Query_cache_block *current = block; - block = block->next; + Query_cache_block *current= block; + block= block->next; free_memory_block(current); } while (block != result_block); } @@ -1848,6 +1965,32 @@ void Query_cache::free_query(Query_cache_block *query_block) DBUG_VOID_RETURN; } + +/* + free_query() - free query from query cache. + + SYNOPSIS + free_query() + query_block Query_cache_block representing the query + + DESCRIPTION + This function will remove 'query_block' from 'queries' hash, and + then call free_query_internal(), which see. +*/ + +void Query_cache::free_query(Query_cache_block *query_block) +{ + DBUG_ENTER("Query_cache::free_query"); + DBUG_PRINT("qcache", ("free query 0x%lx %lu bytes result", + (ulong) query_block, + query_block->query()->length() )); + + hash_delete(&queries,(byte *) query_block); + free_query_internal(query_block); + + DBUG_VOID_RETURN; +} + /***************************************************************************** Query data creation *****************************************************************************/ @@ -2431,12 +2574,8 @@ Query_cache::allocate_block(ulong len, my_bool not_less, ulong min, if (!under_guard) { STRUCT_LOCK(&structure_guard_mutex); - /* - It is very unlikely that following condition is TRUE (it is possible - only if other thread is resizing cache), so we check it only after - guard mutex lock - */ - if (unlikely(query_cache.query_cache_size == 0)) + + if (unlikely(query_cache.query_cache_size == 0 || flush_in_progress)) { STRUCT_UNLOCK(&structure_guard_mutex); DBUG_RETURN(0); @@ -2892,11 +3031,9 @@ static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used, (query without tables are not cached) */ -TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, - char *query, - LEX *lex, - TABLE_LIST *tables_used, - uint8 *tables_type) +TABLE_COUNTER_TYPE +Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex, + TABLE_LIST *tables_used, uint8 *tables_type) { TABLE_COUNTER_TYPE table_count; DBUG_ENTER("Query_cache::is_cacheable"); @@ -2979,13 +3116,10 @@ my_bool Query_cache::ask_handler_allowance(THD *thd, void Query_cache::pack_cache() { DBUG_ENTER("Query_cache::pack_cache"); + STRUCT_LOCK(&structure_guard_mutex); - /* - It is very unlikely that following condition is TRUE (it is possible - only if other thread is resizing cache), so we check it only after - guard mutex lock - */ - if (unlikely(query_cache_size == 0)) + + if (unlikely(query_cache_size == 0 || flush_in_progress)) { STRUCT_UNLOCK(&structure_guard_mutex); DBUG_VOID_RETURN; @@ -3300,7 +3434,7 @@ my_bool Query_cache::join_results(ulong join_limit) DBUG_ENTER("Query_cache::join_results"); STRUCT_LOCK(&structure_guard_mutex); - if (queries_blocks != 0) + if (queries_blocks != 0 && !flush_in_progress) { DBUG_ASSERT(query_cache_size > 0); Query_cache_block *block = queries_blocks; @@ -3587,31 +3721,23 @@ void Query_cache::tables_dump() } -my_bool Query_cache::check_integrity(bool not_locked) +my_bool Query_cache::check_integrity(bool locked) { my_bool result = 0; uint i; DBUG_ENTER("check_integrity"); - if (query_cache_size == 0) + if (!locked) + STRUCT_LOCK(&structure_guard_mutex); + + if (unlikely(query_cache_size == 0 || flush_in_progress)) { + if (!locked) + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); + DBUG_PRINT("qcache", ("Query Cache not initialized")); DBUG_RETURN(0); } - if (!not_locked) - { - STRUCT_LOCK(&structure_guard_mutex); - /* - It is very unlikely that following condition is TRUE (it is possible - only if other thread is resizing cache), so we check it only after - guard mutex lock - */ - if (unlikely(query_cache_size == 0)) - { - STRUCT_UNLOCK(&query_cache.structure_guard_mutex); - DBUG_RETURN(0); - } - } if (hash_check(&queries)) { @@ -3856,7 +3982,7 @@ my_bool Query_cache::check_integrity(bool not_locked) } } DBUG_ASSERT(result == 0); - if (!not_locked) + if (!locked) STRUCT_UNLOCK(&structure_guard_mutex); DBUG_RETURN(result); } diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 29d314d3c44..a66067159e2 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -195,7 +195,6 @@ extern "C" byte *query_cache_table_get_key(const byte *record, uint *length, my_bool not_used); } -void query_cache_insert(NET *thd, const char *packet, ulong length); extern "C" void query_cache_invalidate_by_MyISAM_filename(const char* filename); @@ -241,6 +240,12 @@ public: ulong free_memory, queries_in_cache, hits, inserts, refused, free_memory_blocks, total_blocks, lowmem_prunes; +private: + pthread_cond_t COND_flush_finished; + bool flush_in_progress; + + void free_query_internal(Query_cache_block *point); + protected: /* The following mutex is locked when searching or changing global @@ -249,6 +254,12 @@ protected: LOCK SEQUENCE (to prevent deadlocks): 1. structure_guard_mutex 2. query block (for operation inside query (query block/results)) + + Thread doing cache flush releases the mutex once it sets + flush_in_progress flag, so other threads may bypass the cache as + if it is disabled, not waiting for reset to finish. The exception + is other threads that were going to do cache flush---they'll wait + till the end of a flush operation. */ pthread_mutex_t structure_guard_mutex; byte *cache; // cache memory @@ -358,6 +369,7 @@ protected: If query is cacheable return number tables in query (query without tables not cached) */ + static TABLE_COUNTER_TYPE is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex, TABLE_LIST *tables_used, uint8 *tables_type); @@ -410,6 +422,7 @@ protected: void destroy(); + friend void query_cache_init_query(NET *net); friend void query_cache_insert(NET *net, const char *packet, ulong length); friend void query_cache_end_of_result(THD *thd); friend void query_cache_abort(NET *net); @@ -435,6 +448,8 @@ protected: extern Query_cache query_cache; extern TYPELIB query_cache_type_typelib; +void query_cache_init_query(NET *net); +void query_cache_insert(NET *net, const char *packet, ulong length); void query_cache_end_of_result(THD *thd); void query_cache_abort(NET *net); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 759e3b1a60b..093173ab949 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -224,7 +224,7 @@ THD::THD() #endif client_capabilities= 0; // minimalistic client net.last_error[0]=0; // If error on boot - net.query_cache_query=0; // If error on boot + query_cache_init_query(&net); // If error on boot ull=0; system_thread= cleanup_done= abort_on_warning= no_warnings_for_error= 0; peer_port= 0; // For SHOW PROCESSLIST diff --git a/sql/sql_class.h b/sql/sql_class.h index 53a95a89b51..ed9f4b57f56 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -200,7 +200,7 @@ class MYSQL_LOG: public TC_LOG IO_CACHE log_file; IO_CACHE index_file; char *name; - char time_buff[20],db[NAME_LEN+1]; + char time_buff[20],db[NAME_BYTE_LEN+1]; char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN]; /* The max size before rotation (usable only if log_type == LOG_BIN: binary @@ -342,6 +342,7 @@ public: bool need_mutex); int find_next_log(LOG_INFO* linfo, bool need_mutex); int get_current_log(LOG_INFO* linfo); + int raw_get_current_log(LOG_INFO* linfo); uint next_file_id(); inline bool is_open() { return log_type != LOG_CLOSED; } inline char* get_index_fname() { return index_file_name;} diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 19811efbb12..ebd515bd209 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -139,14 +139,8 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, } if (thd->spcont && - thd->spcont->find_handler(code, - ((int) level >= - (int) MYSQL_ERROR::WARN_LEVEL_WARN && - thd->really_abort_on_warning()) ? - MYSQL_ERROR::WARN_LEVEL_ERROR : level)) + thd->spcont->handle_error(code, level, thd)) { - if (! thd->spcont->found_handler_here()) - thd->net.report_error= 1; /* Make "select" abort correctly */ DBUG_RETURN(NULL); } query_cache_abort(&thd->net); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 563ebce4ff7..43aeea2bf53 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -654,8 +654,9 @@ int MYSQLlex(void *arg, void *yythd) */ if ((yylval->lex_str.str[0]=='_') && - (lex->charset=get_charset_by_csname(yylval->lex_str.str+1, - MY_CS_PRIMARY,MYF(0)))) + (lex->underscore_charset= + get_charset_by_csname(yylval->lex_str.str + 1, + MY_CS_PRIMARY,MYF(0)))) return(UNDERSCORE_CHARSET); return(result_state); // IDENT or IDENT_QUOTED @@ -1040,6 +1041,8 @@ int MYSQLlex(void *arg, void *yythd) if (c == '.') lex->next_state=MY_LEX_IDENT_SEP; length= (uint) (lex->ptr - lex->tok_start)-1; + if (length == 0) + return(ABORT_SYM); // Names must be nonempty. if ((tokval= find_keyword(lex,length,0))) { yyUnget(); // Put back 'c' @@ -1521,10 +1524,10 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) */ Query_arena *arena= thd->stmt_arena; return (ref_pointer_array= - (Item **)arena->alloc(sizeof(Item*) * - (item_list.elements + - select_n_having_items + - order_group_num)* 5)) == 0; + (Item **)arena->alloc(sizeof(Item*) * (n_child_sum_items + + item_list.elements + + select_n_having_items + + order_group_num)*5)) == 0; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 220d928ccf7..2e19c54cbfe 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -548,6 +548,12 @@ public: bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */ /* TRUE when having fix field called in processing of this SELECT */ bool having_fix_field; + + /* Number of Item_sum-derived objects in this SELECT */ + uint n_sum_items; + /* Number of Item_sum-derived objects in children and descendant SELECTs */ + uint n_child_sum_items; + /* explicit LIMIT clause was used */ bool explicit_limit; /* @@ -640,7 +646,7 @@ public: bool test_limit(); friend void lex_start(THD *thd, uchar *buf, uint length); - st_select_lex() {} + st_select_lex() : n_sum_items(0), n_child_sum_items(0) {} void make_empty_select() { init_query(); @@ -834,7 +840,7 @@ typedef struct st_lex : public Query_tables_list XID *xid; gptr yacc_yyss,yacc_yyvs; THD *thd; - CHARSET_INFO *charset; + CHARSET_INFO *charset, *underscore_charset; /* store original leaf_tables for INSERT SELECT and PS/SP */ TABLE_LIST *leaf_tables_insert; /* Position (first character index) of SELECT of CREATE VIEW statement */ diff --git a/sql/sql_load.cc b/sql/sql_load.cc index b1ba2e96651..d5faf6ee7e9 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -147,10 +147,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, MYF(0)); DBUG_RETURN(TRUE); } - /* - This needs to be done before external_lock - */ - ha_enable_transaction(thd, FALSE); if (open_and_lock_tables(thd, table_list)) DBUG_RETURN(TRUE); if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, @@ -394,7 +390,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); table->next_number_field=0; } - ha_enable_transaction(thd, TRUE); if (file >= 0) my_close(file,MYF(0)); free_blobs(table); /* if pack_blob was used */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 905e8cdc71a..d809c1b2cb0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1001,8 +1001,8 @@ static int check_connection(THD *thd) char *passwd= strend(user)+1; uint user_len= passwd - user - 1; char *db= passwd; - char db_buff[NAME_LEN+1]; // buffer to store db in utf8 - char user_buff[USERNAME_LENGTH+1]; // buffer to store user in utf8 + char db_buff[NAME_BYTE_LEN + 1]; // buffer to store db in utf8 + char user_buff[USERNAME_BYTE_LENGTH + 1]; // buffer to store user in utf8 uint dummy_errors; /* @@ -1662,7 +1662,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, password. New clients send the size (1 byte) + string (not null terminated, so also '\0' for empty string). */ - char db_buff[NAME_LEN+1]; // buffer to store db in utf8 + char db_buff[NAME_BYTE_LEN+1]; // buffer to store db in utf8 char *db= passwd; uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? *passwd++ : strlen(passwd); @@ -5785,7 +5785,6 @@ void mysql_init_multi_delete(LEX *lex) lex->query_tables_last= &lex->query_tables; } - /* When you modify mysql_parse(), you may need to mofify mysql_test_parse_for_slave() in this same file. @@ -5794,6 +5793,9 @@ void mysql_init_multi_delete(LEX *lex) void mysql_parse(THD *thd, char *inBuf, uint length) { DBUG_ENTER("mysql_parse"); + + DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on();); + mysql_init_query(thd, (uchar*) inBuf, length); if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) { @@ -6688,11 +6690,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, select_errors=0; /* Write if more errors */ bool tmp_write_to_binlog= 1; - if (thd && thd->in_sub_stmt) - { - my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "FLUSH"); - return 1; - } + DBUG_ASSERT(!thd || !thd->in_sub_stmt); #ifndef NO_EMBEDDED_ACCESS_CHECKS if (options & REFRESH_GRANT) @@ -7540,16 +7538,35 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) LEX_USER *get_current_user(THD *thd, LEX_USER *user) { - LEX_USER *curr_user; if (!user->user.str) // current_user - { - if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) - { - my_error(ER_OUTOFMEMORY, MYF(0), sizeof(LEX_USER)); - return 0; - } - get_default_definer(thd, curr_user); - return curr_user; - } + return create_default_definer(thd); + return user; } + + +/* + Check that length of a string does not exceed some limit. + + SYNOPSIS + check_string_length() + cs string charset + str string to be checked + err_msg error message to be displayed if the string is too long + max_length max length + + RETURN + FALSE the passed string is not longer than max_length + TRUE the passed string is longer than max_length +*/ + +bool check_string_length(CHARSET_INFO *cs, LEX_STRING *str, + const char *err_msg, uint max_length) +{ + if (cs->cset->charpos(cs, str->str, str->str + str->length, + max_length) >= str->length) + return FALSE; + + my_error(ER_WRONG_STRING_LENGTH, MYF(0), str->str, err_msg, max_length); + return TRUE; +} diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 6d35c441368..32f0ca6859d 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1877,7 +1877,8 @@ void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length) thd->stmt_map.erase(stmt); } else - mysql_log.write(thd, COM_STMT_PREPARE, "[%lu] %s", stmt->id, packet); + mysql_log.write(thd, COM_STMT_PREPARE, "[%lu] %.*b", stmt->id, + stmt->query_length, stmt->query); /* check_prepared_statemnt sends the metadata packet in case of success */ DBUG_VOID_RETURN; @@ -2252,7 +2253,8 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length) if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); if (error == 0) - mysql_log.write(thd, COM_STMT_EXECUTE, "[%lu] %s", stmt->id, thd->query); + mysql_log.write(thd, COM_STMT_EXECUTE, "[%lu] %.*b", stmt->id, + thd->query_length, thd->query); DBUG_VOID_RETURN; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index ccda69522c7..e1933d42f9e 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1494,10 +1494,14 @@ bool show_binlogs(THD* thd) if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); + + pthread_mutex_lock(mysql_bin_log.get_log_lock()); mysql_bin_log.lock_index(); index_file=mysql_bin_log.get_index_file(); - - mysql_bin_log.get_current_log(&cur); + + mysql_bin_log.raw_get_current_log(&cur); // dont take mutex + pthread_mutex_unlock(mysql_bin_log.get_log_lock()); // lockdep, OK + cur_dir_len= dirname_length(cur.log_file_name); reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 0); diff --git a/sql/sql_repl.h b/sql/sql_repl.h index 9eb6456ee20..6b1e5e6b447 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -22,7 +22,7 @@ typedef struct st_slave_info uint32 server_id; uint32 rpl_recovery_rank, master_id; char host[HOSTNAME_LENGTH+1]; - char user[USERNAME_LENGTH+1]; + char user[USERNAME_BYTE_LENGTH+1]; char password[MAX_PASSWORD_LENGTH+1]; uint16 port; THD* thd; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0ef4cb6da9d..e9d0e003f6d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7210,6 +7210,8 @@ change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list, left_item->collation.collation == value->collation.collation)) { Item *tmp=value->new_item(); + tmp->collation.set(right_item->collation); + if (tmp) { thd->change_item_tree(args + 1, tmp); @@ -7232,6 +7234,8 @@ change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list, right_item->collation.collation == value->collation.collation)) { Item *tmp=value->new_item(); + tmp->collation.set(left_item->collation); + if (tmp) { thd->change_item_tree(args, tmp); @@ -8990,11 +8994,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, keyinfo->key_length+= key_part_info->length; } } - else - { - set_if_smaller(table->s->max_rows, rows_limit); - param->end_write_records= rows_limit; - } if (distinct && field_count != param->hidden_field_count) { @@ -9009,8 +9008,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, null_pack_length-=hidden_null_pack_length; keyinfo->key_parts= ((field_count-param->hidden_field_count)+ test(null_pack_length)); - set_if_smaller(table->s->max_rows, rows_limit); - param->end_write_records= rows_limit; table->distinct= 1; table->s->keys= 1; if (blob_count) @@ -9062,6 +9059,20 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, 0 : FIELDFLAG_BINARY; } } + + /* + Push the LIMIT clause to the temporary table creation, so that we + materialize only up to 'rows_limit' records instead of all result records. + This optimization is not applicable when there is GROUP BY or there is + no GROUP BY, but there are aggregate functions, because both must be + computed for all result rows. + */ + if (!group && !thd->lex->current_select->with_sum_func) + { + set_if_smaller(table->s->max_rows, rows_limit); + param->end_write_records= rows_limit; + } + if (thd->is_fatal_error) // If end of memory goto err; /* purecov: inspected */ table->s->db_record_offset= 1; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 79228be8a76..7aaca809113 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -248,6 +248,10 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) 0 No conversion needed 1 Either character set conversion or adding leading zeros (e.g. for UCS-2) must be done + + NOTE + to_cs may be NULL for "no conversion" if the system variable + character_set_results is NULL. */ bool String::needs_conversion(uint32 arg_length, @@ -256,7 +260,8 @@ bool String::needs_conversion(uint32 arg_length, uint32 *offset) { *offset= 0; - if ((to_cs == &my_charset_bin) || + if (!to_cs || + (to_cs == &my_charset_bin) || (to_cs == from_cs) || my_charset_same(from_cs, to_cs) || ((from_cs == &my_charset_bin) && diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e065a32c2e8..a340c5ffc98 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -715,6 +715,40 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, DBUG_RETURN(-1); } + /* + Convert the default value from client character + set into the column character set if necessary. + */ + if (sql_field->def && + save_cs != sql_field->def->collation.collation && + (sql_field->sql_type == FIELD_TYPE_VAR_STRING || + sql_field->sql_type == FIELD_TYPE_STRING || + sql_field->sql_type == FIELD_TYPE_SET || + sql_field->sql_type == FIELD_TYPE_ENUM)) + { + Query_arena backup_arena; + bool need_to_change_arena= !thd->stmt_arena->is_conventional(); + if (need_to_change_arena) + { + /* Asser that we don't do that at every PS execute */ + DBUG_ASSERT(thd->stmt_arena->is_first_stmt_execute() || + thd->stmt_arena->is_first_sp_execute()); + thd->set_n_backup_active_arena(thd->stmt_arena, &backup_arena); + } + + sql_field->def= sql_field->def->safe_charset_converter(save_cs); + + if (need_to_change_arena) + thd->restore_active_arena(thd->stmt_arena, &backup_arena); + + if (sql_field->def == NULL) + { + /* Could not convert */ + my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); + DBUG_RETURN(-1); + } + } + if (sql_field->sql_type == FIELD_TYPE_SET || sql_field->sql_type == FIELD_TYPE_ENUM) { @@ -776,35 +810,6 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, sql_field->interval_list.empty(); // Don't need interval_list anymore } - /* - Convert the default value from client character - set into the column character set if necessary. - */ - if (sql_field->def && cs != sql_field->def->collation.collation) - { - Query_arena backup_arena; - bool need_to_change_arena= !thd->stmt_arena->is_conventional(); - if (need_to_change_arena) - { - /* Asser that we don't do that at every PS execute */ - DBUG_ASSERT(thd->stmt_arena->is_first_stmt_execute() || - thd->stmt_arena->is_first_sp_execute()); - thd->set_n_backup_active_arena(thd->stmt_arena, &backup_arena); - } - - sql_field->def= sql_field->def->safe_charset_converter(cs); - - if (need_to_change_arena) - thd->restore_active_arena(thd->stmt_arena, &backup_arena); - - if (sql_field->def == NULL) - { - /* Could not convert */ - my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); - DBUG_RETURN(-1); - } - } - if (sql_field->sql_type == FIELD_TYPE_SET) { uint32 field_length; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index e806dd4a3f3..6bb50d602c3 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -158,11 +158,13 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) { TABLE *table; bool result= TRUE; - LEX_STRING definer_user; - LEX_STRING definer_host; + String stmt_query; DBUG_ENTER("mysql_create_or_drop_trigger"); + /* Charset of the buffer for statement must be system one. */ + stmt_query.set_charset(system_charset_info); + /* QQ: This function could be merged in mysql_alter_table() function But do we want this ? @@ -264,8 +266,8 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) } result= (create ? - table->triggers->create_trigger(thd, tables, &definer_user, &definer_host): - table->triggers->drop_trigger(thd, tables)); + table->triggers->create_trigger(thd, tables, &stmt_query): + table->triggers->drop_trigger(thd, tables, &stmt_query)); end: VOID(pthread_mutex_unlock(&LOCK_open)); @@ -277,32 +279,9 @@ end: { thd->clear_error(); - String log_query(thd->query, thd->query_length, system_charset_info); - - if (create) - { - log_query.set((char *) 0, 0, system_charset_info); /* reset log_query */ - - log_query.append(STRING_WITH_LEN("CREATE ")); - - if (definer_user.str && definer_host.str) - { - /* - Append definer-clause if the trigger is SUID (a usual trigger in - new MySQL versions). - */ - - append_definer(thd, &log_query, &definer_user, &definer_host); - } - - log_query.append(thd->lex->stmt_definition_begin, - (char *)thd->lex->sphead->m_body_begin - - thd->lex->stmt_definition_begin + - thd->lex->sphead->m_body.length); - } - /* Such a statement can always go directly to binlog, no trans cache. */ - Query_log_event qinfo(thd, log_query.ptr(), log_query.length(), 0, FALSE); + Query_log_event qinfo(thd, stmt_query.ptr(), stmt_query.length(), 0, + FALSE); mysql_bin_log.write(&qinfo); } @@ -322,22 +301,8 @@ end: LEX) tables - table list containing one open table for which the trigger is created. - definer_user - [out] after a call it points to 0-terminated string or - contains the NULL-string: - - 0-terminated is returned if the trigger is SUID. The - string contains user name part of the actual trigger - definer. - - NULL-string is returned if the trigger is non-SUID. - Anyway, the caller is responsible to provide memory for - storing LEX_STRING object. - definer_host - [out] after a call it points to 0-terminated string or - contains the NULL-string: - - 0-terminated string is returned if the trigger is - SUID. The string contains host name part of the - actual trigger definer. - - NULL-string is returned if the trigger is non-SUID. - Anyway, the caller is responsible to provide memory for - storing LEX_STRING object. + stmt_query - [OUT] after successful return, this string contains + well-formed statement for creation this trigger. NOTE - Assumes that trigger name is fully qualified. @@ -352,8 +317,7 @@ end: True - error */ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, - LEX_STRING *definer_user, - LEX_STRING *definer_host) + String *stmt_query) { LEX *lex= thd->lex; TABLE *table= tables->table; @@ -361,6 +325,8 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, trigname_path[FN_REFLEN]; LEX_STRING dir, file, trigname_file; LEX_STRING *trg_def, *name; + LEX_STRING definer_user; + LEX_STRING definer_host; ulonglong *trg_sql_mode; char trg_definer_holder[USER_HOST_BUFF_SIZE]; LEX_STRING *trg_definer; @@ -508,8 +474,6 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, definers_list.push_back(trg_definer, &table->mem_root)) goto err_with_cleanup; - trg_def->str= thd->query; - trg_def->length= thd->query_length; *trg_sql_mode= thd->variables.sql_mode; #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -529,27 +493,54 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, { /* SUID trigger. */ - *definer_user= lex->definer->user; - *definer_host= lex->definer->host; + definer_user= lex->definer->user; + definer_host= lex->definer->host; trg_definer->str= trg_definer_holder; - trg_definer->length= strxmov(trg_definer->str, definer_user->str, "@", - definer_host->str, NullS) - trg_definer->str; + trg_definer->length= strxmov(trg_definer->str, definer_user.str, "@", + definer_host.str, NullS) - trg_definer->str; } else { /* non-SUID trigger. */ - definer_user->str= 0; - definer_user->length= 0; + definer_user.str= 0; + definer_user.length= 0; - definer_host->str= 0; - definer_host->length= 0; + definer_host.str= 0; + definer_host.length= 0; trg_definer->str= (char*) ""; trg_definer->length= 0; } + /* + Create well-formed trigger definition query. Original query is not + appropriated, because definer-clause can be not truncated. + */ + + stmt_query->append(STRING_WITH_LEN("CREATE ")); + + if (trg_definer) + { + /* + Append definer-clause if the trigger is SUID (a usual trigger in + new MySQL versions). + */ + + append_definer(thd, stmt_query, &definer_user, &definer_host); + } + + stmt_query->append(thd->lex->stmt_definition_begin, + (char *) thd->lex->sphead->m_body_begin - + thd->lex->stmt_definition_begin + + thd->lex->sphead->m_body.length); + + trg_def->str= stmt_query->c_ptr(); + trg_def->length= stmt_query->length(); + + /* Create trigger definition file. */ + if (!sql_create_definition_file(&dir, &file, &triggers_file_type, (gptr)this, triggers_file_parameters, 0)) return 0; @@ -647,15 +638,19 @@ static bool save_trigger_file(Table_triggers_list *triggers, const char *db, SYNOPSIS drop_trigger() - thd - current thread context (including trigger definition in LEX) - tables - table list containing one open table for which trigger is - dropped. + thd - current thread context + (including trigger definition in LEX) + tables - table list containing one open table for which trigger + is dropped. + stmt_query - [OUT] after successful return, this string contains + well-formed statement for creation this trigger. RETURN VALUE False - success True - error */ -bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables) +bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables, + String *stmt_query) { LEX *lex= thd->lex; LEX_STRING *name; @@ -665,6 +660,8 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables) List_iterator<LEX_STRING> it_definer(definers_list); char path[FN_REFLEN]; + stmt_query->append(thd->query, thd->query_length); + while ((name= it_name++)) { it_def++; diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index e736c3e0e1a..521905a2c56 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -92,10 +92,8 @@ public: } ~Table_triggers_list(); - bool create_trigger(THD *thd, TABLE_LIST *table, - LEX_STRING *definer_user, - LEX_STRING *definer_host); - bool drop_trigger(THD *thd, TABLE_LIST *table); + bool create_trigger(THD *thd, TABLE_LIST *table, String *stmt_query); + bool drop_trigger(THD *thd, TABLE_LIST *table, String *stmt_query); bool process_triggers(THD *thd, trg_event_type event, trg_action_time_type time_type, bool old_row_is_record1); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index b4ee542ac39..4e2b48d9faf 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1060,6 +1060,31 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, table->next_global= view_tables; } + bool view_is_mergeable= (table->algorithm != VIEW_ALGORITHM_TMPTABLE && + lex->can_be_merged()); + TABLE_LIST *view_main_select_tables; + if (view_is_mergeable) + { + /* + Currently 'view_main_select_tables' differs from 'view_tables' + only then view has CONVERT_TZ() function in its select list. + This may change in future, for example if we enable merging of + views with subqueries in select list. + */ + view_main_select_tables= + (TABLE_LIST*)lex->select_lex.table_list.first; + + /* + Let us set proper lock type for tables of the view's main + select since we may want to perform update or insert on + view. This won't work for view containing union. But this is + ok since we don't allow insert and update on such views + anyway. + */ + for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local) + tbl->lock_type= table->lock_type; + } + /* If we are opening this view as part of implicit LOCK TABLES, then this view serves as simple placeholder and we should not continue @@ -1114,43 +1139,26 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, - VIEW SELECT allow merging - VIEW used in subquery or command support MERGE algorithm */ - if (table->algorithm != VIEW_ALGORITHM_TMPTABLE && - lex->can_be_merged() && + if (view_is_mergeable && (table->select_lex->master_unit() != &old_lex->unit || old_lex->can_use_merged()) && !old_lex->can_not_use_merged()) { - List_iterator_fast<TABLE_LIST> ti(view_select->top_join_list); - /* - Currently 'view_main_select_tables' differs from 'view_tables' - only then view has CONVERT_TZ() function in its select list. - This may change in future, for example if we enable merging - of views with subqueries in select list. - */ - TABLE_LIST *view_main_select_tables= - (TABLE_LIST*)lex->select_lex.table_list.first; /* lex should contain at least one table */ DBUG_ASSERT(view_main_select_tables != 0); + List_iterator_fast<TABLE_LIST> ti(view_select->top_join_list); + table->effective_algorithm= VIEW_ALGORITHM_MERGE; DBUG_PRINT("info", ("algorithm: MERGE")); table->updatable= (table->updatable_view != 0); table->effective_with_check= old_lex->get_effective_with_check(table); table->merge_underlying_list= view_main_select_tables; - /* - Let us set proper lock type for tables of the view's main select - since we may want to perform update or insert on view. This won't - work for view containing union. But this is ok since we don't - allow insert and update on such views anyway. - Also we fill correct wanted privileges. - */ - for (tbl= table->merge_underlying_list; tbl; tbl= tbl->next_local) - { - tbl->lock_type= table->lock_type; + /* Fill correct wanted privileges. */ + for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local) tbl->grant.want_privilege= top_view->grant.orig_want_privilege; - } /* prepare view context */ lex->select_lex.context.resolve_in_table_list_only(view_main_select_tables); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d2aca27c836..30c7da220a6 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -68,6 +68,34 @@ inline Item *is_truth_value(Item *A, bool v1, bool v2) new Item_int((char *) (v1 ? "FALSE" : "TRUE"),!v1, 1)); } +#ifndef DBUG_OFF +#define YYDEBUG 1 +#else +#define YYDEBUG 0 +#endif + +#ifndef DBUG_OFF +void turn_parser_debug_on() +{ + /* + MYSQLdebug is in sql/sql_yacc.cc, in bison generated code. + Turning this option on is **VERY** verbose, and should be + used when investigating a syntax error problem only. + + The syntax to run with bison traces is as follows : + - Starting a server manually : + mysqld --debug="d,parser_debug" ... + - Running a test : + mysql-test-run.pl --mysqld="--debug=d,parser_debug" ... + + The result will be in the process stderr (var/log/master.err) + */ + + extern int yydebug; + yydebug= 1; +} +#endif + %} %union { int num; @@ -6759,17 +6787,8 @@ flush: FLUSH_SYM opt_no_write_to_binlog { LEX *lex=Lex; - if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - /* - Note that both FLUSH TABLES and FLUSH PRIVILEGES will break - execution in prelocked mode. So it is better to disable - FLUSH in stored functions and triggers completely. - */ - my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "FLUSH"); - YYABORT; - } - lex->sql_command= SQLCOM_FLUSH; lex->type=0; + lex->sql_command= SQLCOM_FLUSH; + lex->type= 0; lex->no_write_to_binlog= $2; } flush_options @@ -7050,7 +7069,7 @@ text_literal: | NCHAR_STRING { $$= new Item_string($1.str,$1.length,national_charset_info); } | UNDERSCORE_CHARSET TEXT_STRING - { $$ = new Item_string($2.str,$2.length,Lex->charset); } + { $$ = new Item_string($2.str,$2.length,Lex->underscore_charset); } | text_literal TEXT_STRING_literal { ((Item_string*) $1)->append($2.str,$2.length); } ; @@ -7128,7 +7147,7 @@ literal: (String*) 0; $$= new Item_string(str ? str->ptr() : "", str ? str->length() : 0, - Lex->charset); + Lex->underscore_charset); } | UNDERSCORE_CHARSET BIN_NUM { @@ -7487,6 +7506,10 @@ user: $$->user = $1; $$->host.str= (char *) "%"; $$->host.length= 1; + + if (check_string_length(system_charset_info, &$$->user, + ER(ER_USERNAME), USERNAME_LENGTH)) + YYABORT; } | ident_or_text '@' ident_or_text { @@ -7494,6 +7517,12 @@ user: if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) YYABORT; $$->user = $1; $$->host=$3; + + if (check_string_length(system_charset_info, &$$->user, + ER(ER_USERNAME), USERNAME_LENGTH) || + check_string_length(&my_charset_latin1, &$$->host, + ER(ER_HOSTNAME), HOSTNAME_LENGTH)) + YYABORT; } | CURRENT_USER optional_braces { @@ -8927,8 +8956,10 @@ subselect_end: { LEX *lex=Lex; lex->pop_context(); + SELECT_LEX *child= lex->current_select; lex->current_select = lex->current_select->return_after_parsing(); lex->nest_level--; + lex->current_select->n_child_sum_items += child->n_sum_items; }; /************************************************************************** @@ -8971,15 +9002,9 @@ definer: */ YYTHD->lex->definer= 0; } - | DEFINER_SYM EQ CURRENT_USER optional_braces - { - if (! (YYTHD->lex->definer= create_default_definer(YYTHD))) - YYABORT; - } - | DEFINER_SYM EQ ident_or_text '@' ident_or_text + | DEFINER_SYM EQ user { - if (!(YYTHD->lex->definer= create_definer(YYTHD, &$3, &$5))) - YYABORT; + YYTHD->lex->definer= get_current_user(YYTHD, $3); } ; diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 838f547dc02..43f35c452f7 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -21,6 +21,7 @@ #ifdef HAVE_STACKTRACE #include <unistd.h> +#include <strings.h> #define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end) @@ -44,7 +45,29 @@ void safe_print_str(const char* name, const char* val, int max_len) } #ifdef TARGET_OS_LINUX -#define SIGRETURN_FRAME_COUNT 2 + +#ifdef __i386__ +#define SIGRETURN_FRAME_OFFSET 17 +#endif + +#ifdef __x86_64__ +#define SIGRETURN_FRAME_OFFSET 23 +#endif + +static my_bool is_nptl; + +/* Check if we are using NPTL or LinuxThreads on Linux */ +void check_thread_lib(void) +{ + char buf[5]; + +#ifdef _CS_GNU_LIBPTHREAD_VERSION + confstr(_CS_GNU_LIBPTHREAD_VERSION, buf, sizeof(buf)); + is_nptl = !strncasecmp(buf, "NPTL", sizeof(buf)); +#else + is_nptl = 0; +#endif +} #if defined(__alpha__) && defined(__GNUC__) /* @@ -90,7 +113,7 @@ inline uint32* find_prev_pc(uint32* pc, uchar** fp) void print_stacktrace(gptr stack_bottom, ulong thread_stack) { uchar** fp; - uint frame_count = 0; + uint frame_count = 0, sigreturn_frame_count; #if defined(__alpha__) && defined(__GNUC__) uint32* pc; #endif @@ -100,28 +123,27 @@ void print_stacktrace(gptr stack_bottom, ulong thread_stack) Attempting backtrace. You can use the following information to find out\n\ where mysqld died. If you see no messages after this, something went\n\ terribly wrong...\n"); -#ifdef __i386__ +#ifdef __i386__ __asm __volatile__ ("movl %%ebp,%0" :"=r"(fp) :"r"(fp)); - if (!fp) - { - fprintf(stderr, "frame pointer (ebp) is NULL, did you compile with\n\ --fomit-frame-pointer? Aborting backtrace!\n"); - return; - } +#endif +#ifdef __x86_64__ + __asm __volatile__ ("movq %%rbp,%0" + :"=r"(fp) + :"r"(fp)); #endif #if defined(__alpha__) && defined(__GNUC__) __asm __volatile__ ("mov $30,%0" :"=r"(fp) :"r"(fp)); +#endif if (!fp) { - fprintf(stderr, "frame pointer (fp) is NULL, did you compile with\n\ + fprintf(stderr, "frame pointer is NULL, did you compile with\n\ -fomit-frame-pointer? Aborting backtrace!\n"); return; } -#endif /* __alpha__ */ if (!stack_bottom || (gptr) stack_bottom > (gptr) &fp) { @@ -151,13 +173,16 @@ terribly wrong...\n"); :"r"(pc)); #endif /* __alpha__ */ + /* We are 1 frame above signal frame with NPTL and 2 frames above with LT */ + sigreturn_frame_count = is_nptl ? 1 : 2; + while (fp < (uchar**) stack_bottom) { -#ifdef __i386__ +#if defined(__i386__) || defined(__x86_64__) uchar** new_fp = (uchar**)*fp; - fprintf(stderr, "%p\n", frame_count == SIGRETURN_FRAME_COUNT ? - *(fp+17) : *(fp+1)); -#endif /* __386__ */ + fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ? + *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1)); +#endif /* defined(__386__) || defined(__x86_64__) */ #if defined(__alpha__) && defined(__GNUC__) uchar** new_fp = find_prev_fp(pc, fp); diff --git a/sql/stacktrace.h b/sql/stacktrace.h index d5d1e05ef0e..527d10d70a2 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -19,16 +19,20 @@ extern "C" { #endif #ifdef TARGET_OS_LINUX -#if defined(HAVE_STACKTRACE) || (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) +#if defined(HAVE_STACKTRACE) || (defined (__x86_64__) || defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) #undef HAVE_STACKTRACE #define HAVE_STACKTRACE extern char* __bss_start; extern char* heap_start; -#define init_stacktrace() { heap_start = (char*) &__bss_start; } +#define init_stacktrace() do { \ + heap_start = (char*) &__bss_start; \ + check_thread_lib(); \ + } while(0); void print_stacktrace(gptr stack_bottom, ulong thread_stack); void safe_print_str(const char* name, const char* val, int max_len); +void check_thread_lib(void); #endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */ #endif /* TARGET_OS_LINUX */ diff --git a/sql/table.cc b/sql/table.cc index 0a95461cf06..054736401ff 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1592,7 +1592,7 @@ char *get_field(MEM_ROOT *mem, Field *field) bool check_db_name(char *name) { - char *start=name; + uint name_length= 0; // name length in symbols /* Used to catch empty names and names with end space */ bool last_char_is_space= TRUE; @@ -1609,6 +1609,7 @@ bool check_db_name(char *name) name+system_charset_info->mbmaxlen); if (len) { + name_length++; name += len; continue; } @@ -1616,12 +1617,13 @@ bool check_db_name(char *name) #else last_char_is_space= *name==' '; #endif + name_length++; if (*name == '/' || *name == '\\' || *name == FN_LIBCHAR || *name == FN_EXTCHAR) return 1; name++; } - return last_char_is_space || (uint) (name - start) > NAME_LEN; + return (last_char_is_space || name_length > NAME_LEN); } diff --git a/strings/CMakeLists.txt b/strings/CMakeLists.txt new file mode 100755 index 00000000000..0c65ce390b2 --- /dev/null +++ b/strings/CMakeLists.txt @@ -0,0 +1,12 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +ADD_LIBRARY(strings bchange.c bcmp.c bfill.c bmove512.c bmove_upp.c ctype-big5.c ctype-bin.c ctype-cp932.c + ctype-czech.c ctype-euc_kr.c ctype-eucjpms.c ctype-extra.c ctype-gb2312.c ctype-gbk.c + ctype-latin1.c ctype-mb.c ctype-simple.c ctype-sjis.c ctype-tis620.c ctype-uca.c + ctype-ucs2.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype.c decimal.c int2str.c + is_prefix.c llstr.c longlong2str.c my_strtoll10.c my_vsnprintf.c r_strinstr.c + str2int.c str_alloc.c strcend.c strend.c strfill.c strmake.c strmov.c strnmov.c + strtod.c strtol.c strtoll.c strtoul.c strtoull.c strxmov.c strxnmov.c xml.c + strcont.c strinstr.c) diff --git a/strings/Makefile.am b/strings/Makefile.am index 7ee115c09e5..255bc4e1518 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -53,7 +53,7 @@ EXTRA_DIST = ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc bmove_upp-sparc.s strappend-sparc.s strend-sparc.s \ strinstr-sparc.s strmake-sparc.s strmov-sparc.s \ strnmov-sparc.s strstr-sparc.s strxmov-sparc.s \ - t_ctype.h + t_ctype.h CMakeLists.txt libmystrings_a_LIBADD= conf_to_src_SOURCES = conf_to_src.c xml.c ctype.c bcmp.c diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index b4942072e5d..eefc4f55d35 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -677,6 +677,9 @@ fi %attr(755, root, root) %{_bindir}/ndb_show_tables %attr(755, root, root) %{_bindir}/ndb_test_platform %attr(755, root, root) %{_bindir}/ndb_config +%attr(755, root, root) %{_bindir}/ndb_error_reporter +%attr(755, root, root) %{_bindir}/ndb_size.pl +%attr(-, root, root) %{_datadir}/mysql/ndb_size.tmpl %files ndb-extra %defattr(-,root,root,0755) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100755 index 00000000000..46c42d461f3 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,9 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +ADD_DEFINITIONS("-DMYSQL_CLIENT") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + +ADD_EXECUTABLE(mysql_client_test mysql_client_test.c) +TARGET_LINK_LIBRARIES(mysql_client_test dbug mysys mysqlclient yassl taocrypt zlib wsock32) diff --git a/tests/Makefile.am b/tests/Makefile.am index ab747d6e4ec..3eb3d39de1e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -29,7 +29,8 @@ EXTRA_DIST = auto_increment.res auto_increment.tst \ insert_and_repair.pl \ grant.pl grant.res test_delayed_insert.pl \ pmail.pl mail_to_db.pl table_types.pl \ - udf_test udf_test.res myisam-big-rows.tst + udf_test udf_test.res myisam-big-rows.tst \ + CMakeLists.txt bin_PROGRAMS = mysql_client_test noinst_PROGRAMS = insert_test select_test thread_test diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 427994f832f..8a444590301 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -10444,8 +10444,9 @@ static void test_ps_i18n() const char *stmt_text; MYSQL_BIND bind_array[2]; - const char *koi8= "îÕ, ÚÁ ÒÙÂÁÌËÕ"; - const char *cp1251= "Íó, çà ðûáàëêó"; + /* Represented as numbers to keep UTF8 tools from clobbering them. */ + const char *koi8= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5"; + const char *cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3"; char buf1[16], buf2[16]; ulong buf1_len, buf2_len; @@ -14912,22 +14913,31 @@ static void test_bug15613() /* Bug#17667: An attacker has the opportunity to bypass query logging. + + Note! Also tests Bug#21813, where prepared statements are used to + run queries */ static void test_bug17667() { int rc; + MYSQL_STMT *stmt; + enum query_type { QT_NORMAL, QT_PREPARED}; struct buffer_and_length { + enum query_type qt; const char *buffer; const uint length; } statements[]= { - { "drop table if exists bug17667", 29 }, - { "create table bug17667 (c varchar(20))", 37 }, - { "insert into bug17667 (c) values ('regular') /* NUL=\0 with comment */", 68 }, - { "insert into bug17667 (c) values ('NUL=\0 in value')", 50 }, - { "insert into bug17667 (c) values ('5 NULs=\0\0\0\0\0')", 48 }, - { "/* NUL=\0 with comment */ insert into bug17667 (c) values ('encore')", 67 }, - { "drop table bug17667", 19 }, - { NULL, 0 } }; + { QT_NORMAL, "drop table if exists bug17667", 29 }, + { QT_NORMAL, "create table bug17667 (c varchar(20))", 37 }, + { QT_NORMAL, "insert into bug17667 (c) values ('regular') /* NUL=\0 with comment */", 68 }, + { QT_PREPARED, + "insert into bug17667 (c) values ('prepared') /* NUL=\0 with comment */", 69, }, + { QT_NORMAL, "insert into bug17667 (c) values ('NUL=\0 in value')", 50 }, + { QT_NORMAL, "insert into bug17667 (c) values ('5 NULs=\0\0\0\0\0')", 48 }, + { QT_PREPARED, "insert into bug17667 (c) values ('6 NULs=\0\0\0\0\0\0')", 50 }, + { QT_NORMAL, "/* NUL=\0 with comment */ insert into bug17667 (c) values ('encore')", 67 }, + { QT_NORMAL, "drop table bug17667", 19 }, + { QT_NORMAL, NULL, 0 } }; struct buffer_and_length *statement_cursor; FILE *log_file; @@ -14937,9 +14947,36 @@ static void test_bug17667() for (statement_cursor= statements; statement_cursor->buffer != NULL; statement_cursor++) { - rc= mysql_real_query(mysql, statement_cursor->buffer, - statement_cursor->length); - myquery(rc); + if (statement_cursor->qt == QT_NORMAL) + { + /* Run statement as normal query */ + rc= mysql_real_query(mysql, statement_cursor->buffer, + statement_cursor->length); + myquery(rc); + } + else if (statement_cursor->qt == QT_PREPARED) + { + /* + Run as prepared statement + + NOTE! All these queries should be in the log twice, + one time for prepare and one time for execute + */ + stmt= mysql_stmt_init(mysql); + + rc= mysql_stmt_prepare(stmt, statement_cursor->buffer, + statement_cursor->length); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + mysql_stmt_close(stmt); + } + else + { + assert(0==1); + } } /* Make sure the server has written the logs to disk before reading it */ @@ -14957,29 +14994,36 @@ static void test_bug17667() for (statement_cursor= statements; statement_cursor->buffer != NULL; statement_cursor++) { + int expected_hits= 1, hits= 0; char line_buffer[MAX_TEST_QUERY_LENGTH*2]; /* more than enough room for the query and some marginalia. */ + /* Prepared statments always occurs twice in log */ + if (statement_cursor->qt == QT_PREPARED) + expected_hits++; + + /* Loop until we found expected number of log entries */ do { - memset(line_buffer, '/', MAX_TEST_QUERY_LENGTH*2); + /* Loop until statement is found in log */ + do { + memset(line_buffer, '/', MAX_TEST_QUERY_LENGTH*2); - if(fgets(line_buffer, MAX_TEST_QUERY_LENGTH*2, log_file) == NULL) - { - /* If fgets returned NULL, it indicates either error or EOF */ - if (feof(log_file)) - DIE("Found EOF before all statements where found"); - else + if(fgets(line_buffer, MAX_TEST_QUERY_LENGTH*2, log_file) == NULL) { + /* If fgets returned NULL, it indicates either error or EOF */ + if (feof(log_file)) + DIE("Found EOF before all statements where found"); + fprintf(stderr, "Got error %d while reading from file\n", ferror(log_file)); DIE("Read error"); } - } - /* Print the line */ - printf("%s", line_buffer); - } while (my_memmem(line_buffer, MAX_TEST_QUERY_LENGTH*2, - statement_cursor->buffer, statement_cursor->length) == NULL); + } while (my_memmem(line_buffer, MAX_TEST_QUERY_LENGTH*2, + statement_cursor->buffer, + statement_cursor->length) == NULL); + hits++; + } while (hits < expected_hits); printf("Found statement starting with \"%s\"\n", statement_cursor->buffer); diff --git a/vio/CMakeLists.txt b/vio/CMakeLists.txt new file mode 100755 index 00000000000..a3cbb304289 --- /dev/null +++ b/vio/CMakeLists.txt @@ -0,0 +1,6 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX") + +ADD_DEFINITIONS(-DUSE_SYMDIR) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/extra/yassl/include) +ADD_LIBRARY(vio vio.c viosocket.c viossl.c viosslfactories.c) diff --git a/vio/Makefile.am b/vio/Makefile.am index e89191d57cd..cb70501046e 100644 --- a/vio/Makefile.am +++ b/vio/Makefile.am @@ -38,6 +38,6 @@ test_sslclient_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \ ../mysys/libmysys.a ../strings/libmystrings.a \ $(openssl_libs) $(yassl_libs) libvio_a_SOURCES= vio.c viosocket.c viossl.c viosslfactories.c - +EXTRA_DIST= CMakeLists.txt # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/vio/viosocket.c b/vio/viosocket.c index 710f7a93607..1f348c3313d 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -379,16 +379,30 @@ my_bool vio_poll_read(Vio *vio,uint timeout) } -void vio_timeout(Vio *vio __attribute__((unused)), - uint which __attribute__((unused)), - uint timeout __attribute__((unused))) +void vio_timeout(Vio *vio, uint which, uint timeout) { +/* TODO: some action should be taken if socket timeouts are not supported. */ +#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO) + #ifdef __WIN__ - ulong wait_timeout= (ulong) timeout * 1000; - (void) setsockopt(vio->sd, SOL_SOCKET, - which ? SO_SNDTIMEO : SO_RCVTIMEO, (char*) &wait_timeout, - sizeof(wait_timeout)); -#endif /* __WIN__ */ + + /* Windows expects time in milliseconds as int. */ + int wait_timeout= (int) timeout * 1000; + +#else /* ! __WIN__ */ + + /* POSIX specifies time as struct timeval. */ + struct timeval wait_timeout; + wait_timeout.tv_sec= timeout; + wait_timeout.tv_usec= 0; + +#endif /* ! __WIN__ */ + + /* TODO: return value should be checked. */ + (void) setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO, + (char*) &wait_timeout, sizeof(wait_timeout)); + +#endif /* defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO) */ } diff --git a/win/Makefile.am b/win/Makefile.am new file mode 100755 index 00000000000..05c01b61360 --- /dev/null +++ b/win/Makefile.am @@ -0,0 +1,21 @@ +# Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +# +# 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 + +## Process this file with automake to create Makefile.in +EXTRA_DIST = build-vs71.bat build-vs8.bat build-vs8_x64.bat configure.js README + +# Don't update the files from bitkeeper +%::SCCS/s.% diff --git a/win/README b/win/README new file mode 100644 index 00000000000..cbda33e1184 --- /dev/null +++ b/win/README @@ -0,0 +1,82 @@ +Windows building readme +====================================== + +----------------IMPORTANT---------------------------- +This readme outlines the instructions for building +MySQL for Windows staring from version 5.0. +This readme does not apply to MySQL versions 5.1 +or ealier. +----------------------------------------------------- + +The Windows build system uses a tool named CMake to generate build files for +a variety of project systems. This tool is combined with a set of jscript +files to enable building of MySQL for Windows directly out of a bk clone. +The steps required are below. + +Step 1 +------ +Download and install CMake. It can be downloaded from http://www.cmake.org. +Once it is installed, modify your path to make sure you can execute +the cmake binary. + +Step 2 +------ +Download and install bison for Windows. It can be downloaded from +http://gnuwin32.sourceforge.net/packages/bison.htm. Please download using +the link named "Complete package, excluding sources". This includes an +installer that will install bison. After the installer finishes, modify +your path so that you can execute bison. + +Step 3 +------ +Clone your bk tree to any location you like. + +Step 4 +------ +From the root of your bk clone, execute the command: win\configure <options>. +The options right now are + + WITH_INNOBASE_STORAGE_ENGINE Enable particular storage engines + WITH_PARTITION_STORAGE_ENGINE + WITH_ARCHIVE_STORAGE_ENGINE + WITH_BERKELEY_STORAGE_ENGINE + WITH_BLACKHOLE_STORAGE_ENGINE + WITH_EXAMPLE_STORAGE_ENGINE + WITH_FEDERATED_STORAGE_ENGINE + WITH_INNOBASE_STORAGE_ENGINE + __NT__ Enable named pipe support + MYSQL_SERVER_SUFFIX=<suffix> Server suffix, default none + COMPILATION_COMMENT=<comment> Server comment, default "Source distribution" + MYSQL_TCP_PORT=<port> Server port, default 3306 + CYBOZU + +So the command line could look like: + +win\configure WITH_INNOBASE_STORAGE_ENGINE WITH_PARTITION_STORAGE_ENGINE MYSQL_SERVER_SUFFIX=-pro + +Step 5 +------ +From the root of your bk clone, execute one of the batch files to generate the type +of project files you desire. + +For Visual Studio 8, do win\build-vs8. +For Visual Studio 7.1, do win\build-vs71. + +We will support building with nmake in the near future. + +Step 6 +------ +From the root of your bk clone, start your build. + +For Visual Studio, simply execute mysql.sln. This will start the IDE and you can +click the build solution menu option. + +Current issues +-------------- +1. After changing configuration (eg. adding or removing a storage engine), it +may be necessary to clean the build tree to remove any stale objects. + +2. To use Visual C++ Express Edition you also need to install the Platform SDK. +Please see this link: http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/ +At step 4 you only need to add the libraries advapi32.lib and user32.lib to +the file "corewin_express.vsprops" in order to avoid link errors. diff --git a/win/build-vs71.bat b/win/build-vs71.bat new file mode 100755 index 00000000000..959067695c5 --- /dev/null +++ b/win/build-vs71.bat @@ -0,0 +1,7 @@ +@echo off + +if exist cmakecache.txt del cmakecache.txt +copy win\vs71cache.txt cmakecache.txt +cmake -G "Visual Studio 7 .NET 2003" +copy cmakecache.txt win\vs71cache.txt + diff --git a/win/build-vs8.bat b/win/build-vs8.bat new file mode 100755 index 00000000000..d9c06241a9b --- /dev/null +++ b/win/build-vs8.bat @@ -0,0 +1,6 @@ +@echo off + +if exist cmakecache.txt del cmakecache.txt +copy win\vs8cache.txt cmakecache.txt +cmake -G "Visual Studio 8 2005" +copy cmakecache.txt win\vs8cache.txt diff --git a/win/build-vs8_x64.bat b/win/build-vs8_x64.bat new file mode 100755 index 00000000000..f1d96116390 --- /dev/null +++ b/win/build-vs8_x64.bat @@ -0,0 +1,6 @@ +@echo off + +if exist cmakecache.txt del cmakecache.txt +copy win\vs8cache.txt cmakecache.txt +cmake -G "Visual Studio 8 2005 Win64" +copy cmakecache.txt win\vs8cache.txt diff --git a/win/configure.js b/win/configure.js new file mode 100755 index 00000000000..ef90ce982a6 --- /dev/null +++ b/win/configure.js @@ -0,0 +1,166 @@ +// Configure.js + +ForReading = 1; +ForWriting = 2; +ForAppending = 8; + +try +{ + var fso = new ActiveXObject("Scripting.FileSystemObject"); + + var args = WScript.Arguments + + // read in the Unix configure.in file + var configureInTS = fso.OpenTextFile("configure.in", ForReading); + var configureIn = configureInTS.ReadAll(); + configureInTS.Close(); + var default_comment = "Source distribution"; + var default_port = GetValue(configureIn, "MYSQL_TCP_PORT_DEFAULT"); + + var configfile = fso.CreateTextFile("win\\configure.data", true); + for (i=0; i < args.Count(); i++) + { + var parts = args.Item(i).split('='); + switch (parts[0]) + { + case "WITH_ARCHIVE_STORAGE_ENGINE": + case "WITH_BERKELEY_STORAGE_ENGINE": + case "WITH_BLACKHOLE_STORAGE_ENGINE": + case "WITH_EXAMPLE_STORAGE_ENGINE": + case "WITH_FEDERATED_STORAGE_ENGINE": + case "WITH_INNOBASE_STORAGE_ENGINE": + case "WITH_PARTITION_STORAGE_ENGINE": + case "__NT__": + case "CYBOZU": + configfile.WriteLine("SET (" + args.Item(i) + " TRUE)"); + break; + case "MYSQL_SERVER_SUFFIX": + configfile.WriteLine("SET (" + parts[0] + " \"" + + parts[1] + "\")"); + break; + case "COMPILATION_COMMENT": + default_comment = parts[1]; + break; + case "MYSQL_TCP_PORT": + default_port = parts[1]; + break; + } + } + + configfile.WriteLine("SET (COMPILATION_COMMENT \"" + + default_comment + "\")"); + + configfile.WriteLine("SET (PROTOCOL_VERSION \"" + + GetValue(configureIn, "PROTOCOL_VERSION") + "\")"); + configfile.WriteLine("SET (DOT_FRM_VERSION \"" + + GetValue(configureIn, "DOT_FRM_VERSION") + "\")"); + configfile.WriteLine("SET (MYSQL_TCP_PORT \"" + default_port + "\")"); + configfile.WriteLine("SET (MYSQL_UNIX_ADDR \"" + + GetValue(configureIn, "MYSQL_UNIX_ADDR_DEFAULT") + "\")"); + var version = GetVersion(configureIn); + configfile.WriteLine("SET (VERSION \"" + version + "\")"); + configfile.WriteLine("SET (MYSQL_BASE_VERSION \"" + + GetBaseVersion(version) + "\")"); + configfile.WriteLine("SET (MYSQL_VERSION_ID \"" + + GetVersionId(version) + "\")"); + + configfile.Close(); + + //ConfigureBDB(); + + fso = null; + + WScript.Echo("done!"); +} +catch (e) +{ + WScript.Echo("Error: " + e.description); +} + +function GetValue(str, key) +{ + var pos = str.indexOf(key+'='); + if (pos == -1) return null; + pos += key.length + 1; + var end = str.indexOf("\n", pos); + if (str.charAt(pos) == "\"") + pos++; + if (str.charAt(end-1) == "\"") + end--; + return str.substring(pos, end); +} + +function GetVersion(str) +{ + var key = "AM_INIT_AUTOMAKE(mysql, "; + var pos = str.indexOf(key); //5.0.6-beta) + if (pos == -1) return null; + pos += key.length; + var end = str.indexOf(")", pos); + if (end == -1) return null; + return str.substring(pos, end); +} + +function GetBaseVersion(version) +{ + var dot = version.indexOf("."); + if (dot == -1) return null; + dot = version.indexOf(".", dot+1); + if (dot == -1) dot = version.length; + return version.substring(0, dot); +} + +function GetVersionId(version) +{ + var dot = version.indexOf("."); + if (dot == -1) return null; + var major = parseInt(version.substring(0, dot), 10); + + dot++; + var nextdot = version.indexOf(".", dot); + if (nextdot == -1) return null; + var minor = parseInt(version.substring(dot, nextdot), 10); + dot = nextdot+1; + + var stop = version.indexOf("-", dot); + if (stop == -1) stop = version.length; + var build = parseInt(version.substring(dot, stop), 10); + + var id = major; + if (minor < 10) + id += '0'; + id += minor; + if (build < 10) + id += '0'; + id += build; + return id; +} + +function ConfigureBDB() +{ + // read in the Unix configure.in file + var dbIncTS = fso.OpenTextFile("..\\bdb\\dbinc\\db.in", ForReading); + var dbIn = dbIncTS.ReadAll(); + dbIncTS.Close(); + + dbIn = dbIn.replace("@DB_VERSION_MAJOR@", "$DB_VERSION_MAJOR"); + dbIn = dbIn.replace("@DB_VERSION_MINOR@", "$DB_VERSION_MINOR"); + dbIn = dbIn.replace("@DB_VERSION_PATCH@", "$DB_VERSION_PATCH"); + dbIn = dbIn.replace("@DB_VERSION_STRING@", "$DB_VERSION_STRING"); + + dbIn = dbIn.replace("@u_int8_decl@", "typedef unsigned char u_int8_t;"); + dbIn = dbIn.replace("@int16_decl@", "typedef short int16_t;"); + dbIn = dbIn.replace("@u_int16_decl@", "typedef unsigned short u_int16_t;"); + dbIn = dbIn.replace("@int32_decl@", "typedef int int32_t;"); + dbIn = dbIn.replace("@u_int32_decl@", "typedef unsigned int u_int32_t;"); + + dbIn = dbIn.replace("@u_char_decl@", "{\r\n#if !defined(_WINSOCKAPI_)\r\n" + + "typedef unsigned char u_char;"); + dbIn = dbIn.replace("@u_short_decl@", "typedef unsigned short u_short;"); + dbIn = dbIn.replace("@u_int_decl@", "typedef unsigned int u_int;"); + dbIn = dbIn.replace("@u_long_decl@", "typedef unsigned long u_long;"); + + dbIn = dbIn.replace("@ssize_t_decl@", "#endif\r\n#if defined(_WIN64)\r\n" + + "typedef __int64 ssize_t;\r\n#else\r\n" + + "typedef int ssize_t;\r\n#endif"); +} diff --git a/zlib/CMakeLists.txt b/zlib/CMakeLists.txt new file mode 100755 index 00000000000..53560adf6d1 --- /dev/null +++ b/zlib/CMakeLists.txt @@ -0,0 +1,8 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG") + +ADD_DEFINITIONS(-DUSE_TLS -DMYSQL_CLIENT -D__WIN32__) +ADD_LIBRARY(zlib adler32.c compress.c crc32.c crc32.h deflate.c deflate.h gzio.c infback.c inffast.c inffast.h + inffixed.h inflate.c inflate.h inftrees.c inftrees.h trees.c trees.h uncompr.c zconf.h zlib.h + zutil.c zutil.h) +
\ No newline at end of file diff --git a/zlib/Makefile.am b/zlib/Makefile.am index 71619ce40c1..0081c93a2ae 100644 --- a/zlib/Makefile.am +++ b/zlib/Makefile.am @@ -29,5 +29,5 @@ libz_la_SOURCES= adler32.c compress.c crc32.c deflate.c gzio.c \ infback.c inffast.c inflate.c inftrees.c trees.c \ uncompr.c zutil.c -EXTRA_DIST= README FAQ INDEX ChangeLog algorithm.txt zlib.3 +EXTRA_DIST= README FAQ INDEX ChangeLog algorithm.txt zlib.3 CMakeLists.txt |