diff options
author | unknown <tomas@poseidon.ndb.mysql.com> | 2005-06-04 19:26:35 +0200 |
---|---|---|
committer | unknown <tomas@poseidon.ndb.mysql.com> | 2005-06-04 19:26:35 +0200 |
commit | 84f89641cfc6acff016b973c3bfa12ef0a31fe12 (patch) | |
tree | 5a32b384f0388487fb7fee12035b2f2e36fb75d9 | |
parent | 7b3cd08e9bb71e57102a5aa5ab2237980bf92b02 (diff) | |
parent | dab1b26b1d3ec57e11681459282de2fe81e362f3 (diff) | |
download | mariadb-git-84f89641cfc6acff016b973c3bfa12ef0a31fe12.tar.gz |
Merge
BitKeeper/etc/logging_ok:
auto-union
libmysqld/Makefile.am:
Auto merged
sql/field.cc:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/ha_ndbcluster.cc:
Auto merged
sql/ha_ndbcluster.h:
Auto merged
sql/item.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
storage/ndb/src/mgmclient/CommandInterpreter.cpp:
Auto merged
sql/sql_bitmap.h:
merge
52 files changed, 2607 insertions, 730 deletions
diff --git a/BUILD/Makefile.am b/BUILD/Makefile.am index d60672e05f8..27a42cdca16 100644 --- a/BUILD/Makefile.am +++ b/BUILD/Makefile.am @@ -19,6 +19,7 @@ EXTRA_DIST = FINISH.sh \ SETUP.sh \ + check-cpu \ compile-alpha \ compile-alpha-ccc \ compile-alpha-cxx \ diff --git a/BUILD/check-cpu b/BUILD/check-cpu index 0283c669fb2..3ceb9c269fe 100755 --- a/BUILD/check-cpu +++ b/BUILD/check-cpu @@ -6,113 +6,197 @@ # 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 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 + + # 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) + FreeBSD|OpenBSD) cpu_family=`uname -m`; - model_name=`sysctl -b hw.model` + model_name=`sysctl -n hw.model` + ;; + Darwin) + cpu_family=`uname -p` + model_name=`machine` ;; *) cpu_family=`uname -m`; - model_name="unknown"; + model_name=`uname -p`; ;; esac fi -cpu_flag="" -cpu_flag_old="" +# 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_flag="ev6"; + cpu_arg="ev6"; ;; + + # Intel ia32 *Xeon*) - cpu_flag="nocona"; + # 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 ;; - *Pentium*4*Mobile*CPU*) - cpu_flag="pentium4m"; + *Pentium*4*Mobile*) + cpu_arg="pentium4m"; ;; - *Pentium*4*CPU*) - cpu_flag="pentium4"; + *Pentium*4*) + cpu_arg="pentium4"; ;; - *Pentium*III*Mobile*CPU*) - cpu_flag="pentium3m"; + *Pentium*III*Mobile*) + cpu_arg="pentium3m"; ;; - *Pentium*III*CPU*) - cpu_flag="pentium3"; + *Pentium*III*) + cpu_arg="pentium3"; ;; *Pentium*M*pro*) - cpu_flag="pentium-m"; - cpu_flag_old="pentium"; + cpu_arg="pentium-m"; ;; *Athlon*64*) - cpu_flag="athlon64"; - cpu_flag_old="athlon"; + cpu_arg="athlon64"; ;; *Athlon*) - cpu_flag="athlon"; + cpu_arg="athlon"; ;; + + # Intel ia64 *Itanium*) # Don't need to set any flags for itanium(at the moment) - cpu_flag=""; + cpu_arg=""; ;; - *ppc) - cpu_flag="powerpc"; - no_march=1; + + # + *powerpc*) + cpu_arg=`echo $model_name | sed -e"s/ppc//g"` ;; + + # unknown *) - cpu_flag=""; + cpu_arg=""; ;; esac -if test -z "$cpu_flag"; then + +if test -z "$cpu_arg"; then echo "BUILD/check-cpu: Oops, could not findout what kind of cpu this machine is using." - check_cpu_flags="" + check_cpu_cflags="" return fi -echo "cpu_flag: $cpu_flag" - +# 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/[^0-9. ]//g; s/^ *//g; s/ .*//g'` case "$cc_ver--$cc_verno" in - *GCC*--3.4*|*GCC*--3.5*|*GCC*--4.*) - check_cpu_cflags="-mtune=$cpu_flag -march=$cpu_flag" - ;; *GCC*) - # Fix for older compiler versions - if test -n "$cpu_flag_old"; then - cpu_flag="$cpu_flag_old" - fi - check_cpu_cflags="-mcpu=$cpu_flag -march=$cpu_flag" - if test -n "$no_march"; then - check_cpu_cflags="-mcpu=$cpu_flag" - fi + # 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' + ;; + *) + 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 -echo $check_cpu_cflags + +# 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="" + + # 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.* + diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index a559e0f9b0d..5d06a8aac73 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -88,6 +88,7 @@ hf@deer.mysql.r18.ru hf@genie.(none) holyfoot@mysql.com igor@hundin.mysql.fi +igor@igor-inspiron.creware.com igor@linux.local igor@rurik.mysql.com ingo@mysql.com @@ -239,6 +240,7 @@ rburnett@bk-internal.mysql.com rburnett@build.mysql.com reggie@bob.(none) reggie@mdk10.(none) +reggie@monster. root@home.(none) root@mc04.(none) root@x3.internalnet diff --git a/VC++Files/client/mysql.dsp b/VC++Files/client/mysql.dsp index 8298e62d8ad..e9e79a49d0a 100644 --- a/VC++Files/client/mysql.dsp +++ b/VC++Files/client/mysql.dsp @@ -52,7 +52,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\" # SUBTRACT LINK32 /incremental:yes !ELSEIF "$(CFG)" == "mysql - Win32 Debug" @@ -78,7 +78,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysql.exe" /pdbtype:sept /libpath:"..\lib_debug\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysql.exe" /pdbtype:sept /libpath:"..\lib_debug\\" !ELSEIF "$(CFG)" == "mysql - Win32 classic" @@ -104,9 +104,9 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=xilink6.exe -# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\" +# ADD BASE LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\" # SUBTRACT BASE LINK32 /incremental:yes -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_classic/mysql.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_classic/mysql.exe" /libpath:"..\lib_release\\" # SUBTRACT LINK32 /incremental:yes !ENDIF diff --git a/VC++Files/client/mysqladmin.dsp b/VC++Files/client/mysqladmin.dsp index b473d104a76..d713325b4e7 100644 --- a/VC++Files/client/mysqladmin.dsp +++ b/VC++Files/client/mysqladmin.dsp @@ -52,7 +52,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqladmin.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqladmin.exe" /libpath:"..\lib_release\\" !ELSEIF "$(CFG)" == "mysqladmin - Win32 Debug" @@ -77,7 +77,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqladmin.exe" /pdbtype:sept /libpath:"..\lib_debug\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqladmin.exe" /pdbtype:sept /libpath:"..\lib_debug\\" !ELSEIF "$(CFG)" == "mysqladmin - Win32 classic" @@ -104,7 +104,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqladmin.exe" /libpath:"..\lib_release\\" -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqladmin.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqladmin.exe" /libpath:"..\lib_release\\" !ENDIF diff --git a/VC++Files/client/mysqlimport.dsp b/VC++Files/client/mysqlimport.dsp index 1a9b64a0383..1b650dab731 100644 --- a/VC++Files/client/mysqlimport.dsp +++ b/VC++Files/client/mysqlimport.dsp @@ -52,7 +52,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\" # SUBTRACT LINK32 /incremental:yes !ELSEIF "$(CFG)" == "mysqlimport - Win32 Debug" @@ -78,7 +78,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlimport.exe" /pdbtype:sept /libpath:"..\lib_debug\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlimport.exe" /pdbtype:sept /libpath:"..\lib_debug\\" !ELSEIF "$(CFG)" == "mysqlimport - Win32 classic" @@ -104,9 +104,9 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=xilink6.exe -# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\" +# ADD BASE LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\" # SUBTRACT BASE LINK32 /incremental:yes -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlimport.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlimport.exe" /libpath:"..\lib_release\\" # SUBTRACT LINK32 /incremental:yes !ENDIF diff --git a/VC++Files/client/mysqlshow.dsp b/VC++Files/client/mysqlshow.dsp index 855c2dcdf34..f9377763c49 100644 --- a/VC++Files/client/mysqlshow.dsp +++ b/VC++Files/client/mysqlshow.dsp @@ -52,7 +52,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\" !ELSEIF "$(CFG)" == "mysqlshow - Win32 Debug" @@ -77,7 +77,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlshow.exe" /pdbtype:sept /libpath:"..\lib_debug\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlshow.exe" /pdbtype:sept /libpath:"..\lib_debug\\" !ELSEIF "$(CFG)" == "mysqlshow - Win32 classic" @@ -103,8 +103,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=xilink6.exe -# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\" -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlshow.exe" /libpath:"..\lib_release\\" +# ADD BASE LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlshow.exe" /libpath:"..\lib_release\\" !ENDIF diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp index 473aa60d8af..4f93ac93c40 100644 --- a/VC++Files/libmysql/libmysql.dsp +++ b/VC++Files/libmysql/libmysql.dsp @@ -54,7 +54,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 -# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"..\lib_release\libmysql.dll" /libpath:"." /libpath:"..\lib_release" +# ADD LINK32 mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"..\lib_release\libmysql.dll" /libpath:"." /libpath:"..\lib_release" # SUBTRACT LINK32 /pdb:none # Begin Special Build Tool SOURCE="$(InputPath)" @@ -87,7 +87,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 zlib.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"..\lib_debug\libmysql.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug" +# ADD LINK32 zlib.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"..\lib_debug\libmysql.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug" # SUBTRACT LINK32 /pdb:none # Begin Special Build Tool SOURCE="$(InputPath)" diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw index 25bcab8338b..6ebda999c35 100644 --- a/VC++Files/mysql.dsw +++ b/VC++Files/mysql.dsw @@ -80,6 +80,9 @@ Package=<4> Begin Project Dependency Project_Dep_Name zlib End Project Dependency + Begin Project Dependency + Project_Dep_Name mysys + End Project Dependency }}} ############################################################################### @@ -320,6 +323,9 @@ Package=<4> Begin Project Dependency Project_Dep_Name zlib End Project Dependency + Begin Project Dependency + Project_Dep_Name mysys + End Project Dependency }}} ############################################################################### @@ -476,6 +482,9 @@ Package=<4> Begin Project Dependency Project_Dep_Name mysqlclient End Project Dependency + Begin Project Dependency + Project_Dep_Name mysys + End Project Dependency }}} ############################################################################### @@ -533,6 +542,9 @@ Package=<4> Begin Project Dependency Project_Dep_Name mysqlclient End Project Dependency + Begin Project Dependency + Project_Dep_Name mysys + End Project Dependency }}} ############################################################################### diff --git a/client/mysql.cc b/client/mysql.cc index 9cdc270e8ed..ca021cd11f0 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -44,7 +44,7 @@ #include <locale.h> #endif -const char *VER= "14.10"; +const char *VER= "14.11"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -1917,7 +1917,7 @@ com_go(String *buffer,char *line __attribute__((unused))) time_buff[0]=0; if (result) { - if (!mysql_num_rows(result) && ! quick) + if (!mysql_num_rows(result) && ! quick && !info_flag) { strmov(buff, "Empty set"); } @@ -2049,18 +2049,93 @@ com_ego(String *buffer,char *line) return result; } +static char *fieldtype2str(enum enum_field_types type) { + switch(type) { + case FIELD_TYPE_BIT: return "BIT"; + case FIELD_TYPE_BLOB: return "BLOB"; + case FIELD_TYPE_DATE: return "DATE"; + case FIELD_TYPE_DATETIME: return "DATETIME"; + case FIELD_TYPE_NEWDECIMAL: return "NEWDECIMAL"; + case FIELD_TYPE_DECIMAL: return "DECIMAL"; + case FIELD_TYPE_DOUBLE: return "DOUBLE"; + case FIELD_TYPE_ENUM: return "ENUM"; + case FIELD_TYPE_FLOAT: return "FLOAT"; + case FIELD_TYPE_GEOMETRY: return "GEOMETRY"; + case FIELD_TYPE_INT24: return "INT24"; + case FIELD_TYPE_LONG: return "LONG"; + case FIELD_TYPE_LONGLONG: return "LONGLONG"; + case FIELD_TYPE_LONG_BLOB: return "LONG_BLOB"; + case FIELD_TYPE_MEDIUM_BLOB: return "MEDIUM_BLOB"; + case FIELD_TYPE_NEWDATE: return "NEWDATE"; + case FIELD_TYPE_NULL: return "NULL"; + case FIELD_TYPE_SET: return "SET"; + case FIELD_TYPE_SHORT: return "SHORT"; + case FIELD_TYPE_STRING: return "STRING"; + case FIELD_TYPE_TIME: return "TIME"; + case FIELD_TYPE_TIMESTAMP: return "TIMESTAMP"; + case FIELD_TYPE_TINY: return "TINY"; + case FIELD_TYPE_TINY_BLOB: return "TINY_BLOB"; + case FIELD_TYPE_VAR_STRING: return "VAR_STRING"; + case FIELD_TYPE_YEAR: return "YEAR"; + default: return "?-unknown-?"; + } +} + +static char *fieldflags2str(uint f) { + static char buf[1024]; + char *s=buf; + *s=0; +#define ff2s_check_flag(X) \ + if (f & X ## _FLAG) { s=strmov(s, # X " "); f &= ~ X ## _FLAG; } + ff2s_check_flag(NOT_NULL); + ff2s_check_flag(PRI_KEY); + ff2s_check_flag(UNIQUE_KEY); + ff2s_check_flag(MULTIPLE_KEY); + ff2s_check_flag(BLOB); + ff2s_check_flag(UNSIGNED); + ff2s_check_flag(ZEROFILL); + ff2s_check_flag(BINARY); + ff2s_check_flag(ENUM); + ff2s_check_flag(AUTO_INCREMENT); + ff2s_check_flag(TIMESTAMP); + ff2s_check_flag(SET); + ff2s_check_flag(NO_DEFAULT_VALUE); + ff2s_check_flag(NUM); + ff2s_check_flag(PART_KEY); + ff2s_check_flag(GROUP); + ff2s_check_flag(UNIQUE); + ff2s_check_flag(BINCMP); +#undef ff2s_check_flag + if (f) + sprintf(s, " unknows=0x%04x", f); + return buf; +} + static void print_field_types(MYSQL_RES *result) { - MYSQL_FIELD *field; + MYSQL_FIELD *field; + uint i=0; + while ((field = mysql_fetch_field(result))) { - tee_fprintf(PAGER,"Catalog: '%s'\nDatabase: '%s'\nTable: '%s'\nName: '%s'\nType: %d\nLength: %ld\nMax length: %ld\nIs_null: %d\nFlags: %u\nDecimals: %u\n\n", - field->catalog, field->db, field->table, field->name, - (int) field->type, - field->length, field->max_length, - !IS_NOT_NULL(field->flags), - field->flags, field->decimals); + tee_fprintf(PAGER, "Field %3u: `%s`\n" + "Catalog: `%s`\n" + "Database: `%s`\n" + "Table: `%s`\n" + "Org_table: `%s`\n" + "Type: %s\n" + "Collation: %s (%u)\n" + "Length: %lu\n" + "Max_length: %lu\n" + "Decimals: %u\n" + "Flags: %s\n\n", + ++i, + field->name, field->catalog, field->db, field->table, + field->org_table, fieldtype2str(field->type), + get_charset_name(field->charsetnr), field->charsetnr, + field->length, field->max_length, field->decimals, + fieldflags2str(field->flags)); } tee_puts("", PAGER); } @@ -2078,6 +2153,8 @@ print_table_data(MYSQL_RES *result) if (info_flag) { print_field_types(result); + if (!mysql_num_rows(result)) + return; mysql_field_seek(result,0); } separator.copy("+",1,charset_info); diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4 index ada1a2c0bd1..ddacde51c2a 100644 --- a/config/ac-macros/yassl.m4 +++ b/config/ac-macros/yassl.m4 @@ -19,8 +19,8 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ AC_MSG_RESULT([using bundled yaSSL]) yassl_dir="extra/yassl" openssl_libs="\ - \$(top_builddir)/extra/yassl/src/libyassl.a\ - \$(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.a" + -L\$(top_builddir)/extra/yassl/src -lyassl\ + -L\$(top_builddir)/extra/yassl/taocrypt/src -ltaocrypt" openssl_includes="-I\$(top_srcdir)/extra/yassl/include" AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) else diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 466884f3cd9..84ffb9b5829 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -36,7 +36,7 @@ #include "handshake.hpp" #include "yassl_int.hpp" #include <stdio.h> - +#include "runtime.hpp" namespace yaSSL { diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 67f3c963cac..deea376189c 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -3940,7 +3940,10 @@ Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, } #ifdef __GNUC__ -template unsigned int DivideThreeWordsByTwo<unsigned int, DWord>(unsigned int*, unsigned int, unsigned int, DWord*); +#ifndef TAOCRYPT_NATIVE_DWORD_AVAILABLE +template hword DivideThreeWordsByTwo<hword, Word>(hword*, hword, hword, Word*); +#endif +template word DivideThreeWordsByTwo<word, DWord>(word*, word, word, DWord*); #endif } // namespace diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp index 28dbdc5c739..81a8273c5c3 100644 --- a/extra/yassl/taocrypt/src/template_instnt.cpp +++ b/extra/yassl/taocrypt/src/template_instnt.cpp @@ -9,23 +9,27 @@ namespace TaoCrypt { #if defined(SSE2_INTRINSICS_AVAILABLE) template AlignedAllocator<unsigned int>::pointer StdReallocate<unsigned int, AlignedAllocator<unsigned int> >(AlignedAllocator<unsigned int>&, unsigned int*, AlignedAllocator<unsigned int>::size_type, AlignedAllocator<unsigned int>::size_type, bool); #endif -template AllocatorWithCleanup<unsigned char>::pointer StdReallocate<unsigned char, AllocatorWithCleanup<unsigned char> >(AllocatorWithCleanup<unsigned char>&, unsigned char*, AllocatorWithCleanup<unsigned char>::size_type, AllocatorWithCleanup<unsigned char>::size_type, bool); -template AllocatorWithCleanup<unsigned int>::pointer StdReallocate<unsigned int, AllocatorWithCleanup<unsigned int> >(AllocatorWithCleanup<unsigned int>&, unsigned int*, AllocatorWithCleanup<unsigned int>::size_type, AllocatorWithCleanup<unsigned int>::size_type, bool); template class RSA_Decryptor<RSA_BlockType2>; template class RSA_Encryptor<RSA_BlockType1>; template class RSA_Encryptor<RSA_BlockType2>; +template void tcDelete<HASH>(HASH*); +template void tcArrayDelete<byte>(byte*); +template AllocatorWithCleanup<byte>::pointer StdReallocate<byte, AllocatorWithCleanup<byte> >(AllocatorWithCleanup<byte>&, byte*, AllocatorWithCleanup<byte>::size_type, AllocatorWithCleanup<byte>::size_type, bool); +template void tcArrayDelete<word>(word*); +template AllocatorWithCleanup<word>::pointer StdReallocate<word, AllocatorWithCleanup<word> >(AllocatorWithCleanup<word>&, word*, AllocatorWithCleanup<word>::size_type, AllocatorWithCleanup<word>::size_type, bool); +#ifndef TAOCRYPT_SLOW_WORD64 // defined when word != word32 +template void tcArrayDelete<word32>(word32*); +template AllocatorWithCleanup<word32>::pointer StdReallocate<word32, AllocatorWithCleanup<word32> >(AllocatorWithCleanup<word32>&, word32*, AllocatorWithCleanup<word32>::size_type, AllocatorWithCleanup<word32>::size_type, bool); +#endif +template void tcArrayDelete<char>(char*); } namespace mySTL { -template vector<TaoCrypt::Integer>* uninit_fill_n<vector<TaoCrypt::Integer>*, unsigned int, vector<TaoCrypt::Integer> >(vector<TaoCrypt::Integer>*, unsigned int, vector<TaoCrypt::Integer> const&); +template vector<TaoCrypt::Integer>* uninit_fill_n<vector<TaoCrypt::Integer>*, size_t, vector<TaoCrypt::Integer> >(vector<TaoCrypt::Integer>*, size_t, vector<TaoCrypt::Integer> const&); template void destroy<vector<TaoCrypt::Integer>*>(vector<TaoCrypt::Integer>*, vector<TaoCrypt::Integer>*); template TaoCrypt::Integer* uninit_copy<TaoCrypt::Integer*, TaoCrypt::Integer*>(TaoCrypt::Integer*, TaoCrypt::Integer*, TaoCrypt::Integer*); -template TaoCrypt::Integer* uninit_fill_n<TaoCrypt::Integer*, unsigned int, TaoCrypt::Integer>(TaoCrypt::Integer*, unsigned int, TaoCrypt::Integer const&); +template TaoCrypt::Integer* uninit_fill_n<TaoCrypt::Integer*, size_t, TaoCrypt::Integer>(TaoCrypt::Integer*, size_t, TaoCrypt::Integer const&); template void destroy<TaoCrypt::Integer*>(TaoCrypt::Integer*, TaoCrypt::Integer*); } -template void TaoCrypt::tcDelete<TaoCrypt::HASH>(TaoCrypt::HASH*); -template void TaoCrypt::tcArrayDelete<unsigned>(unsigned*); -template void TaoCrypt::tcArrayDelete<unsigned char>(unsigned char*); -template void TaoCrypt::tcArrayDelete<char>(char*); #endif diff --git a/include/config-win.h b/include/config-win.h index bc14d3d3e53..b17e4df4e26 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -76,6 +76,7 @@ functions */ #define F_EXCLUSIVE 1 /* We have only exclusive locking */ #define F_TO_EOF (INT_MAX32/2) /* size for lock of all file */ #define F_OK 0 /* parameter to access() */ +#define W_OK 2 #define S_IROTH S_IREAD /* for my_lib */ diff --git a/include/mysql.h b/include/mysql.h index b2b2e239758..84284fa0661 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -74,14 +74,14 @@ extern char *mysql_unix_port; #define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG) #define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG) #define IS_BLOB(n) ((n) & BLOB_FLAG) -#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR) +#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR || (t) == FIELD_TYPE_NEWDECIMAL) #define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG) #define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR) typedef struct st_mysql_field { char *name; /* Name of column */ - char *org_name; /* Original column name, if an alias */ + char *org_name; /* Original column name, if an alias */ char *table; /* Table of column if column was a field */ char *org_table; /* Org table name, if table was an alias */ char *db; /* Database for table */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index c87728ab783..d294921aad2 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2809,11 +2809,14 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, { switch (attr_type) { case STMT_ATTR_UPDATE_MAX_LENGTH: - *(unsigned long *) value= stmt->update_max_length; + *(ulong*) value= stmt->update_max_length; break; case STMT_ATTR_CURSOR_TYPE: - *(unsigned long *) value= stmt->flags; + *(ulong*) value= stmt->flags; break; + case STMT_ATTR_PREFETCH_ROWS: + *(ulong*) value= stmt->prefetch_rows; + break; default: return TRUE; } diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 776bcb4de69..12bae21a5a0 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -86,29 +86,24 @@ INC_LIB= $(top_builddir)/regex/libregex.a \ # To make it easy for the end user to use the embedded library we # generate a total libmysqld.a from all library files, +# note - InnoDB libraries have circular dependencies, so in INC_LIB +# few libraries are present two times. Metrowerks linker doesn't like +# it at all. Traditional ar has no problems with it, but still there's no +# need to add the same file twice to the library, so 'sort -u' save us +# some time and spares unnecessary work. + libmysqld.a: libmysqld_int.a $(INC_LIB) if DARWIN_MWCC - mwld -lib -o $@ libmysqld_int.a `ls -1 $(INC_LIB) | sort -u` + mwld -lib -o $@ libmysqld_int.a `echo $(INC_LIB) | sort -u` else if test "$(host_os)" = "netware" ; \ then \ $(libmysqld_a_AR) libmysqld.a libmysqld_int.a $(INC_LIB) ; \ else \ - if test ! -d tmp ; then mkdir tmp ; fi ; \ - rm -f $@ libmysqld_int2.a tmp/*.o tmp/*.a ; \ - cp $(INC_LIB) tmp ; \ - cp libmysqld_int.a libmysqld_int2.a ; \ - cd tmp ; \ - for file in *.a ; do \ - bfile=`basename $$file .a` ; \ - $(AR) x $$file; \ - for obj in *.o ; do mv $$obj $${bfile}_$$obj ; done ; \ - $(AR) q ../libmysqld_int2.a *.o ; \ - rm -f *.o ; \ - done ; \ - cd .. ; \ - mv libmysqld_int2.a libmysqld.a ; \ - rm -f tmp/* ; \ + for arc in ./libmysqld_int.a $(INC_LIB); do \ + arpath=`echo $$arc|sed 's|[^/]*$$||'`; \ + $(AR) t $$arc|sed "s|^|$$arpath|"; \ + done | sort -u | xargs $(AR) cq libmysqld.a ; \ $(RANLIB) libmysqld.a ; \ fi endif diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index 5fb21004469..a854cf4c7b0 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -160,3 +160,20 @@ t1 CREATE TABLE `t1` ( `COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; +CREATE TABLE t1 (EMPNUM INT); +INSERT INTO t1 VALUES (0), (2); +CREATE TABLE t2 (EMPNUM DECIMAL (4, 2)); +INSERT INTO t2 VALUES (0.0), (9.0); +SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM, +t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2 +FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM; +CEMPNUM EMPMUM1 EMPNUM2 +0.00 0 0.00 +2.00 2 NULL +SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM, +t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2 +FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM; +CEMPNUM EMPMUM1 EMPNUM2 +0.00 0 0.00 +2.00 2 NULL +DROP TABLE t1,t2; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 8ab24fe550b..4be9139f20b 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -888,3 +888,6 @@ NULL select ifnull(NULL, _utf8'string'); ifnull(NULL, _utf8'string') string +create table t1 (a varchar(255)) default character set utf8; +insert into t1 values (1.0); +drop table t1; diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index 4db31121756..3e72fb45a14 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -91,3 +91,20 @@ drop table t1; SELECT NULLIF(5,5) IS NULL, NULLIF(5,5) IS NOT NULL; NULLIF(5,5) IS NULL NULLIF(5,5) IS NOT NULL 1 0 +CREATE TABLE `t1` ( +`id` int(11) NOT NULL , +`date` int(10) default NULL, +`text` varchar(32) NOT NULL +); +INSERT INTO t1 VALUES (1,1110000000,'Day 1'),(2,1111000000,'Day 2'),(3,1112000000,'Day 3'); +SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord ASC; +id date_ord text +1 05-03-2005 Day 1 +2 16-03-2005 Day 2 +3 28-03-2005 Day 3 +SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord DESC; +id date_ord text +3 28-03-2005 Day 3 +2 16-03-2005 Day 2 +1 05-03-2005 Day 1 +DROP TABLE t1; diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 4293ef5bd85..239fca65b67 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -688,3 +688,6 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 select timestamp_diff(WEEK,_latin1'2001-02-01',_latin1'2001-05-01') AS `a1`,timestamp_diff(SECOND_FRAC,_latin1'2001-02-01 12:59:59.120000',_latin1'2001-05-01 12:58:58.119999') AS `a2` +select time_format('100:00:00', '%H %k %h %I %l'); +time_format('100:00:00', '%H %k %h %I %l') +100 100 04 04 4 diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result index 7f769154212..14cd4666528 100644 --- a/mysql-test/r/ndb_condition_pushdown.result +++ b/mysql-test/r/ndb_condition_pushdown.result @@ -251,6 +251,213 @@ auto 1 3 4 +select auto from t1 where +(string between "aaaa" and "cccc") and +(vstring between "aaaa" and "cccc") and +(bin between 0xAAAA and 0xCCCC) and +(vbin between 0xAAAA and 0xCCCC) and +(tiny between -3 and -1) and +(short between -3 and -1) and +(medium between -3 and -1) and +(long_int between -3 and -1) and +(longlong between -3 and -1) and +(utiny between 1 and 3) and +(ushort between 1 and 3) and +(umedium between 1 and 3) and +(ulong between 1 and 3) and +(ulonglong between 1 and 3) and +(bits between b'001' and b'011') and +(options between 'one' and 'three') and +(flags between 'one' and 'one,two,three') and +(date_field between '1901-01-01' and '1903-03-03') and +(year_field between '1901' and '1903') and +(time_field between '01:01:01' and '03:03:03') and +(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; +auto +1 +3 +select auto from t1 where +("aaaa" between string and string) and +("aaaa" between vstring and vstring) and +(0xAAAA between bin and bin) and +(0xAAAA between vbin and vbin) and +(-1 between tiny and tiny) and +(-1 between short and short) and +(-1 between medium and medium) and +(-1 between long_int and long_int) and +(-1 between longlong and longlong) and +(1 between utiny and utiny) and +(1 between ushort and ushort) and +(1 between umedium and umedium) and +(1 between ulong and ulong) and +(1 between ulonglong and ulonglong) and +(b'001' between bits and bits) and +('one' between options and options) and +('one' between flags and flags) and +('1901-01-01' between date_field and date_field) and +('1901' between year_field and year_field) and +('01:01:01' between time_field and time_field) and +('1901-01-01 01:01:01' between date_time and date_time) +order by auto; +auto +1 +select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +(bits not between b'001' and b'011') and +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; +auto +4 +select auto from t1 where +("aaaa" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +(b'001' not between bits and bits) and +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not between date_time and date_time) +order by auto; +auto +2 +3 +4 +select auto from t1 where +string in("aaaa","cccc") and +vstring in("aaaa","cccc") and +bin in(0xAAAA,0xCCCC) and +vbin in(0xAAAA,0xCCCC) and +tiny in(-1,-3) and +short in(-1,-3) and +medium in(-1,-3) and +long_int in(-1,-3) and +longlong in(-1,-3) and +utiny in(1,3) and +ushort in(1,3) and +umedium in(1,3) and +ulong in(1,3) and +ulonglong in(1,3) and +bits in(b'001',b'011') and +options in('one','three') and +flags in('one','one,two,three') and +date_field in('1901-01-01','1903-03-03') and +year_field in('1901','1903') and +time_field in('01:01:01','03:03:03') and +date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; +auto +1 +3 +select auto from t1 where +"aaaa" in(string) and +"aaaa" in(vstring) and +0xAAAA in(bin) and +0xAAAA in(vbin) and +(-1 in(tiny)) and +(-1 in(short)) and +(-1 in(medium)) and +(-1 in(long_int)) and +(-1 in(longlong)) and +1 in(utiny) and +1 in(ushort) and +1 in(umedium) and +1 in(ulong) and +1 in(ulonglong) and +b'001' in(bits) and +'one' in(options) and +'one' in(flags) and +'1901-01-01' in(date_field) and +'1901' in(year_field) and +'01:01:01' in(time_field) and +'1901-01-01 01:01:01' in(date_time) +order by auto; +auto +1 +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +bits not in(b'001',b'011') and +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; +auto +2 +4 +select auto from t1 where +"aaaa" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +b'001' not in(bits) and +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not in(date_time) +order by auto; +auto +2 +3 +4 select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1; pk1 attr1 attr2 attr3 2 2 NULL NULL @@ -1023,6 +1230,421 @@ auto 1 3 4 +explain +select auto from t1 where +(string between "aaaa" and "cccc") and +(vstring between "aaaa" and "cccc") and +(bin between 0xAAAA and 0xCCCC) and +(vbin between 0xAAAA and 0xCCCC) and +(tiny between -3 and -1) and +(short between -3 and -1) and +(medium between -3 and -1) and +(long_int between -3 and -1) and +(longlong between -3 and -1) and +(utiny between 1 and 3) and +(ushort between 1 and 3) and +(umedium between 1 and 3) and +(ulong between 1 and 3) and +(ulonglong between 1 and 3) and +/* (bits between b'001' and b'011') and */ +(options between 'one' and 'three') and +(flags between 'one' and 'one,two,three') and +(date_field between '1901-01-01' and '1903-03-03') and +(year_field between '1901' and '1903') and +(time_field between '01:01:01' and '03:03:03') and +(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range medium_index medium_index 3 NULL 10 Using where with pushed condition; Using filesort +select auto from t1 where +(string between "aaaa" and "cccc") and +(vstring between "aaaa" and "cccc") and +(bin between 0xAAAA and 0xCCCC) and +(vbin between 0xAAAA and 0xCCCC) and +(tiny between -3 and -1) and +(short between -3 and -1) and +(medium between -3 and -1) and +(long_int between -3 and -1) and +(longlong between -3 and -1) and +(utiny between 1 and 3) and +(ushort between 1 and 3) and +(umedium between 1 and 3) and +(ulong between 1 and 3) and +(ulonglong between 1 and 3) and +/* (bits between b'001' and b'011') and */ +(options between 'one' and 'three') and +(flags between 'one' and 'one,two,three') and +(date_field between '1901-01-01' and '1903-03-03') and +(year_field between '1901' and '1903') and +(time_field between '01:01:01' and '03:03:03') and +(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; +auto +1 +3 +explain +select auto from t1 where +("aaaa" between string and string) and +("aaaa" between vstring and vstring) and +(0xAAAA between bin and bin) and +(0xAAAA between vbin and vbin) and +(-1 between tiny and tiny) and +(-1 between short and short) and +(-1 between medium and medium) and +(-1 between long_int and long_int) and +(-1 between longlong and longlong) and +(1 between utiny and utiny) and +(1 between ushort and ushort) and +(1 between umedium and umedium) and +(1 between ulong and ulong) and +(1 between ulonglong and ulonglong) and +/* (b'001' between bits and bits) and */ +('one' between options and options) and +('one' between flags and flags) and +('1901-01-01' between date_field and date_field) and +('1901' between year_field and year_field) and +('01:01:01' between time_field and time_field) and +('1901-01-01 01:01:01' between date_time and date_time) +order by auto; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort +select auto from t1 where +("aaaa" between string and string) and +("aaaa" between vstring and vstring) and +(0xAAAA between bin and bin) and +(0xAAAA between vbin and vbin) and +(-1 between tiny and tiny) and +(-1 between short and short) and +(-1 between medium and medium) and +(-1 between long_int and long_int) and +(-1 between longlong and longlong) and +(1 between utiny and utiny) and +(1 between ushort and ushort) and +(1 between umedium and umedium) and +(1 between ulong and ulong) and +(1 between ulonglong and ulonglong) and +/* (b'001' between bits and bits) and */ +('one' between options and options) and +('one' between flags and flags) and +('1901-01-01' between date_field and date_field) and +('1901' between year_field and year_field) and +('01:01:01' between time_field and time_field) and +('1901-01-01 01:01:01' between date_time and date_time) +order by auto; +auto +1 +explain +select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +/* (bits not between b'001' and b'011') and */ +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range medium_index medium_index 3 NULL 20 Using where with pushed condition; Using filesort +select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +/* (bits not between b'001' and b'011') and */ +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; +auto +4 +explain +select auto from t1 where +("aaaa" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +/* (b'001' not between bits and bits) and */ +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not between date_time and date_time) +order by auto; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort +select auto from t1 where +("aaaa" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +/* (b'001' not between bits and bits) and */ +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not between date_time and date_time) +order by auto; +auto +2 +3 +4 +explain +select auto from t1 where +string in("aaaa","cccc") and +vstring in("aaaa","cccc") and +bin in(0xAAAA,0xCCCC) and +vbin in(0xAAAA,0xCCCC) and +tiny in(-1,-3) and +short in(-1,-3) and +medium in(-1,-3) and +long_int in(-1,-3) and +longlong in(-1,-3) and +utiny in(1,3) and +ushort in(1,3) and +umedium in(1,3) and +ulong in(1,3) and +ulonglong in(1,3) and +/* bits in(b'001',b'011') and */ +options in('one','three') and +flags in('one','one,two,three') and +date_field in('1901-01-01','1903-03-03') and +year_field in('1901','1903') and +time_field in('01:01:01','03:03:03') and +date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range medium_index medium_index 3 NULL 20 Using where with pushed condition; Using filesort +select auto from t1 where +string in("aaaa","cccc") and +vstring in("aaaa","cccc") and +bin in(0xAAAA,0xCCCC) and +vbin in(0xAAAA,0xCCCC) and +tiny in(-1,-3) and +short in(-1,-3) and +medium in(-1,-3) and +long_int in(-1,-3) and +longlong in(-1,-3) and +utiny in(1,3) and +ushort in(1,3) and +umedium in(1,3) and +ulong in(1,3) and +ulonglong in(1,3) and +/* bits in(b'001',b'011') and */ +options in('one','three') and +flags in('one','one,two,three') and +date_field in('1901-01-01','1903-03-03') and +year_field in('1901','1903') and +time_field in('01:01:01','03:03:03') and +date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; +auto +1 +3 +explain +select auto from t1 where +"aaaa" in(string) and +"aaaa" in(vstring) and +0xAAAA in(bin) and +0xAAAA in(vbin) and +(-1 in(tiny)) and +(-1 in (short)) and +(-1 in(medium)) and +(-1 in(long_int)) and +(-1 in(longlong)) and +1 in(utiny) and +1 in(ushort) and +1 in(umedium) and +1 in(ulong) and +1 in(ulonglong) and +/* b'001' in(bits) and */ +'one' in(options) and +'one' in(flags) and +'1901-01-01' in(date_field) and +'1901' in(year_field) and +'01:01:01' in(time_field) and +'1901-01-01 01:01:01' in(date_time) +order by auto; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort +select auto from t1 where +"aaaa" in(string) and +"aaaa" in(vstring) and +0xAAAA in(bin) and +0xAAAA in(vbin) and +(-1 in(tiny)) and +(-1 in (short)) and +(-1 in(medium)) and +(-1 in(long_int)) and +(-1 in(longlong)) and +1 in(utiny) and +1 in(ushort) and +1 in(umedium) and +1 in(ulong) and +1 in(ulonglong) and +/* b'001' in(bits) and */ +'one' in(options) and +'one' in(flags) and +'1901-01-01' in(date_field) and +'1901' in(year_field) and +'01:01:01' in(time_field) and +'1901-01-01 01:01:01' in(date_time) +order by auto; +auto +1 +explain +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +/* bits not in(b'001',b'011') and */ +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range medium_index medium_index 3 NULL 30 Using where with pushed condition; Using filesort +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +/* bits not in(b'001',b'011') and */ +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; +auto +2 +4 +explain +select auto from t1 where +"aaaa" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +/* b'001' not in(bits) and */ +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not in(date_time) +order by auto; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort +select auto from t1 where +"aaaa" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +/* b'001' not in(bits) and */ +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not in(date_time) +order by auto; +auto +2 +3 +4 update t1 set medium = 17 where @@ -1139,5 +1761,10 @@ explain select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where; Using filesort +explain +select * from t3 left join t4 on t4.attr2 = t3.attr2 where t4.attr1 > 1 and t4.attr3 < 5 or t4.attr1 is null order by t4.pk1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort +1 SIMPLE t4 ALL NULL NULL NULL NULL 6 Using where set engine_condition_pushdown = @old_ecpd; DROP TABLE t1,t2,t3,t4; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index c7f980df350..99b4f0529e6 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -236,6 +236,12 @@ query_prealloc_size 8192 range_alloc_block_size 2048 transaction_alloc_block_size 8192 transaction_prealloc_size 4096 +SELECT @@version LIKE 'non-existent'; +@@version LIKE 'non-existent' +0 +SELECT @@version_compile_os LIKE 'non-existent'; +@@version_compile_os LIKE 'non-existent' +0 set big_tables=OFFF; ERROR 42000: Variable 'big_tables' can't be set to the value of 'OFFF' set big_tables="OFFF"; diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index fed3ff07a13..f2cfce9085d 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -110,3 +110,22 @@ explain extended SELECT COALESCE('a' COLLATE latin1_bin,'b'); SHOW CREATE TABLE t1; DROP TABLE t1; + +# +# Tests for bug #9939: conversion of the arguments for COALESCE and IFNULL +# + +CREATE TABLE t1 (EMPNUM INT); +INSERT INTO t1 VALUES (0), (2); +CREATE TABLE t2 (EMPNUM DECIMAL (4, 2)); +INSERT INTO t2 VALUES (0.0), (9.0); + +SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM, + t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2 + FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM; + +SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM, + t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2 + FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM; + +DROP TABLE t1,t2; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 02024adb34e..bac6e60c302 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -724,3 +724,10 @@ select ifnull(a,'') from t1; drop table t1; select repeat(_utf8'+',3) as h union select NULL; select ifnull(NULL, _utf8'string'); + +# +# Bug#10714: Inserting double value into utf8 column crashes server +# +create table t1 (a varchar(255)) default character set utf8; +insert into t1 values (1.0); +drop table t1; diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index a2ea26390ca..37556984f68 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -61,3 +61,17 @@ drop table t1; # Bug #5595 NULLIF() IS NULL returns false if NULLIF() returns NULL # SELECT NULLIF(5,5) IS NULL, NULLIF(5,5) IS NOT NULL; + +# +# Bug #9669 Ordering on IF function with FROM_UNIXTIME function fails +# +CREATE TABLE `t1` ( + `id` int(11) NOT NULL , + `date` int(10) default NULL, + `text` varchar(32) NOT NULL +); +INSERT INTO t1 VALUES (1,1110000000,'Day 1'),(2,1111000000,'Day 2'),(3,1112000000,'Day 3'); +SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord ASC; +SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord DESC; +DROP TABLE t1; + diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 80ddb205110..34da2ae1435 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -336,3 +336,9 @@ DROP TABLE t1; explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1, timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a2; + +# +# Bug #10590: %h, %I, and %l format specifies should all return results in +# the 0-11 range +# +select time_format('100:00:00', '%H %k %h %I %l'); diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test index 1d201a94c95..d090d12e81b 100644 --- a/mysql-test/t/ndb_condition_pushdown.test +++ b/mysql-test/t/ndb_condition_pushdown.test @@ -249,6 +249,202 @@ bin not like concat(0xBB, '%') and vbin not like concat(0xBB, '%') order by auto; +# BETWEEN +select auto from t1 where +(string between "aaaa" and "cccc") and +(vstring between "aaaa" and "cccc") and +(bin between 0xAAAA and 0xCCCC) and +(vbin between 0xAAAA and 0xCCCC) and +(tiny between -3 and -1) and +(short between -3 and -1) and +(medium between -3 and -1) and +(long_int between -3 and -1) and +(longlong between -3 and -1) and +(utiny between 1 and 3) and +(ushort between 1 and 3) and +(umedium between 1 and 3) and +(ulong between 1 and 3) and +(ulonglong between 1 and 3) and +(bits between b'001' and b'011') and +(options between 'one' and 'three') and +(flags between 'one' and 'one,two,three') and +(date_field between '1901-01-01' and '1903-03-03') and +(year_field between '1901' and '1903') and +(time_field between '01:01:01' and '03:03:03') and +(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +("aaaa" between string and string) and +("aaaa" between vstring and vstring) and +(0xAAAA between bin and bin) and +(0xAAAA between vbin and vbin) and +(-1 between tiny and tiny) and +(-1 between short and short) and +(-1 between medium and medium) and +(-1 between long_int and long_int) and +(-1 between longlong and longlong) and +(1 between utiny and utiny) and +(1 between ushort and ushort) and +(1 between umedium and umedium) and +(1 between ulong and ulong) and +(1 between ulonglong and ulonglong) and +(b'001' between bits and bits) and +('one' between options and options) and +('one' between flags and flags) and +('1901-01-01' between date_field and date_field) and +('1901' between year_field and year_field) and +('01:01:01' between time_field and time_field) and +('1901-01-01 01:01:01' between date_time and date_time) +order by auto; + +# NOT BETWEEN +select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +(bits not between b'001' and b'011') and +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +("aaaa" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +(b'001' not between bits and bits) and +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not between date_time and date_time) +order by auto; + +# IN +select auto from t1 where +string in("aaaa","cccc") and +vstring in("aaaa","cccc") and +bin in(0xAAAA,0xCCCC) and +vbin in(0xAAAA,0xCCCC) and +tiny in(-1,-3) and +short in(-1,-3) and +medium in(-1,-3) and +long_int in(-1,-3) and +longlong in(-1,-3) and +utiny in(1,3) and +ushort in(1,3) and +umedium in(1,3) and +ulong in(1,3) and +ulonglong in(1,3) and +bits in(b'001',b'011') and +options in('one','three') and +flags in('one','one,two,three') and +date_field in('1901-01-01','1903-03-03') and +year_field in('1901','1903') and +time_field in('01:01:01','03:03:03') and +date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +"aaaa" in(string) and +"aaaa" in(vstring) and +0xAAAA in(bin) and +0xAAAA in(vbin) and +(-1 in(tiny)) and +(-1 in(short)) and +(-1 in(medium)) and +(-1 in(long_int)) and +(-1 in(longlong)) and +1 in(utiny) and +1 in(ushort) and +1 in(umedium) and +1 in(ulong) and +1 in(ulonglong) and +b'001' in(bits) and +'one' in(options) and +'one' in(flags) and +'1901-01-01' in(date_field) and +'1901' in(year_field) and +'01:01:01' in(time_field) and +'1901-01-01 01:01:01' in(date_time) +order by auto; + +# NOT IN +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +bits not in(b'001',b'011') and +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +"aaaa" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +b'001' not in(bits) and +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not in(date_time) +order by auto; + # Various tests select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1; select * from t2 where attr3 is not null and attr1 > 2 order by pk1; @@ -955,6 +1151,402 @@ bin not like concat(0xBB, '%') and vbin not like concat(0xBB, '%') order by auto; +# BETWEEN +explain +select auto from t1 where +(string between "aaaa" and "cccc") and +(vstring between "aaaa" and "cccc") and +(bin between 0xAAAA and 0xCCCC) and +(vbin between 0xAAAA and 0xCCCC) and +(tiny between -3 and -1) and +(short between -3 and -1) and +(medium between -3 and -1) and +(long_int between -3 and -1) and +(longlong between -3 and -1) and +(utiny between 1 and 3) and +(ushort between 1 and 3) and +(umedium between 1 and 3) and +(ulong between 1 and 3) and +(ulonglong between 1 and 3) and +/* (bits between b'001' and b'011') and */ +(options between 'one' and 'three') and +(flags between 'one' and 'one,two,three') and +(date_field between '1901-01-01' and '1903-03-03') and +(year_field between '1901' and '1903') and +(time_field between '01:01:01' and '03:03:03') and +(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +(string between "aaaa" and "cccc") and +(vstring between "aaaa" and "cccc") and +(bin between 0xAAAA and 0xCCCC) and +(vbin between 0xAAAA and 0xCCCC) and +(tiny between -3 and -1) and +(short between -3 and -1) and +(medium between -3 and -1) and +(long_int between -3 and -1) and +(longlong between -3 and -1) and +(utiny between 1 and 3) and +(ushort between 1 and 3) and +(umedium between 1 and 3) and +(ulong between 1 and 3) and +(ulonglong between 1 and 3) and +/* (bits between b'001' and b'011') and */ +(options between 'one' and 'three') and +(flags between 'one' and 'one,two,three') and +(date_field between '1901-01-01' and '1903-03-03') and +(year_field between '1901' and '1903') and +(time_field between '01:01:01' and '03:03:03') and +(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; + +explain +select auto from t1 where +("aaaa" between string and string) and +("aaaa" between vstring and vstring) and +(0xAAAA between bin and bin) and +(0xAAAA between vbin and vbin) and +(-1 between tiny and tiny) and +(-1 between short and short) and +(-1 between medium and medium) and +(-1 between long_int and long_int) and +(-1 between longlong and longlong) and +(1 between utiny and utiny) and +(1 between ushort and ushort) and +(1 between umedium and umedium) and +(1 between ulong and ulong) and +(1 between ulonglong and ulonglong) and +/* (b'001' between bits and bits) and */ +('one' between options and options) and +('one' between flags and flags) and +('1901-01-01' between date_field and date_field) and +('1901' between year_field and year_field) and +('01:01:01' between time_field and time_field) and +('1901-01-01 01:01:01' between date_time and date_time) +order by auto; + +select auto from t1 where +("aaaa" between string and string) and +("aaaa" between vstring and vstring) and +(0xAAAA between bin and bin) and +(0xAAAA between vbin and vbin) and +(-1 between tiny and tiny) and +(-1 between short and short) and +(-1 between medium and medium) and +(-1 between long_int and long_int) and +(-1 between longlong and longlong) and +(1 between utiny and utiny) and +(1 between ushort and ushort) and +(1 between umedium and umedium) and +(1 between ulong and ulong) and +(1 between ulonglong and ulonglong) and +/* (b'001' between bits and bits) and */ +('one' between options and options) and +('one' between flags and flags) and +('1901-01-01' between date_field and date_field) and +('1901' between year_field and year_field) and +('01:01:01' between time_field and time_field) and +('1901-01-01 01:01:01' between date_time and date_time) +order by auto; + +# NOT BETWEEN +explain +select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +/* (bits not between b'001' and b'011') and */ +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +/* (bits not between b'001' and b'011') and */ +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; + +explain +select auto from t1 where +("aaaa" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +/* (b'001' not between bits and bits) and */ +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not between date_time and date_time) +order by auto; + +select auto from t1 where +("aaaa" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +/* (b'001' not between bits and bits) and */ +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not between date_time and date_time) +order by auto; + +# IN +explain +select auto from t1 where +string in("aaaa","cccc") and +vstring in("aaaa","cccc") and +bin in(0xAAAA,0xCCCC) and +vbin in(0xAAAA,0xCCCC) and +tiny in(-1,-3) and +short in(-1,-3) and +medium in(-1,-3) and +long_int in(-1,-3) and +longlong in(-1,-3) and +utiny in(1,3) and +ushort in(1,3) and +umedium in(1,3) and +ulong in(1,3) and +ulonglong in(1,3) and +/* bits in(b'001',b'011') and */ +options in('one','three') and +flags in('one','one,two,three') and +date_field in('1901-01-01','1903-03-03') and +year_field in('1901','1903') and +time_field in('01:01:01','03:03:03') and +date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +string in("aaaa","cccc") and +vstring in("aaaa","cccc") and +bin in(0xAAAA,0xCCCC) and +vbin in(0xAAAA,0xCCCC) and +tiny in(-1,-3) and +short in(-1,-3) and +medium in(-1,-3) and +long_int in(-1,-3) and +longlong in(-1,-3) and +utiny in(1,3) and +ushort in(1,3) and +umedium in(1,3) and +ulong in(1,3) and +ulonglong in(1,3) and +/* bits in(b'001',b'011') and */ +options in('one','three') and +flags in('one','one,two,three') and +date_field in('1901-01-01','1903-03-03') and +year_field in('1901','1903') and +time_field in('01:01:01','03:03:03') and +date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; + +explain +select auto from t1 where +"aaaa" in(string) and +"aaaa" in(vstring) and +0xAAAA in(bin) and +0xAAAA in(vbin) and +(-1 in(tiny)) and +(-1 in (short)) and +(-1 in(medium)) and +(-1 in(long_int)) and +(-1 in(longlong)) and +1 in(utiny) and +1 in(ushort) and +1 in(umedium) and +1 in(ulong) and +1 in(ulonglong) and +/* b'001' in(bits) and */ +'one' in(options) and +'one' in(flags) and +'1901-01-01' in(date_field) and +'1901' in(year_field) and +'01:01:01' in(time_field) and +'1901-01-01 01:01:01' in(date_time) +order by auto; + +select auto from t1 where +"aaaa" in(string) and +"aaaa" in(vstring) and +0xAAAA in(bin) and +0xAAAA in(vbin) and +(-1 in(tiny)) and +(-1 in (short)) and +(-1 in(medium)) and +(-1 in(long_int)) and +(-1 in(longlong)) and +1 in(utiny) and +1 in(ushort) and +1 in(umedium) and +1 in(ulong) and +1 in(ulonglong) and +/* b'001' in(bits) and */ +'one' in(options) and +'one' in(flags) and +'1901-01-01' in(date_field) and +'1901' in(year_field) and +'01:01:01' in(time_field) and +'1901-01-01 01:01:01' in(date_time) +order by auto; + +# NOT IN +explain +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +/* bits not in(b'001',b'011') and */ +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +/* bits not in(b'001',b'011') and */ +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; + +explain +select auto from t1 where +"aaaa" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +/* b'001' not in(bits) and */ +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not in(date_time) +order by auto; + +select auto from t1 where +"aaaa" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +/* b'001' not in(bits) and */ +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not in(date_time) +order by auto; + # Update test update t1 set medium = 17 @@ -1044,6 +1636,8 @@ explain select auto from t1 where string = "aaaa" collate latin1_general_ci order by auto; explain select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1; +explain +select * from t3 left join t4 on t4.attr2 = t3.attr2 where t4.attr1 > 1 and t4.attr3 < 5 or t4.attr1 is null order by t4.pk1; set engine_condition_pushdown = @old_ecpd; DROP TABLE t1,t2,t3,t4; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 9e8a7a1b56f..f8d833b6b73 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -130,6 +130,13 @@ set @@query_alloc_block_size=default, @@query_prealloc_size=default; set transaction_alloc_block_size=default, @@transaction_prealloc_size=default; show variables like '%alloc%'; +# +# Bug #10904 Illegal mix of collations between +# a system variable and a constant +# +SELECT @@version LIKE 'non-existent'; +SELECT @@version_compile_os LIKE 'non-existent'; + # The following should give errors --error 1231 diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 2308536cd37..feb9c77a5b9 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -184,10 +184,18 @@ static void test_key_cache(KEY_CACHE *keycache, static FILE *keycache_debug_log=NULL; static void keycache_debug_print _VARARGS((const char *fmt,...)); #define KEYCACHE_DEBUG_OPEN \ - if (!keycache_debug_log) keycache_debug_log=fopen(KEYCACHE_DEBUG_LOG, "w") + if (!keycache_debug_log) \ + { \ + keycache_debug_log= fopen(KEYCACHE_DEBUG_LOG, "w"); \ + (void) setvbuf(keycache_debug_log, NULL, _IOLBF, BUFSIZ); \ + } #define KEYCACHE_DEBUG_CLOSE \ - if (keycache_debug_log) { fclose(keycache_debug_log); keycache_debug_log=0; } + if (keycache_debug_log) \ + { \ + fclose(keycache_debug_log); \ + keycache_debug_log= 0; \ + } #else #define KEYCACHE_DEBUG_OPEN #define KEYCACHE_DEBUG_CLOSE @@ -213,7 +221,7 @@ static long keycache_thread_id; #define KEYCACHE_THREAD_TRACE_BEGIN(l) \ { struct st_my_thread_var *thread_var= my_thread_var; \ - keycache_thread_id= my_thread_var->id; \ + keycache_thread_id= thread_var->id; \ KEYCACHE_DBUG_PRINT(l,("[thread %ld",keycache_thread_id)) } #define KEYCACHE_THREAD_TRACE_END(l) \ @@ -240,12 +248,10 @@ static int keycache_pthread_cond_wait(pthread_cond_t *cond, static int keycache_pthread_mutex_lock(pthread_mutex_t *mutex); static void keycache_pthread_mutex_unlock(pthread_mutex_t *mutex); static int keycache_pthread_cond_signal(pthread_cond_t *cond); -static int keycache_pthread_cond_broadcast(pthread_cond_t *cond); #else #define keycache_pthread_mutex_lock pthread_mutex_lock #define keycache_pthread_mutex_unlock pthread_mutex_unlock #define keycache_pthread_cond_signal pthread_cond_signal -#define keycache_pthread_cond_broadcast pthread_cond_broadcast #endif /* defined(KEYCACHE_DEBUG) */ static uint next_power(uint value) @@ -508,6 +514,8 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, keycache->can_be_used= 0; while (keycache->cnt_for_resize_op) { + KEYCACHE_DBUG_PRINT("resize_key_cache: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -520,7 +528,11 @@ finish: unlink_from_queue(wqueue, thread); /* Signal for the next resize request to proceeed if any */ if (wqueue->last_thread) + { + KEYCACHE_DBUG_PRINT("resize_key_cache: signal", + ("thread %ld", wqueue->last_thread->next->id)); keycache_pthread_cond_signal(&wqueue->last_thread->next->suspend); + } keycache_pthread_mutex_unlock(&keycache->cache_lock); return blocks; } @@ -544,7 +556,11 @@ static inline void dec_counter_for_resize_op(KEY_CACHE *keycache) struct st_my_thread_var *last_thread; if (!--keycache->cnt_for_resize_op && (last_thread= keycache->resize_queue.last_thread)) + { + KEYCACHE_DBUG_PRINT("dec_counter_for_resize_op: signal", + ("thread %ld", last_thread->next->id)); keycache_pthread_cond_signal(&last_thread->next->suspend); + } } /* @@ -761,8 +777,8 @@ static void release_queue(KEYCACHE_WQUEUE *wqueue) do { thread=next; - keycache_pthread_cond_signal(&thread->suspend); KEYCACHE_DBUG_PRINT("release_queue: signal", ("thread %ld", thread->id)); + keycache_pthread_cond_signal(&thread->suspend); next=thread->next; thread->next= NULL; } @@ -876,7 +892,8 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, BLOCK_LINK **pins; KEYCACHE_DBUG_ASSERT(! (block->hash_link && block->hash_link->requests)); - if (!hot && keycache->waiting_for_block.last_thread) { + if (!hot && keycache->waiting_for_block.last_thread) + { /* Signal that in the LRU warm sub-chain an available block has appeared */ struct st_my_thread_var *last_thread= keycache->waiting_for_block.last_thread; @@ -894,6 +911,7 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, */ if ((HASH_LINK *) thread->opt_info == hash_link) { + KEYCACHE_DBUG_PRINT("link_block: signal", ("thread %ld", thread->id)); keycache_pthread_cond_signal(&thread->suspend); unlink_from_queue(&keycache->waiting_for_block, thread); block->requests++; @@ -1000,11 +1018,10 @@ static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count) linking it to the LRU chain if it's the last request SYNOPSIS - - unreg_block() - keycache pointer to a key cache data structure - block pointer to the block to link to the LRU chain - at_end <-> to link the block at the end of the LRU chain + unreg_request() + keycache pointer to a key cache data structure + block pointer to the block to link to the LRU chain + at_end <-> to link the block at the end of the LRU chain RETURN VALUE none @@ -1086,6 +1103,9 @@ static inline void wait_for_readers(KEY_CACHE *keycache, BLOCK_LINK *block) struct st_my_thread_var *thread= my_thread_var; while (block->hash_link->requests) { + KEYCACHE_DBUG_PRINT("wait_for_readers: wait", + ("suspend thread %ld block %u", + thread->id, BLOCK_NUMBER(block))); block->condvar= &thread->suspend; keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); block->condvar= NULL; @@ -1143,6 +1163,7 @@ static void unlink_hash(KEY_CACHE *keycache, HASH_LINK *hash_link) */ if (page->file == hash_link->file && page->filepos == hash_link->diskpos) { + KEYCACHE_DBUG_PRINT("unlink_hash: signal", ("thread %ld", thread->id)); keycache_pthread_cond_signal(&thread->suspend); unlink_from_queue(&keycache->waiting_for_hash_link, thread); } @@ -1225,6 +1246,8 @@ restart: page.filepos= filepos; thread->opt_info= (void *) &page; link_into_queue(&keycache->waiting_for_hash_link, thread); + KEYCACHE_DBUG_PRINT("get_hash_link: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); thread->opt_info= NULL; @@ -1343,6 +1366,8 @@ restart: add_to_queue(&block->wqueue[COND_FOR_SAVED], thread); do { + KEYCACHE_DBUG_PRINT("find_key_block: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -1360,7 +1385,9 @@ restart: /* This is a request for a page to be removed from cache */ KEYCACHE_DBUG_PRINT("find_key_block", - ("request for old page in block %u",BLOCK_NUMBER(block))); + ("request for old page in block %u " + "wrmode: %d block->status: %d", + BLOCK_NUMBER(block), wrmode, block->status)); /* Only reading requests can proceed until the old dirty page is flushed, all others are to be suspended, then resubmitted @@ -1379,6 +1406,8 @@ restart: /* Wait until the request can be resubmitted */ do { + KEYCACHE_DBUG_PRINT("find_key_block: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -1448,6 +1477,8 @@ restart: link_into_queue(&keycache->waiting_for_block, thread); do { + KEYCACHE_DBUG_PRINT("find_key_block: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -1528,9 +1559,13 @@ restart: else { /* This is for secondary requests for a new page only */ - page_status= block->hash_link == hash_link && - (block->status & BLOCK_READ) ? - PAGE_READ : PAGE_WAIT_TO_BE_READ; + KEYCACHE_DBUG_PRINT("find_key_block", + ("block->hash_link: %p hash_link: %p " + "block->status: %u", block->hash_link, + hash_link, block->status )); + page_status= (((block->hash_link == hash_link) && + (block->status & BLOCK_READ)) ? + PAGE_READ : PAGE_WAIT_TO_BE_READ); } } keycache->global_cache_read++; @@ -1538,17 +1573,22 @@ restart: else { reg_requests(keycache, block, 1); - page_status = block->hash_link == hash_link && - (block->status & BLOCK_READ) ? - PAGE_READ : PAGE_WAIT_TO_BE_READ; + KEYCACHE_DBUG_PRINT("find_key_block", + ("block->hash_link: %p hash_link: %p " + "block->status: %u", block->hash_link, + hash_link, block->status )); + page_status= (((block->hash_link == hash_link) && + (block->status & BLOCK_READ)) ? + PAGE_READ : PAGE_WAIT_TO_BE_READ); } } KEYCACHE_DBUG_ASSERT(page_status != -1); *page_st=page_status; KEYCACHE_DBUG_PRINT("find_key_block", - ("fd: %u pos %lu page_status %lu", - (uint) file,(ulong) filepos,(uint) page_status)); + ("fd: %u pos %lu block->status %u page_status %lu", + (uint) file, (ulong) filepos, block->status, + (uint) page_status)); #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) DBUG_EXECUTE("check_keycache2", @@ -1604,6 +1644,10 @@ static void read_block(KEY_CACHE *keycache, /* Page is not in buffer yet, is to be read from disk */ keycache_pthread_mutex_unlock(&keycache->cache_lock); + /* + Here other threads may step in and register as secondary readers. + They will register in block->wqueue[COND_FOR_REQUESTED]. + */ got_length= my_pread(block->hash_link->file, block->buffer, read_length, block->hash_link->diskpos, MYF(0)); keycache_pthread_mutex_lock(&keycache->cache_lock); @@ -1634,6 +1678,8 @@ static void read_block(KEY_CACHE *keycache, add_to_queue(&block->wqueue[COND_FOR_REQUESTED], thread); do { + KEYCACHE_DBUG_PRINT("read_block: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -1855,6 +1901,10 @@ int key_cache_insert(KEY_CACHE *keycache, /* The requested page is to be read into the block buffer */ #if !defined(SERIALIZED_READ_FROM_CACHE) keycache_pthread_mutex_unlock(&keycache->cache_lock); + /* + Here other threads may step in and register as secondary readers. + They will register in block->wqueue[COND_FOR_REQUESTED]. + */ #endif /* Copy data from buff */ @@ -1865,9 +1915,15 @@ int key_cache_insert(KEY_CACHE *keycache, #if !defined(SERIALIZED_READ_FROM_CACHE) keycache_pthread_mutex_lock(&keycache->cache_lock); + /* Here we are alone again. */ #endif block->status= BLOCK_READ; block->length= read_length+offset; + KEYCACHE_DBUG_PRINT("key_cache_insert", + ("primary request: new page in cache")); + /* Signal that all pending requests for this now can be processed. */ + if (block->wqueue[COND_FOR_REQUESTED].last_thread) + release_queue(&block->wqueue[COND_FOR_REQUESTED]); } remove_reader(block); @@ -2074,9 +2130,16 @@ static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block) { KEYCACHE_THREAD_TRACE("free block"); KEYCACHE_DBUG_PRINT("free_block", - ("block %u to be freed",BLOCK_NUMBER(block))); + ("block %u to be freed, hash_link %p", + BLOCK_NUMBER(block), block->hash_link)); if (block->hash_link) { + /* + While waiting for readers to finish, new readers might request the + block. But since we set block->status|= BLOCK_REASSIGNED, they + will wait on block->wqueue[COND_FOR_SAVED]. They must be signalled + later. + */ block->status|= BLOCK_REASSIGNED; wait_for_readers(keycache, block); unlink_hash(keycache, block->hash_link); @@ -2102,6 +2165,10 @@ static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block) keycache->free_block_list= block; /* Keep track of the number of currently unused blocks. */ keycache->blocks_unused++; + + /* All pending requests for this page must be resubmitted. */ + if (block->wqueue[COND_FOR_SAVED].last_thread) + release_queue(&block->wqueue[COND_FOR_SAVED]); } @@ -2334,6 +2401,8 @@ restart: add_to_queue(&block->wqueue[COND_FOR_SAVED], thread); do { + KEYCACHE_DBUG_PRINT("flush_key_blocks_int: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -2685,14 +2754,6 @@ static int keycache_pthread_cond_signal(pthread_cond_t *cond) } -static int keycache_pthread_cond_broadcast(pthread_cond_t *cond) -{ - int rc; - KEYCACHE_THREAD_TRACE("signal"); - rc= pthread_cond_broadcast(cond); - return rc; -} - #if defined(KEYCACHE_DEBUG_LOG) diff --git a/sql/field.cc b/sql/field.cc index ed9d3e1ecd9..08a785b2780 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5859,31 +5859,32 @@ int Field_str::store(double nr) char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; uint length; bool use_scientific_notation= TRUE; + uint char_length= field_length / charset()->mbmaxlen; /* Check fabs(nr) against longest value that can be stored in field, which depends on whether the value is < 1 or not, and negative or not */ double anr= fabs(nr); int neg= (nr < 0.0) ? 1 : 0; - if (field_length > 4 && field_length < 32 && - (anr < 1.0 ? anr > 1/(log_10[max(0,(int) field_length-neg-2)]) /* -2 for "0." */ - : anr < log_10[field_length-neg]-1)) + if (char_length > 4 && char_length < 32 && + (anr < 1.0 ? anr > 1/(log_10[max(0,(int) char_length-neg-2)]) /* -2 for "0." */ + : anr < log_10[char_length-neg]-1)) use_scientific_notation= FALSE; length= (uint) my_sprintf(buff, (buff, "%-.*g", (use_scientific_notation ? - max(0, (int)field_length-neg-5) : - field_length), + max(0, (int)char_length-neg-5) : + char_length), nr)); /* +1 below is because "precision" in %g above means the max. number of significant digits, not the output width. Thus the width can be larger than number of significant digits by 1 (for decimal point) - the test for field_length < 5 is for extreme cases, + the test for char_length < 5 is for extreme cases, like inserting 500.0 in char(1) */ - DBUG_ASSERT(field_length < 5 || length <= field_length+1); + DBUG_ASSERT(char_length < 5 || length <= char_length+1); return store((const char *) buff, length, charset()); } diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 5f4027c1a88..d2652b242ce 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5964,11 +5964,14 @@ ha_innobase::external_lock( TABLES if AUTOCOMMIT=1. It does not make much sense to acquire an InnoDB table lock if it is released immediately at the end of LOCK TABLES, and InnoDB's table locks in that case cause - VERY easily deadlocks. */ + VERY easily deadlocks. We do not set InnoDB table locks when + MySQL sets them at the start of a stored procedure call + (MySQL does have thd->in_lock_tables TRUE there). */ if (prebuilt->select_lock_type != LOCK_NONE) { if (thd->in_lock_tables && + thd->lex->sql_command != SQLCOM_CALL && thd->variables.innodb_table_locks && (thd->options & OPTION_NOT_AUTOCOMMIT)) { @@ -6479,11 +6482,21 @@ ha_innobase::store_lock( if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { + /* Starting from 5.0.7, we weaken also the table locks + set at the start of a MySQL stored procedure call, just like + we weaken the locks set at the start of an SQL statement. + MySQL does set thd->in_lock_tables TRUE there, but in reality + we do not need table locks to make the execution of a + single transaction stored procedure call deterministic + (if it does not use a consistent read). */ + /* If we are not doing a LOCK TABLE or DISCARD/IMPORT TABLESPACE or TRUNCATE TABLE, then allow multiple writers */ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && - lock_type <= TL_WRITE) && !thd->in_lock_tables + lock_type <= TL_WRITE) + && (!thd->in_lock_tables + || thd->lex->sql_command == SQLCOM_CALL) && !thd->tablespace_op && thd->lex->sql_command != SQLCOM_TRUNCATE && thd->lex->sql_command != SQLCOM_CREATE_TABLE) { @@ -6497,7 +6510,10 @@ ha_innobase::store_lock( to t2. Convert the lock to a normal read lock to allow concurrent inserts to t2. */ - if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) { + if (lock_type == TL_READ_NO_INSERT + && (!thd->in_lock_tables + || thd->lex->sql_command == SQLCOM_CALL)) { + lock_type = TL_READ; } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index fc21a634b00..2bd0e992ae4 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -6077,572 +6077,778 @@ void ndb_serialize_cond(const Item *item, void *arg) context->supported= FALSE; break; } - + DBUG_VOID_RETURN; } if (context->supported) { - Ndb_cond_stack *ndb_stack= context->stack_ptr; - Ndb_cond *prev_cond= context->cond_ptr; - Ndb_cond *curr_cond= context->cond_ptr= new Ndb_cond(); - if (!ndb_stack->ndb_cond) - ndb_stack->ndb_cond= curr_cond; - curr_cond->prev= prev_cond; - if (prev_cond) prev_cond->next= curr_cond; - - // Check for end of AND/OR expression - if (!item) + Ndb_rewrite_context *rewrite_context= context->rewrite_stack; + const Item_func *func_item; + // Check if we are rewriting some unsupported function call + if (rewrite_context && + (func_item= rewrite_context->func_item) && + rewrite_context->count++ == 0) { - // End marker for condition group - DBUG_PRINT("info", ("End of condition group")); - curr_cond->ndb_item= new Ndb_item(NDB_END_COND); - } - else - switch(item->type()) { - case(Item::FIELD_ITEM): { - Item_field *field_item= (Item_field *) item; - Field *field= field_item->field; - enum_field_types type= field->type(); + switch(func_item->functype()) { + case(Item_func::BETWEEN): /* - Check that the field is part of the table of the handler - instance and that we expect a field with of this result type. + Rewrite + <field>|<const> BETWEEN <const1>|<field1> AND <const2>|<field2> + to <field>|<const> > <const1>|<field1> AND + <field>|<const> < <const2>|<field2> + or actually in prefix format + BEGIN(AND) GT(<field>|<const>, <const1>|<field1>), + LT(<field>|<const>, <const2>|<field2>), END() */ - if (context->table == field->table) - { - const NDBTAB *tab= (const NDBTAB *) context->ndb_table; - DBUG_PRINT("info", ("FIELD_ITEM")); - DBUG_PRINT("info", ("table %s", tab->getName())); - DBUG_PRINT("info", ("column %s", field->field_name)); - DBUG_PRINT("info", ("result type %d", field->result_type())); - - // Check that we are expecting a field and with the correct - // result type - if(context->expecting(Item::FIELD_ITEM) && - (context->expecting_field_result(field->result_type()) || - // Date and year can be written as strings - (type == MYSQL_TYPE_TIME || - type == MYSQL_TYPE_DATE || - type == MYSQL_TYPE_YEAR || - type == MYSQL_TYPE_DATETIME) - ? context->expecting_field_result(STRING_RESULT) : true) - // Bit fields no yet supported in scan filter - && type != MYSQL_TYPE_BIT) + case(Item_func::IN_FUNC): { + /* + Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..) + to <field>|<const> = <const1>|<field1> OR + <field> = <const2>|<field2> ... + or actually in prefix format + BEGIN(OR) EQ(<field>|<const>, <const1><field1>), + EQ(<field>|<const>, <const2>|<field2>), ... END() + Each part of the disjunction is added for each call + to ndb_serialize_cond and end of rewrite statement + is wrapped in end of ndb_serialize_cond + */ + if (context->expecting(item->type())) + { + // This is the <field>|<const> item, save it in the rewrite context + rewrite_context->left_hand_item= item; + if (item->type() == Item::FUNC_ITEM) { - const NDBCOL *col= tab->getColumn(field->field_name); - DBUG_ASSERT(col); - curr_cond->ndb_item= new Ndb_item(field, col->getColumnNo()); - context->dont_expect(Item::FIELD_ITEM); - context->expect_no_field_result(); - if (context->expect_mask) + Item_func *func_item= (Item_func *) item; + if (func_item->functype() == Item_func::UNKNOWN_FUNC && + func_item->const_item()) { - // We have not seen second argument yet - if (type == MYSQL_TYPE_TIME || - type == MYSQL_TYPE_DATE || - type == MYSQL_TYPE_YEAR || - type == MYSQL_TYPE_DATETIME) - { - context->expect_only(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - } - else - switch(field->result_type()) { - case(STRING_RESULT): - // Expect char string or binary string - context->expect_only(Item::STRING_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect_collation(field_item->collation.collation); - break; - case(REAL_RESULT): - context->expect_only(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - break; - case(INT_RESULT): - context->expect_only(Item::INT_ITEM); - context->expect(Item::VARBIN_ITEM); - break; - case(DECIMAL_RESULT): - context->expect_only(Item::DECIMAL_ITEM); - context->expect(Item::REAL_ITEM); - break; - default: - break; - } + // Skip any arguments since we will evaluate function instead + DBUG_PRINT("info", ("Skip until end of arguments marker")); + context->skip= func_item->argument_count(); } else { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - // Check that field and string constant collations are the same - if ((field->result_type() == STRING_RESULT) && - !context->expecting_collation(item->collation.collation)) - { - DBUG_PRINT("info", ("Found non-matching collation %s", - item->collation.collation->name)); - context->supported= FALSE; - } + DBUG_PRINT("info", ("Found unsupported functional expression in BETWEEN|IN")); + context->supported= FALSE; + DBUG_VOID_RETURN; + } - break; } } - DBUG_PRINT("info", ("Was not expecting field of type %u", - field->result_type())); - context->supported= FALSE; - break; - } - case(Item::FUNC_ITEM): { - Item_func *func_item= (Item_func *) item; - // Check that we expect a function or functional expression here - if (context->expecting(Item::FUNC_ITEM) || - func_item->functype() == Item_func::UNKNOWN_FUNC) - context->expect_nothing(); else { - // Did not expect function here + // Non-supported BETWEEN|IN expression + DBUG_PRINT("info", ("Found unexpected item of type %u in BETWEEN|IN", + item->type())); context->supported= FALSE; - break; + DBUG_VOID_RETURN; } - + break; + } + default: + context->supported= FALSE; + break; + } + DBUG_VOID_RETURN; + } + else + { + Ndb_cond_stack *ndb_stack= context->stack_ptr; + Ndb_cond *prev_cond= context->cond_ptr; + Ndb_cond *curr_cond= context->cond_ptr= new Ndb_cond(); + if (!ndb_stack->ndb_cond) + ndb_stack->ndb_cond= curr_cond; + curr_cond->prev= prev_cond; + if (prev_cond) prev_cond->next= curr_cond; + // Check if we are rewriting some unsupported function call + if (context->rewrite_stack) + { + Ndb_rewrite_context *rewrite_context= context->rewrite_stack; + const Item_func *func_item= rewrite_context->func_item; switch(func_item->functype()) { - case(Item_func::EQ_FUNC): { - DBUG_PRINT("info", ("EQ_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::NE_FUNC): { - DBUG_PRINT("info", ("NE_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::LT_FUNC): { - DBUG_PRINT("info", ("LT_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::LE_FUNC): { - DBUG_PRINT("info", ("LE_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::GE_FUNC): { - DBUG_PRINT("info", ("GE_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::GT_FUNC): { - DBUG_PRINT("info", ("GT_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::LIKE_FUNC): { - DBUG_PRINT("info", ("LIKE_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - break; - } - case(Item_func::NOTLIKE_FUNC): { - DBUG_PRINT("info", ("NOTLIKE_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - break; - } - case(Item_func::ISNULL_FUNC): { - DBUG_PRINT("info", ("ISNULL_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); + case(Item_func::BETWEEN): { + /* + Rewrite + <field>|<const> BETWEEN <const1>|<field1> AND <const2>|<field2> + to <field>|<const> > <const1>|<field1> AND + <field>|<const> < <const2>|<field2> + or actually in prefix format + BEGIN(AND) GT(<field>|<const>, <const1>|<field1>), + LT(<field>|<const>, <const2>|<field2>), END() + */ + if (rewrite_context->count == 2) + { + // Lower limit of BETWEEN + DBUG_PRINT("info", ("GE_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::GE_FUNC, 2); + } + else if (rewrite_context->count == 3) + { + // Upper limit of BETWEEN + DBUG_PRINT("info", ("LE_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::LE_FUNC, 2); + } + else + { + // Illegal BETWEEN expression + DBUG_PRINT("info", ("Illegal BETWEEN expression")); + context->supported= FALSE; + DBUG_VOID_RETURN; + } break; } - case(Item_func::ISNOTNULL_FUNC): { - DBUG_PRINT("info", ("ISNOTNULL_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); + case(Item_func::IN_FUNC): { + /* + Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..) + to <field>|<const> = <const1>|<field1> OR + <field> = <const2>|<field2> ... + or actually in prefix format + BEGIN(OR) EQ(<field>|<const>, <const1><field1>), + EQ(<field>|<const>, <const2>|<field2>), ... END() + Each part of the disjunction is added for each call + to ndb_serialize_cond and end of rewrite statement + is wrapped in end of ndb_serialize_cond + */ + DBUG_PRINT("info", ("EQ_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::EQ_FUNC, 2); break; } - case(Item_func::NOT_FUNC): { - DBUG_PRINT("info", ("NOT_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - break; + default: + context->supported= FALSE; } - case(Item_func::UNKNOWN_FUNC): { - DBUG_PRINT("info", ("UNKNOWN_FUNC %s", - func_item->const_item()?"const":"")); - DBUG_PRINT("info", ("result type %d", func_item->result_type())); - if (func_item->const_item()) - switch(func_item->result_type()) { - case(STRING_RESULT): { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::STRING_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) + // Handle left hand <field>|<const> + context->rewrite_stack= NULL; // Disable rewrite mode + context->expect_only(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + context->expect(Item::INT_ITEM); + context->expect(Item::STRING_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FUNC_ITEM); + ndb_serialize_cond(rewrite_context->left_hand_item, arg); + context->skip= 0; // Any FUNC_ITEM expression has already been parsed + context->rewrite_stack= rewrite_context; // Enable rewrite mode + if (!context->supported) + DBUG_VOID_RETURN; + + prev_cond= context->cond_ptr; + curr_cond= context->cond_ptr= new Ndb_cond(); + prev_cond->next= curr_cond; + } + + // Check for end of AND/OR expression + if (!item) + { + // End marker for condition group + DBUG_PRINT("info", ("End of condition group")); + curr_cond->ndb_item= new Ndb_item(NDB_END_COND); + } + else + switch(item->type()) { + case(Item::FIELD_ITEM): { + Item_field *field_item= (Item_field *) item; + Field *field= field_item->field; + enum_field_types type= field->type(); + /* + Check that the field is part of the table of the handler + instance and that we expect a field with of this result type. + */ + if (context->table == field->table) + { + const NDBTAB *tab= (const NDBTAB *) context->ndb_table; + DBUG_PRINT("info", ("FIELD_ITEM")); + DBUG_PRINT("info", ("table %s", tab->getName())); + DBUG_PRINT("info", ("column %s", field->field_name)); + DBUG_PRINT("info", ("result type %d", field->result_type())); + + // Check that we are expecting a field and with the correct + // result type + if (context->expecting(Item::FIELD_ITEM) && + (context->expecting_field_result(field->result_type()) || + // Date and year can be written as strings + ((type == MYSQL_TYPE_TIME || + type == MYSQL_TYPE_DATE || + type == MYSQL_TYPE_YEAR || + type == MYSQL_TYPE_DATETIME) + ? context->expecting_field_result(STRING_RESULT) : true)) && + // Bit fields no yet supported in scan filter + type != MYSQL_TYPE_BIT) + { + const NDBCOL *col= tab->getColumn(field->field_name); + DBUG_ASSERT(col); + curr_cond->ndb_item= new Ndb_item(field, col->getColumnNo()); + context->dont_expect(Item::FIELD_ITEM); + context->expect_no_field_result(); + if (context->expect_mask) { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(STRING_RESULT); - context->expect_collation(func_item->collation.collation); + // We have not seen second argument yet + if (type == MYSQL_TYPE_TIME || + type == MYSQL_TYPE_DATE || + type == MYSQL_TYPE_YEAR || + type == MYSQL_TYPE_DATETIME) + { + context->expect_only(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + } + else + switch(field->result_type()) { + case(STRING_RESULT): + // Expect char string or binary string + context->expect_only(Item::STRING_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect_collation(field_item->collation.collation); + break; + case(REAL_RESULT): + context->expect_only(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + break; + case(INT_RESULT): + context->expect_only(Item::INT_ITEM); + context->expect(Item::VARBIN_ITEM); + break; + case(DECIMAL_RESULT): + context->expect_only(Item::DECIMAL_ITEM); + context->expect(Item::REAL_ITEM); + break; + default: + break; + } } else { // Expect another logical expression context->expect_only(Item::FUNC_ITEM); context->expect(Item::COND_ITEM); - // Check that string result have correct collation - if (!context->expecting_collation(item->collation.collation)) + // Check that field and string constant collations are the same + if ((field->result_type() == STRING_RESULT) && + !context->expecting_collation(item->collation.collation) + && type != MYSQL_TYPE_TIME + && type != MYSQL_TYPE_DATE + && type != MYSQL_TYPE_YEAR + && type != MYSQL_TYPE_DATETIME) { DBUG_PRINT("info", ("Found non-matching collation %s", - item->collation.collation->name)); - context->supported= FALSE; + item->collation.collation->name)); + context->supported= FALSE; } } - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); - break; - } - case(REAL_RESULT): { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::REAL_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(REAL_RESULT); - } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - } - - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); break; } - case(INT_RESULT): { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::INT_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(INT_RESULT); - } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - } - - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); - break; - } - case(DECIMAL_RESULT): { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::DECIMAL_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(DECIMAL_RESULT); - } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - } - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); - break; - } - default: - break; + else + { + DBUG_PRINT("info", ("Was not expecting field of type %u", + field->result_type())); + context->supported= FALSE; } + } else - // Function does not return constant expression + { + DBUG_PRINT("info", ("Was not expecting field from table %s(%s)", + context->table->s->table_name, + field->table->s->table_name)); context->supported= FALSE; + } break; } - default: { - DBUG_PRINT("info", ("Found func_item of type %d", - func_item->functype())); - context->supported= FALSE; - } - } - break; - } - case(Item::STRING_ITEM): - DBUG_PRINT("info", ("STRING_ITEM")); - if (context->expecting(Item::STRING_ITEM)) - { -#ifndef DBUG_OFF - char buff[256]; - String str(buff,(uint32) sizeof(buff), system_charset_info); - str.length(0); - Item_string *string_item= (Item_string *) item; - DBUG_PRINT("info", ("value \"%s\"", - string_item->val_str(&str)->ptr())); -#endif - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::STRING_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) + case(Item::FUNC_ITEM): { + Item_func *func_item= (Item_func *) item; + // Check that we expect a function or functional expression here + if (context->expecting(Item::FUNC_ITEM) || + func_item->functype() == Item_func::UNKNOWN_FUNC) + context->expect_nothing(); + else { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(STRING_RESULT); - context->expect_collation(item->collation.collation); + // Did not expect function here + context->supported= FALSE; + break; } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - // Check that we are comparing with a field with same collation - if (!context->expecting_collation(item->collation.collation)) - { - DBUG_PRINT("info", ("Found non-matching collation %s", - item->collation.collation->name)); - context->supported= FALSE; - } + + switch(func_item->functype()) { + case(Item_func::EQ_FUNC): { + DBUG_PRINT("info", ("EQ_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; } - } - else - context->supported= FALSE; - break; - case(Item::INT_ITEM): - DBUG_PRINT("info", ("INT_ITEM")); - if (context->expecting(Item::INT_ITEM)) - { - Item_int *int_item= (Item_int *) item; - DBUG_PRINT("info", ("value %d", int_item->value)); - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::INT_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(INT_RESULT); + case(Item_func::NE_FUNC): { + DBUG_PRINT("info", ("NE_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); + case(Item_func::LT_FUNC): { + DBUG_PRINT("info", ("LT_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::LE_FUNC): { + DBUG_PRINT("info", ("LE_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::GE_FUNC): { + DBUG_PRINT("info", ("GE_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::GT_FUNC): { + DBUG_PRINT("info", ("GT_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::LIKE_FUNC): { + DBUG_PRINT("info", ("LIKE_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect(Item::FUNC_ITEM); + break; + } + case(Item_func::NOTLIKE_FUNC): { + DBUG_PRINT("info", ("NOTLIKE_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect(Item::FUNC_ITEM); + break; + } + case(Item_func::ISNULL_FUNC): { + DBUG_PRINT("info", ("ISNULL_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::ISNOTNULL_FUNC): { + DBUG_PRINT("info", ("ISNOTNULL_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::NOT_FUNC): { + DBUG_PRINT("info", ("NOT_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::FUNC_ITEM); context->expect(Item::COND_ITEM); + break; } - } - else - context->supported= FALSE; - break; - case(Item::REAL_ITEM): - DBUG_PRINT("info", ("REAL_ITEM %s")); - if (context->expecting(Item::REAL_ITEM)) - { - Item_float *float_item= (Item_float *) item; - DBUG_PRINT("info", ("value %f", float_item->value)); - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::REAL_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) - { - // We have not seen the field argument yet + case(Item_func::BETWEEN) : { + DBUG_PRINT("info", ("BETWEEN, rewriting using AND")); + Ndb_rewrite_context *rewrite_context= + new Ndb_rewrite_context(func_item); + rewrite_context->next= context->rewrite_stack; + context->rewrite_stack= rewrite_context; + DBUG_PRINT("info", ("COND_AND_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::COND_AND_FUNC, + func_item->argument_count() - 1); context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(REAL_RESULT); + context->expect(Item::INT_ITEM); + context->expect(Item::STRING_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FUNC_ITEM); + break; } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); + case(Item_func::IN_FUNC) : { + DBUG_PRINT("info", ("IN_FUNC, rewriting using OR")); + Ndb_rewrite_context *rewrite_context= + new Ndb_rewrite_context(func_item); + rewrite_context->next= context->rewrite_stack; + context->rewrite_stack= rewrite_context; + DBUG_PRINT("info", ("COND_OR_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::COND_OR_FUNC, + func_item->argument_count() - 1); + context->expect_only(Item::FIELD_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::STRING_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FUNC_ITEM); + break; } + case(Item_func::UNKNOWN_FUNC): { + DBUG_PRINT("info", ("UNKNOWN_FUNC %s", + func_item->const_item()?"const":"")); + DBUG_PRINT("info", ("result type %d", func_item->result_type())); + if (func_item->const_item()) + switch(func_item->result_type()) { + case(STRING_RESULT): { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::STRING_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(STRING_RESULT); + context->expect_collation(func_item->collation.collation); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + // Check that string result have correct collation + if (!context->expecting_collation(item->collation.collation)) + { + DBUG_PRINT("info", ("Found non-matching collation %s", + item->collation.collation->name)); + context->supported= FALSE; + } + } + // Skip any arguments since we will evaluate function instead + DBUG_PRINT("info", ("Skip until end of arguments marker")); + context->skip= func_item->argument_count(); + break; + } + case(REAL_RESULT): { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::REAL_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(REAL_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } + + // Skip any arguments since we will evaluate function instead + DBUG_PRINT("info", ("Skip until end of arguments marker")); + context->skip= func_item->argument_count(); + break; + } + case(INT_RESULT): { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::INT_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(INT_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } + + // Skip any arguments since we will evaluate function instead + DBUG_PRINT("info", ("Skip until end of arguments marker")); + context->skip= func_item->argument_count(); + break; + } + case(DECIMAL_RESULT): { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::DECIMAL_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(DECIMAL_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } + // Skip any arguments since we will evaluate function instead + DBUG_PRINT("info", ("Skip until end of arguments marker")); + context->skip= func_item->argument_count(); + break; + } + default: + break; + } + else + // Function does not return constant expression + context->supported= FALSE; + break; + } + default: { + DBUG_PRINT("info", ("Found func_item of type %d", + func_item->functype())); + context->supported= FALSE; + } + } + break; } - else - context->supported= FALSE; - break; - case(Item::VARBIN_ITEM): - DBUG_PRINT("info", ("VARBIN_ITEM")); - if (context->expecting(Item::VARBIN_ITEM)) - { + case(Item::STRING_ITEM): + DBUG_PRINT("info", ("STRING_ITEM")); + if (context->expecting(Item::STRING_ITEM)) + { #ifndef DBUG_OFF - char buff[256]; - String str(buff,(uint32) sizeof(buff), system_charset_info); - str.length(0); - Item_hex_string *varbin_item= (Item_hex_string *) item; - DBUG_PRINT("info", ("value \"%s\"", - varbin_item->val_str(&str)->ptr())); + char buff[256]; + String str(buff,(uint32) sizeof(buff), system_charset_info); + str.length(0); + Item_string *string_item= (Item_string *) item; + DBUG_PRINT("info", ("value \"%s\"", + string_item->val_str(&str)->ptr())); #endif - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::VARBIN_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::STRING_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(STRING_RESULT); + context->expect_collation(item->collation.collation); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + // Check that we are comparing with a field with same collation + if (!context->expecting_collation(item->collation.collation)) + { + DBUG_PRINT("info", ("Found non-matching collation %s", + item->collation.collation->name)); + context->supported= FALSE; + } + } + } + else + context->supported= FALSE; + break; + case(Item::INT_ITEM): + DBUG_PRINT("info", ("INT_ITEM")); + if (context->expecting(Item::INT_ITEM)) { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(STRING_RESULT); + Item_int *int_item= (Item_int *) item; + DBUG_PRINT("info", ("value %d", int_item->value)); + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::INT_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(INT_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } } else + context->supported= FALSE; + break; + case(Item::REAL_ITEM): + DBUG_PRINT("info", ("REAL_ITEM %s")); + if (context->expecting(Item::REAL_ITEM)) { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); + Item_float *float_item= (Item_float *) item; + DBUG_PRINT("info", ("value %f", float_item->value)); + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::REAL_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(REAL_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } } - } - else - context->supported= FALSE; - break; - case(Item::DECIMAL_ITEM): - DBUG_PRINT("info", ("DECIMAL_ITEM %s")); - if (context->expecting(Item::DECIMAL_ITEM)) - { - Item_decimal *decimal_item= (Item_decimal *) item; - DBUG_PRINT("info", ("value %f", decimal_item->val_real())); - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::DECIMAL_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) + else + context->supported= FALSE; + break; + case(Item::VARBIN_ITEM): + DBUG_PRINT("info", ("VARBIN_ITEM")); + if (context->expecting(Item::VARBIN_ITEM)) { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(REAL_RESULT); - context->expect_field_result(DECIMAL_RESULT); + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::VARBIN_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(STRING_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } } else + context->supported= FALSE; + break; + case(Item::DECIMAL_ITEM): + DBUG_PRINT("info", ("DECIMAL_ITEM %s")); + if (context->expecting(Item::DECIMAL_ITEM)) { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); + Item_decimal *decimal_item= (Item_decimal *) item; + DBUG_PRINT("info", ("value %f", decimal_item->val_real())); + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::DECIMAL_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(REAL_RESULT); + context->expect_field_result(DECIMAL_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } } + else + context->supported= FALSE; + break; + case(Item::COND_ITEM): { + Item_cond *cond_item= (Item_cond *) item; + + if (context->expecting(Item::COND_ITEM)) + switch(cond_item->functype()) { + case(Item_func::COND_AND_FUNC): + DBUG_PRINT("info", ("COND_AND_FUNC")); + curr_cond->ndb_item= new Ndb_item(cond_item->functype(), + cond_item); + break; + case(Item_func::COND_OR_FUNC): + DBUG_PRINT("info", ("COND_OR_FUNC")); + curr_cond->ndb_item= new Ndb_item(cond_item->functype(), + cond_item); + break; + default: + DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype())); + context->supported= FALSE; + break; + } + else + // Did not expect condition + context->supported= FALSE; + break; } - else + default: { + DBUG_PRINT("info", ("Found item of type %d", item->type())); context->supported= FALSE; - break; - case(Item::COND_ITEM): { - Item_cond *cond_item= (Item_cond *) item; - - if (context->expecting(Item::COND_ITEM)) - switch(cond_item->functype()) { - case(Item_func::COND_AND_FUNC): - DBUG_PRINT("info", ("COND_AND_FUNC")); - curr_cond->ndb_item= new Ndb_item(cond_item->functype(), - cond_item); - break; - case(Item_func::COND_OR_FUNC): - DBUG_PRINT("info", ("COND_OR_FUNC")); - curr_cond->ndb_item= new Ndb_item(cond_item->functype(), - cond_item); - break; - default: - DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype())); - context->supported= FALSE; - break; - } - else - // Did not expect condition - context->supported= FALSE; - break; - } - default: { - DBUG_PRINT("info", ("Found item of type %d", item->type())); - context->supported= FALSE; - } + } + } + + if (context->supported && context->rewrite_stack) + { + Ndb_rewrite_context *rewrite_context= context->rewrite_stack; + if (rewrite_context->count == + rewrite_context->func_item->argument_count()) + { + // Rewrite is done, wrap an END() at the en + DBUG_PRINT("info", ("End of condition group")); + prev_cond= curr_cond; + curr_cond= context->cond_ptr= new Ndb_cond(); + prev_cond->next= curr_cond; + curr_cond->ndb_item= new Ndb_item(NDB_END_COND); + // Pop rewrite stack + context->rewrite_stack= context->rewrite_stack->next; + } } + } } - + DBUG_VOID_RETURN; } @@ -6925,8 +7131,10 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter) break; } case(Item_func::NOT_FUNC): { + DBUG_PRINT("info", ("Generating negated query")); cond= cond->next; negated= TRUE; + break; } default: @@ -6942,12 +7150,14 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter) if (cond) cond= cond->next; if (filter->end() == -1) DBUG_RETURN(1); - break; + if (!negated) + break; + // else fall through (NOT END is an illegal condition) default: { DBUG_PRINT("info", ("Illegal scan filter")); } } - } while (level > 0); + } while (level > 0 || negated); DBUG_RETURN(0); } @@ -6958,14 +7168,20 @@ ha_ndbcluster::build_scan_filter(Ndb_cond * &cond, NdbScanFilter *filter) bool simple_cond= TRUE; DBUG_ENTER("build_scan_filter"); - switch(cond->ndb_item->type) { - case(Item_func::COND_AND_FUNC): - case(Item_func::COND_OR_FUNC): - simple_cond= FALSE; - break; - default: - break; - } + switch(cond->ndb_item->type) { + case(NDB_FUNCTION): + switch(cond->ndb_item->qualification.function_type) { + case(Item_func::COND_AND_FUNC): + case(Item_func::COND_OR_FUNC): + simple_cond= FALSE; + break; + default: + break; + } + break; + default: + break; + } if (simple_cond && filter->begin() == -1) DBUG_RETURN(1); if (build_scan_filter_group(cond, filter)) @@ -6983,6 +7199,7 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack, DBUG_ENTER("generate_scan_filter"); if (ndb_cond_stack) { + DBUG_PRINT("info", ("Generating scan filter")); NdbScanFilter filter(op); bool multiple_cond= FALSE; // Wrap an AND group around multiple conditions diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 01e7bea057f..f73ca8a974e 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -86,6 +86,7 @@ typedef struct ndb_item_field_value { typedef union ndb_item_value { const Item *item; NDB_ITEM_FIELD_VALUE *field_value; + uint arg_count; } NDB_ITEM_VALUE; struct negated_function_mapping @@ -144,6 +145,7 @@ class Ndb_item { } case(NDB_FUNCTION): value.item= item_value; + value.arg_count= ((Item_func *) item_value)->argument_count(); break; case(NDB_END_COND): break; @@ -162,6 +164,13 @@ class Ndb_item { { qualification.function_type= func_type; value.item= item_value; + value.arg_count= ((Item_func *) item_value)->argument_count(); + }; + Ndb_item(Item_func::Functype func_type, uint no_args) + : type(NDB_FUNCTION) + { + qualification.function_type= func_type; + value.arg_count= no_args; }; ~Ndb_item() { @@ -194,7 +203,7 @@ class Ndb_item { int argument_count() { - return ((Item_func *) value.item)->argument_count(); + return value.arg_count; }; const char* get_val() @@ -273,12 +282,28 @@ class Ndb_cond_stack { if (ndb_cond) delete ndb_cond; ndb_cond= NULL; + if (next) delete next; next= NULL; }; Ndb_cond *ndb_cond; Ndb_cond_stack *next; }; +class Ndb_rewrite_context +{ +public: + Ndb_rewrite_context(Item_func *func) + : func_item(func), left_hand_item(NULL), count(0) {}; + ~Ndb_rewrite_context() + { + if (next) delete next; + } + const Item_func *func_item; + const Item *left_hand_item; + uint count; + Ndb_rewrite_context *next; +}; + /* This class is used for storing the context when traversing the Item tree. It stores a reference to the table the condition @@ -292,11 +317,16 @@ class Ndb_cond_traverse_context Ndb_cond_traverse_context(TABLE *tab, void* ndb_tab, Ndb_cond_stack* stack) : table(tab), ndb_table(ndb_tab), supported(TRUE), stack_ptr(stack), cond_ptr(NULL), - expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL) + expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL), + rewrite_stack(NULL) { if (stack) cond_ptr= stack->ndb_cond; }; + ~Ndb_cond_traverse_context() + { + if (rewrite_stack) delete rewrite_stack; + } void expect(Item::Type type) { expect_mask|= (1 << type); @@ -357,7 +387,7 @@ class Ndb_cond_traverse_context uint expect_field_result_mask; uint skip; CHARSET_INFO* collation; - + Ndb_rewrite_context *rewrite_stack; }; /* diff --git a/sql/item.cc b/sql/item.cc index 913c01f5992..5fef75a6e30 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1027,7 +1027,7 @@ Item_field::Item_field(THD *thd, Field *f) structure can go away and pop up again between subsequent executions of a prepared statement). */ - if (thd->current_arena->is_stmt_prepare()) + if (thd->current_arena->is_stmt_prepare_or_first_sp_execute()) { if (db_name) orig_db_name= thd->strdup(db_name); diff --git a/sql/item.h b/sql/item.h index f2e8e582780..4f5ed9934c5 100644 --- a/sql/item.h +++ b/sql/item.h @@ -585,10 +585,12 @@ public: } /* For error printing */ - inline void my_name(char **strp, uint *lengthp) + inline LEX_STRING *my_name(LEX_STRING *get_name) { - *strp= m_name.str; - *lengthp= m_name.length; + if (!get_name) + return &m_name; + (*get_name)= m_name; + return get_name; } bool is_splocal() { return 1; } /* Needed for error checking */ diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a7abb5f9be8..3f25d473792 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1116,8 +1116,8 @@ Item_func_ifnull::fix_length_and_dec() max_length= (max(args[0]->max_length - args[0]->decimals, args[1]->max_length - args[1]->decimals) + decimals); - agg_result_type(&cached_result_type, args, 2); - switch (cached_result_type) { + agg_result_type(&hybrid_type, args, 2); + switch (hybrid_type) { case STRING_RESULT: agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV); break; @@ -1155,7 +1155,7 @@ Field *Item_func_ifnull::tmp_table_field(TABLE *table) } double -Item_func_ifnull::val_real() +Item_func_ifnull::real_op() { DBUG_ASSERT(fixed == 1); double value= args[0]->val_real(); @@ -1171,7 +1171,7 @@ Item_func_ifnull::val_real() } longlong -Item_func_ifnull::val_int() +Item_func_ifnull::int_op() { DBUG_ASSERT(fixed == 1); longlong value=args[0]->val_int(); @@ -1187,7 +1187,7 @@ Item_func_ifnull::val_int() } -my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value) +my_decimal *Item_func_ifnull::decimal_op(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); my_decimal *value= args[0]->val_decimal(decimal_value); @@ -1204,7 +1204,7 @@ my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value) String * -Item_func_ifnull::val_str(String *str) +Item_func_ifnull::str_op(String *str) { DBUG_ASSERT(fixed == 1); String *res =args[0]->val_str(str); @@ -1227,9 +1227,16 @@ Item_func_if::fix_length_and_dec() { maybe_null=args[1]->maybe_null || args[2]->maybe_null; decimals= max(args[1]->decimals, args[2]->decimals); - max_length= (max(args[1]->max_length - args[1]->decimals, + if (decimals == NOT_FIXED_DEC) + { + max_length= max(args[1]->max_length, args[2]->max_length); + } + else + { + max_length= (max(args[1]->max_length - args[1]->decimals, args[2]->max_length - args[2]->decimals) + decimals); + } enum Item_result arg1_type=args[1]->result_type(); enum Item_result arg2_type=args[2]->result_type(); bool null1=args[1]->const_item() && args[1]->null_value; @@ -1678,7 +1685,7 @@ void Item_func_case::print(String *str) Coalesce - return first not NULL argument. */ -String *Item_func_coalesce::val_str(String *str) +String *Item_func_coalesce::str_op(String *str) { DBUG_ASSERT(fixed == 1); null_value=0; @@ -1692,7 +1699,7 @@ String *Item_func_coalesce::val_str(String *str) return 0; } -longlong Item_func_coalesce::val_int() +longlong Item_func_coalesce::int_op() { DBUG_ASSERT(fixed == 1); null_value=0; @@ -1706,7 +1713,7 @@ longlong Item_func_coalesce::val_int() return 0; } -double Item_func_coalesce::val_real() +double Item_func_coalesce::real_op() { DBUG_ASSERT(fixed == 1); null_value=0; @@ -1721,7 +1728,7 @@ double Item_func_coalesce::val_real() } -my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value) +my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); null_value= 0; @@ -1738,8 +1745,8 @@ my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value) void Item_func_coalesce::fix_length_and_dec() { - agg_result_type(&cached_result_type, args, arg_count); - switch (cached_result_type) { + agg_result_type(&hybrid_type, args, arg_count); + switch (hybrid_type) { case STRING_RESULT: count_only_length(); decimals= NOT_FIXED_DEC; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index a929d509723..7a22e76b217 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -453,23 +453,19 @@ public: }; -class Item_func_coalesce :public Item_func +class Item_func_coalesce :public Item_func_numhybrid { protected: - enum Item_result cached_result_type; - Item_func_coalesce(Item *a, Item *b) - :Item_func(a, b), cached_result_type(INT_RESULT) - {} + Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {} public: - Item_func_coalesce(List<Item> &list) - :Item_func(list),cached_result_type(INT_RESULT) - {} - double val_real(); - longlong val_int(); - String *val_str(String *); - my_decimal *val_decimal(my_decimal *); + Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {} + double real_op(); + longlong int_op(); + String *str_op(String *); + my_decimal *decimal_op(my_decimal *); void fix_length_and_dec(); - enum Item_result result_type () const { return cached_result_type; } + void find_num_type() {} + enum Item_result result_type () const { return hybrid_type; } const char *func_name() const { return "coalesce"; } table_map not_null_tables() const { return 0; } }; @@ -482,10 +478,10 @@ protected: bool field_type_defined; public: Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {} - double val_real(); - longlong val_int(); - String *val_str(String *str); - my_decimal *val_decimal(my_decimal *); + double real_op(); + longlong int_op(); + String *str_op(String *str); + my_decimal *decimal_op(my_decimal *); enum_field_types field_type() const; void fix_length_and_dec(); const char *func_name() const { return "ifnull"; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 3767844e200..5af99cb8132 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -695,8 +695,8 @@ String *Item_int_func::val_str(String *str) /* - Check arguments here to determine result's type for function with two - arguments. + Check arguments here to determine result's type for a numeric + function of two arguments. SYNOPSIS Item_num_op::find_num_type() @@ -722,8 +722,9 @@ void Item_num_op::find_num_type(void) hybrid_type= DECIMAL_RESULT; result_precision(); } - else if (r0 == INT_RESULT && r1 == INT_RESULT) + else { + DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT); decimals= 0; hybrid_type=INT_RESULT; result_precision(); @@ -738,7 +739,9 @@ void Item_num_op::find_num_type(void) /* - Set result type of function if it (type) is depends only on first argument + Set result type for a numeric function of one argument + (can be also used by a numeric function of many arguments, if the result + type depends only on the first argument) SYNOPSIS Item_func_num1::find_num_type() @@ -817,6 +820,8 @@ String *Item_func_numhybrid::val_str(String *str) str->set(nr,decimals,&my_charset_bin); break; } + case STRING_RESULT: + return str_op(&str_value); default: DBUG_ASSERT(0); } @@ -841,6 +846,14 @@ double Item_func_numhybrid::val_real() return (double)int_op(); case REAL_RESULT: return real_op(); + case STRING_RESULT: + { + char *end_not_used; + int err_not_used; + String *res= str_op(&str_value); + return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(), + &end_not_used, &err_not_used) : 0.0); + } default: DBUG_ASSERT(0); } @@ -865,6 +878,15 @@ longlong Item_func_numhybrid::val_int() return int_op(); case REAL_RESULT: return (longlong)real_op(); + case STRING_RESULT: + { + char *end_not_used; + int err_not_used; + String *res= str_op(&str_value); + CHARSET_INFO *cs= str_value.charset(); + return (res ? (*(cs->cset->strtoll10))(cs, res->ptr(), &end_not_used, + &err_not_used) : 0); + } default: DBUG_ASSERT(0); } @@ -893,6 +915,12 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value) break; } case STRING_RESULT: + { + String *res= str_op(&str_value); + str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(), + res->length(), res->charset(), decimal_value); + break; + } case ROW_RESULT: default: DBUG_ASSERT(0); @@ -2325,9 +2353,6 @@ longlong Item_func_field::val_int() { DBUG_ASSERT(fixed == 1); - if (args[0]->is_null()) - return 0; - if (cmp_type == STRING_RESULT) { String *field; @@ -2343,6 +2368,8 @@ longlong Item_func_field::val_int() else if (cmp_type == INT_RESULT) { longlong val= args[0]->val_int(); + if (args[0]->null_value) + return 0; for (uint i=1; i < arg_count ; i++) { if (!args[i]->is_null() && val == args[i]->val_int()) @@ -2353,6 +2380,8 @@ longlong Item_func_field::val_int() { my_decimal dec_arg_buf, *dec_arg, dec_buf, *dec= args[0]->val_decimal(&dec_buf); + if (args[0]->null_value) + return 0; for (uint i=1; i < arg_count; i++) { dec_arg= args[i]->val_decimal(&dec_arg_buf); @@ -2363,6 +2392,8 @@ longlong Item_func_field::val_int() else { double val= args[0]->val_real(); + if (args[0]->null_value) + return 0; for (uint i=1; i < arg_count ; i++) { if (!args[i]->is_null() && val == args[i]->val_real()) @@ -4509,7 +4540,7 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name, !my_strcasecmp(system_charset_info, name.str, "VERSION")) return new Item_string("@@VERSION", server_version, (uint) strlen(server_version), - system_charset_info); + system_charset_info, DERIVATION_SYSCONST); Item *item; sys_var *var; diff --git a/sql/item_func.h b/sql/item_func.h index b53f2a0b9c6..f0c7e25ad53 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -189,10 +189,13 @@ class Item_func_numhybrid: public Item_func protected: Item_result hybrid_type; public: - Item_func_numhybrid(Item *a) :Item_func(a),hybrid_type(REAL_RESULT) + Item_func_numhybrid(Item *a) :Item_func(a), hybrid_type(REAL_RESULT) {} Item_func_numhybrid(Item *a,Item *b) - :Item_func(a,b),hybrid_type(REAL_RESULT) + :Item_func(a,b), hybrid_type(REAL_RESULT) + {} + Item_func_numhybrid(List<Item> &list) + :Item_func(list), hybrid_type(REAL_RESULT) {} enum Item_result result_type () const { return hybrid_type; } @@ -208,6 +211,7 @@ public: virtual longlong int_op()= 0; virtual double real_op()= 0; virtual my_decimal *decimal_op(my_decimal *)= 0; + virtual String *str_op(String *)= 0; bool is_null() { (void) val_real(); return null_value; } }; @@ -220,6 +224,7 @@ public: void fix_num_length_and_dec(); void find_num_type(); + String *str_op(String *str) { DBUG_ASSERT(0); return 0; } }; @@ -231,6 +236,7 @@ class Item_num_op :public Item_func_numhybrid virtual void result_precision()= 0; void print(String *str) { print_op(str); } void find_num_type(); + String *str_op(String *str) { DBUG_ASSERT(0); return 0; } }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index b7aefdd6f2e..4f1e5b9a290 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -362,7 +362,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) because we do not rollback this changes TODO: make rollback for it, or special name resolving mode in 5.0. */ - !arena->is_stmt_prepare() + !arena->is_stmt_prepare_or_first_sp_execute() ) { diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 0f2c9a2907d..76b0fa6afcf 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -499,7 +499,6 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, timestamp_type type, String *str) { char intbuff[15]; - uint days_i; uint hours_i; uint weekday; ulong length; @@ -602,8 +601,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, break; case 'h': case 'I': - days_i= l_time->hour/24; - hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i; + hours_i= (l_time->hour%24 + 11)%12+1; length= int10_to_str(hours_i, intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 2, '0'); break; @@ -624,8 +622,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, str->append_with_prefill(intbuff, length, 1, '0'); break; case 'l': - days_i= l_time->hour/24; - hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i; + hours_i= (l_time->hour%24 + 11)%12+1; length= int10_to_str(hours_i, intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 1, '0'); break; diff --git a/sql/set_var.cc b/sql/set_var.cc index 5f0db0bd2d5..0d743f99b73 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1715,7 +1715,8 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) Item_string *tmp; pthread_mutex_lock(&LOCK_global_system_variables); char *str= (char*) value_ptr(thd, var_type, base); - tmp= new Item_string(str, strlen(str), system_charset_info); + tmp= new Item_string(str, strlen(str), + system_charset_info, DERIVATION_SYSCONST); pthread_mutex_unlock(&LOCK_global_system_variables); return tmp; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a07927547c6..f68a06a80e5 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3224,7 +3224,8 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, if (!(*leaves)) make_leaves_list(leaves, tables); - for (TABLE_LIST *table_list= *leaves; + TABLE_LIST *table_list; + for (table_list= *leaves; table_list; table_list= table_list->next_leaf, tablenr++) { @@ -3263,7 +3264,7 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES); DBUG_RETURN(1); } - for (TABLE_LIST *table_list= tables; + for (table_list= tables; table_list; table_list= table_list->next_local) { diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h index bd137e15b90..5e5bb1d8d3b 100644 --- a/sql/sql_bitmap.h +++ b/sql/sql_bitmap.h @@ -28,7 +28,7 @@ template <uint default_width> class Bitmap uint32 buffer[(default_width+31)/32]; public: Bitmap() { init(); } - Bitmap(Bitmap& from) { *this=from; } + Bitmap(const Bitmap& from) { *this=from; } explicit Bitmap(uint prefix_to_set) { init(prefix_to_set); } void init() { bitmap_init(&map, buffer, default_width, 0); } void init(uint prefix_to_set) { init(); set_prefix(prefix_to_set); } @@ -61,19 +61,17 @@ public: my_bool operator==(const Bitmap& map2) const { return bitmap_cmp(&map, &map2.map); } char *print(char *buf) const { - char *s=buf; int i; - uchar *uchar_buffer= (uchar*)&buffer; - for (i=sizeof(buffer)-1; i>=0 ; i--) + char *s=buf; + const uchar *e=buffer, *b=e+sizeof(buffer)-1; + while (!*b && b>e) + b--; + if ((*s=_dig_vec_upper[*b >> 4]) != '0') + s++; + *s++=_dig_vec_upper[*b & 15]; + while (--b>=e) { - if ((*s=_dig_vec_upper[uchar_buffer[i] >> 4]) != '0') - break; - if ((*s=_dig_vec_upper[uchar_buffer[i] & 15]) != '0') - break; - } - for (s++, i-- ; i>=0 ; i--) - { - *s++=_dig_vec_upper[uchar_buffer[i] >> 4]; - *s++=_dig_vec_upper[uchar_buffer[i] & 15]; + *s++=_dig_vec_upper[*b >> 4]; + *s++=_dig_vec_upper[*b & 15]; } *s=0; return buf; diff --git a/sql/sql_class.h b/sql/sql_class.h index 1a014e2151b..8f8ba9e2d8e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -696,7 +696,8 @@ public: virtual Type type() const; virtual ~Item_arena() {}; - inline bool is_stmt_prepare() const { return (int)state < (int)PREPARED; } + inline bool is_stmt_prepare_or_first_sp_execute() const + { return (int)state < (int)PREPARED; } inline bool is_first_stmt_execute() const { return state == PREPARED; } inline bool is_stmt_execute() const { return state == PREPARED || state == EXECUTED; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3947ed2ba27..c374890c717 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5898,7 +5898,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->db= empty_c_string; ptr->db_length= 0; } - if (thd->current_arena->is_stmt_prepare()) + if (thd->current_arena->is_stmt_prepare_or_first_sp_execute()) ptr->db= thd->strdup(ptr->db); ptr->alias= alias_str; @@ -6976,7 +6976,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, against the opened tables to ensure we don't use a table that is part of the view (which can only be done after the table has been opened). */ - if (thd->current_arena->is_stmt_prepare()) + if (thd->current_arena->is_stmt_prepare_or_first_sp_execute()) { /* For temporary tables we don't have to check if the created table exists diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 403d20f3ddb..5e8b6cb49e9 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5217,7 +5217,10 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab) tmp= new Item_func_trig_cond(tmp, &tab->found); } if (tmp) + { tmp->quick_fix_field(); + tmp->update_used_tables(); + } return tmp; } @@ -5445,11 +5448,13 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) if (!(tmp= add_found_match_trig_cond(first_inner_tab, tmp, 0))) DBUG_RETURN(1); tab->select_cond=sel->cond=tmp; + /* Push condition to storage engine if this is enabled + and the condition is not guarded */ + tab->table->file->pushed_cond= NULL; if (thd->variables.engine_condition_pushdown) { COND *push_cond= - make_cond_for_table(cond,current_map,current_map); - tab->table->file->pushed_cond= NULL; + make_cond_for_table(tmp, current_map, current_map); if (push_cond) { /* Push condition to handler */ @@ -5790,6 +5795,7 @@ make_join_readinfo(JOIN *join, uint options) if (!table->no_keyread) { if (tab->select && tab->select->quick && + tab->select->quick->index != MAX_KEY && //not index_merge table->used_keys.is_set(tab->select->quick->index)) { table->key_read=1; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 8d36889df76..56401ced67c 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -323,7 +323,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } if (tmp_arena) thd->restore_backup_item_arena(tmp_arena, &backup); - if (arena->is_stmt_prepare()) + if (arena->is_stmt_prepare_or_first_sp_execute()) { /* prepare fake select to initialize it correctly */ init_prepare_fake_select_lex(thd); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a6e77edaa84..2a7237c7fc2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4346,11 +4346,11 @@ simple_expr: { if ($3->is_splocal()) { - LEX_STRING name; + LEX_STRING *name; Item_splocal *il= static_cast<Item_splocal *>($3); - il->my_name(&name.str, &name.length); - my_error(ER_WRONG_COLUMN_NAME, MYF(0), name.str); + name= il->my_name(NULL); + my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str); YYABORT; } $$= new Item_default_value($3); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 9a8ee44c54c..002076afd90 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -7455,12 +7455,16 @@ static void test_explain_bug() verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_LEN, 0); - verify_prepare_field(result, 6, "key_len", "", - (mysql_get_server_version(mysql) <= 50000 ? - MYSQL_TYPE_LONGLONG : MYSQL_TYPE_VAR_STRING), - "", "", "", - (mysql_get_server_version(mysql) <= 50000 ? 3 : 4096), - 0); + if (mysql_get_server_version(mysql) <= 50000) + { + verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_LONGLONG, "", + "", "", 3, 0); + } + else + { + verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING, "", + "", "", NAME_LEN*MAX_KEY, 0); + } verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_LEN*16, 0); |