summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xBUILD/compile-pentium-valgrind-max2
-rw-r--r--BitKeeper/etc/logging_ok4
-rwxr-xr-xBitKeeper/triggers/post-incoming3
-rwxr-xr-xBitKeeper/triggers/post-outgoing3
-rwxr-xr-xBitKeeper/triggers/pre-commit12
-rwxr-xr-xINSTALL-WIN-SOURCE221
-rw-r--r--Makefile.am2
-rw-r--r--VC++Files/client/mysql.dsp10
-rw-r--r--VC++Files/client/mysqlclient.dsp26
-rw-r--r--VC++Files/libmysqld/examples/test_libmysqld.dsp24
-rw-r--r--VC++Files/libmysqld/libmysqld.def183
-rw-r--r--VC++Files/libmysqld/libmysqld.dsp50
-rw-r--r--VC++Files/myisam/myisam.dsp4
-rw-r--r--VC++Files/mysql.dsw9
-rw-r--r--VC++Files/sql/mysqld.dsp26
-rw-r--r--acinclude.m46
-rw-r--r--client/get_password.c1
-rw-r--r--client/mysql.cc13
-rw-r--r--client/mysqltest.c98
-rw-r--r--configure.in8
-rw-r--r--include/Makefile.am3
-rw-r--r--include/my_base.h4
-rw-r--r--include/my_getopt.h9
-rw-r--r--include/my_sys.h8
-rw-r--r--include/myisam.h1
-rw-r--r--include/mysql.h2
-rw-r--r--include/mysql_com.h1
-rw-r--r--include/mysqld_error.h7
-rw-r--r--include/sql_state.h6
-rw-r--r--libmysql/Makefile.am1
-rw-r--r--libmysql/libmysql.c23
-rw-r--r--libmysql/libmysql.def148
-rw-r--r--libmysqld/libmysqld.c102
-rw-r--r--libmysqld/libmysqld.def183
-rw-r--r--myisam/Makefile.am1
-rw-r--r--myisam/mi_extra.c3
-rw-r--r--myisam/mi_open.c1
-rw-r--r--myisam/mi_preload.c114
-rw-r--r--myisam/myisamchk.c2
-rw-r--r--myisam/myisamdef.h1
-rw-r--r--mysql-test/include/have_openssl_2.inc2
-rw-r--r--mysql-test/r/alter_table.result39
-rw-r--r--mysql-test/r/auto_increment.result7
-rw-r--r--mysql-test/r/case.result67
-rw-r--r--mysql-test/r/cast.result4
-rw-r--r--mysql-test/r/create.result4
-rw-r--r--mysql-test/r/ctype_latin1_de.result10
-rw-r--r--mysql-test/r/distinct.result6
-rw-r--r--mysql-test/r/drop.result6
-rw-r--r--mysql-test/r/func_gconcat.result27
-rw-r--r--mysql-test/r/func_group.result9
-rw-r--r--mysql-test/r/func_in.result53
-rw-r--r--mysql-test/r/func_sapdb.result200
-rw-r--r--mysql-test/r/func_str.result205
-rw-r--r--mysql-test/r/grant_cache.result2
-rw-r--r--mysql-test/r/handler.result19
-rw-r--r--mysql-test/r/have_openssl_2.require2
-rw-r--r--mysql-test/r/innodb.result2
-rw-r--r--mysql-test/r/key_cache.result43
-rw-r--r--mysql-test/r/merge.result50
-rw-r--r--mysql-test/r/null.result2
-rw-r--r--mysql-test/r/null_key.result110
-rw-r--r--mysql-test/r/openssl_1.result8
-rw-r--r--mysql-test/r/openssl_2.result25
-rw-r--r--mysql-test/r/preload.result167
-rw-r--r--mysql-test/r/repair_part2.result2
-rw-r--r--mysql-test/r/rpl000009.result6
-rw-r--r--mysql-test/r/rpl_rotate_logs.result7
-rw-r--r--mysql-test/r/select_safe.result2
-rw-r--r--mysql-test/r/subselect.result80
-rw-r--r--mysql-test/r/symlink.result2
-rw-r--r--mysql-test/r/type_blob.result2
-rw-r--r--mysql-test/r/variables.result2
-rw-r--r--mysql-test/r/warnings.result2
-rw-r--r--mysql-test/t/alter_table.test27
-rw-r--r--mysql-test/t/auto_increment.test4
-rw-r--r--mysql-test/t/case.test59
-rw-r--r--mysql-test/t/ctype_latin1_de.test13
-rw-r--r--mysql-test/t/func_gconcat.test26
-rw-r--r--mysql-test/t/func_group.test8
-rw-r--r--mysql-test/t/func_in.test27
-rw-r--r--mysql-test/t/func_sapdb.test99
-rw-r--r--mysql-test/t/func_str.test128
-rw-r--r--mysql-test/t/handler.test14
-rw-r--r--mysql-test/t/innodb.test4
-rw-r--r--mysql-test/t/key_cache-master.opt1
-rw-r--r--mysql-test/t/key_cache.test42
-rw-r--r--mysql-test/t/merge.test29
-rw-r--r--mysql-test/t/null_key.test35
-rw-r--r--mysql-test/t/openssl_1.test2
-rw-r--r--mysql-test/t/openssl_2.test2
-rw-r--r--mysql-test/t/preload.test100
-rw-r--r--mysql-test/t/rpl_rotate_logs.test5
-rw-r--r--mysql-test/t/subselect.test90
-rw-r--r--mysys/mf_keycache.c89
-rw-r--r--mysys/mf_loadpath.c11
-rw-r--r--mysys/my_getopt.c193
-rw-r--r--mysys/my_symlink.c12
-rw-r--r--mysys/tree.c10
-rw-r--r--scripts/Makefile.am2
-rwxr-xr-xscripts/make_win_src_distribution.sh7
-rw-r--r--scripts/mysql_create_system_tables.sh12
-rw-r--r--scripts/mysql_fix_privilege_tables.sh3
-rw-r--r--scripts/mysql_fix_privilege_tables.sql2
-rw-r--r--scripts/mysql_install_db.sh2
-rw-r--r--sql-common/Makefile.am21
-rw-r--r--sql-common/client.c15
-rw-r--r--sql/Makefile.am2
-rw-r--r--sql/field.cc5
-rw-r--r--sql/field.h1
-rw-r--r--sql/field_conv.cc2
-rw-r--r--sql/ha_myisam.cc66
-rw-r--r--sql/ha_myisam.h1
-rw-r--r--sql/ha_myisammrg.cc91
-rw-r--r--sql/handler.cc7
-rw-r--r--sql/handler.h1
-rw-r--r--sql/item.cc188
-rw-r--r--sql/item.h110
-rw-r--r--sql/item_cmpfunc.cc564
-rw-r--r--sql/item_cmpfunc.h82
-rw-r--r--sql/item_create.cc41
-rw-r--r--sql/item_create.h9
-rw-r--r--sql/item_func.cc275
-rw-r--r--sql/item_func.h46
-rw-r--r--sql/item_geofunc.cc4
-rw-r--r--sql/item_geofunc.h4
-rw-r--r--sql/item_strfunc.cc175
-rw-r--r--sql/item_strfunc.h49
-rw-r--r--sql/item_subselect.cc11
-rw-r--r--sql/item_sum.cc134
-rw-r--r--sql/item_sum.h30
-rw-r--r--sql/item_timefunc.cc632
-rw-r--r--sql/item_timefunc.h115
-rw-r--r--sql/lex.h21
-rw-r--r--sql/log_event.cc2
-rw-r--r--sql/mysql_priv.h19
-rw-r--r--sql/mysqld.cc125
-rw-r--r--sql/net_serv.cc2
-rw-r--r--sql/nt_servc.cc2
-rw-r--r--sql/opt_range.cc6
-rw-r--r--sql/protocol.cc19
-rw-r--r--sql/set_var.cc222
-rw-r--r--sql/set_var.h105
-rw-r--r--sql/share/czech/errmsg.txt15
-rw-r--r--sql/share/danish/errmsg.txt25
-rw-r--r--sql/share/dutch/errmsg.txt19
-rw-r--r--sql/share/english/errmsg.txt29
-rw-r--r--sql/share/estonian/errmsg.txt13
-rw-r--r--sql/share/french/errmsg.txt19
-rw-r--r--sql/share/german/errmsg.txt55
-rw-r--r--sql/share/greek/errmsg.txt17
-rw-r--r--sql/share/hungarian/errmsg.txt15
-rw-r--r--sql/share/italian/errmsg.txt19
-rw-r--r--sql/share/japanese/errmsg.txt13
-rw-r--r--sql/share/korean/errmsg.txt13
-rw-r--r--sql/share/norwegian-ny/errmsg.txt21
-rw-r--r--sql/share/norwegian/errmsg.txt21
-rw-r--r--sql/share/polish/errmsg.txt21
-rw-r--r--sql/share/portuguese/errmsg.txt13
-rw-r--r--sql/share/romanian/errmsg.txt21
-rw-r--r--sql/share/russian/errmsg.txt11
-rw-r--r--sql/share/serbian/errmsg.txt21
-rw-r--r--sql/share/slovak/errmsg.txt21
-rw-r--r--sql/share/spanish/errmsg.txt21
-rw-r--r--sql/share/swedish/errmsg.txt25
-rw-r--r--sql/share/ukrainian/errmsg.txt11
-rw-r--r--sql/slave.cc9
-rw-r--r--sql/spatial.cc90
-rw-r--r--sql/spatial.h42
-rw-r--r--sql/sql_analyse.cc6
-rw-r--r--sql/sql_analyse.h5
-rw-r--r--sql/sql_base.cc12
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h25
-rw-r--r--sql/sql_client.cc2
-rw-r--r--sql/sql_derived.cc2
-rw-r--r--sql/sql_handler.cc39
-rw-r--r--sql/sql_help.cc25
-rw-r--r--sql/sql_insert.cc19
-rw-r--r--sql/sql_lex.cc56
-rw-r--r--sql/sql_lex.h28
-rw-r--r--sql/sql_load.cc4
-rw-r--r--sql/sql_parse.cc39
-rw-r--r--sql/sql_prepare.cc5
-rw-r--r--sql/sql_select.cc690
-rw-r--r--sql/sql_select.h13
-rw-r--r--sql/sql_show.cc57
-rw-r--r--sql/sql_string.cc17
-rw-r--r--sql/sql_string.h2
-rw-r--r--sql/sql_table.cc27
-rw-r--r--sql/sql_union.cc5
-rw-r--r--sql/sql_update.cc8
-rw-r--r--sql/sql_yacc.yy214
-rw-r--r--sql/table.cc4
-rw-r--r--sql/table.h1
-rw-r--r--sql/time.cc14
-rw-r--r--sql/unireg.cc4
-rw-r--r--strings/ctype-utf8.c2
-rw-r--r--tests/client_test.c139
199 files changed, 6650 insertions, 2176 deletions
diff --git a/BUILD/compile-pentium-valgrind-max b/BUILD/compile-pentium-valgrind-max
index c6d8e4f21e8..20876d67472 100755
--- a/BUILD/compile-pentium-valgrind-max
+++ b/BUILD/compile-pentium-valgrind-max
@@ -3,7 +3,7 @@
path=`dirname $0`
. "$path/SETUP.sh"
-extra_flags="$pentium_cflags $debug_cflags -USAFEMALLOC -DHAVE_purify"
+extra_flags="$pentium_cflags $debug_cflags -USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify"
c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs"
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 806eac52759..794edcdd968 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -17,6 +17,7 @@ bar@gw.udmsearch.izhnet.ru
bell@laptop.sanja.is.com.ua
bell@sanja.is.com.ua
bk@admin.bk
+bk@mysql.r18.ru
carsten@tsort.bitbybit.dk
davida@isil.mysql.com
gluh@gluh.(none)
@@ -34,6 +35,7 @@ hf@deer.(none)
hf@deer.mysql.r18.ru
hf@genie.(none)
igor@hundin.mysql.fi
+igor@rurik.mysql.com
jani@dsl-jkl1657.dial.inet.fi
jani@dsl-kpogw4gb5.dial.inet.fi
jani@hynda.(none)
@@ -51,6 +53,7 @@ jorge@linux.jorge.mysql.com
kaj@work.mysql.com
lenz@kallisto.mysql.com
lenz@mysql.com
+miguel@hegel.(none)
miguel@hegel.br
miguel@hegel.local
miguel@light.
@@ -97,6 +100,7 @@ sasha@mysql.sashanet.com
serg@build.mysql2.com
serg@serg.mylan
serg@serg.mysql.com
+serg@sergbook.mylan
serg@sergbook.mysql.com
sinisa@rhols221.adsl.netsonic.fi
tfr@beta.frontier86.ee
diff --git a/BitKeeper/triggers/post-incoming b/BitKeeper/triggers/post-incoming
deleted file mode 100755
index f1ea2255de9..00000000000
--- a/BitKeeper/triggers/post-incoming
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /bin/sh
-
-echo "Test: post-incoming works"
diff --git a/BitKeeper/triggers/post-outgoing b/BitKeeper/triggers/post-outgoing
deleted file mode 100755
index 3fc2cdbad67..00000000000
--- a/BitKeeper/triggers/post-outgoing
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /bin/sh
-
-echo "Test: post-outgoing works"
diff --git a/BitKeeper/triggers/pre-commit b/BitKeeper/triggers/pre-commit
new file mode 100755
index 00000000000..2293dc55e2a
--- /dev/null
+++ b/BitKeeper/triggers/pre-commit
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+if [ "$REAL_EMAIL" = "" ]
+then
+ echo "Error: you must set REAL_EMAIL in your profile"
+ echo "e.g.: export REAL_EMAIL='Joe Dow <joe@foo.bar>'"
+ echo ""
+ echo "Commit FAILED!"
+ echo "Set REAL_EMAIL and retry."
+ exit 1
+fi
+
diff --git a/INSTALL-WIN-SOURCE b/INSTALL-WIN-SOURCE
new file mode 100755
index 00000000000..bce093633f5
--- /dev/null
+++ b/INSTALL-WIN-SOURCE
@@ -0,0 +1,221 @@
+#########################################################
+# #
+# HOWTO : INSTALL MySQL FROM SOURCE #
+# WINDOWS PORT #
+# #
+# Copyright (C) MySQL AB 1995-2003 #
+#########################################################
+
+This is a simple 'HOWTO' document describing how to
+build MySQL binaries for versions 4.1 and above on
+Windows. Instructions are provided for building binaries
+from a standard source distribution or from the BitKeeper
+tree that contains the latest development source.
+
+---------------------------------------------------------
+NOTE
+---------------------------------------------------------
+
+Normally, it is best to use precompiled binary distributions
+of MySQL that are built specifically for optimal performance
+on Windows by MySQL AB. Binary distributions are available
+from:
+
+http://www.mysql.com/downloads/
+
+The instructions in this document are strictly for users
+who want to test MySQL on Windows from the latest source or
+from the BitKeeper tree, and for internal MySQL developers.
+
+--------------------------------------------------------
+TABLE OF CONTENTS
+--------------------------------------------------------
+1. REQUIREMENTS
+2. OBTAINING A WINDOWS SOURCE DISTRIBUTION
+3. CREATING A SOURCE PACKAGE FROM THE 'BitKeeper' TREE
+4. BUILDING 'mysql server and clients' FROM VC++ WORKSPACE
+5. BUILDING FROM 'nmake' MAKEFILES
+6. STARTING THE MYSQL SERVER FOR THE FIRST TIME
+7. TESTING THE CONNECTION
+8. SPECIAL NOTES AND CONSIDERATIONS
+
+-------------------------------------------------------
+1. REQUIREMENTS
+-------------------------------------------------------
+
+To build MySQL on Windows from source, you need the
+following compiler and resources available on your Windows
+system:
+
+ - Microsoft Visual C++ 6.0 and above
+ - ~45 MB disk space
+ - 64 MB RAM
+
+You'll also need a MySQL source distribution, which you
+can obtain as described in section 2.
+
+-------------------------------------------------------
+2. OBTAINING A WINDOWS SOURCE DISTRIBUTION
+-------------------------------------------------------
+
+There are two ways you can get a Windows source distribution
+for MySQL version 4.1 and above:
+
+ I. Obtain a MySQL AB-distributed source distribution for the
+ particular version of MySQL in which you are interested.
+ Prepackaged source distributions are available for released
+ versions of MySQL and can be obtained from:
+
+ http://www.mysql.com/downloads/
+
+ II. Alternatively, you can package a source distribution
+ yourself from the latest BitKeeper developer source
+ tree. If you plan to do this, you must create the
+ package on a Unix system and then transfer it to your
+ Windows system. (The reason for this is that some of the
+ configuration and build steps require tools that work only
+ on Unix.) The BitKeeper approach thus requires:
+
+ - A system running Unix, or a Unix-like system such as Linux
+ - BitKeeper 3.0 installed on that system (you can obtain
+ BitKeeper from http://www.bitkeeper.com)
+
+If you are using the first option, you can skip the next
+section and go directly to "BUILDING 'mysql server & clients'
+FROM VC++ WORKSPACE"
+
+-------------------------------------------------------
+3. CREATING A SOURCE PACKAGE FROM THE 'BitKeeper' TREE
+-------------------------------------------------------
+
+To build the latest Windows source package from the current
+BitKeeper source tree, use the following instructions. Please
+note that this procedure must be performed on a system
+running a Unix or Unix-like operating system. (The procedure
+is know to work well on Linux, for example.
+
+- Clone the BitKeeper source tree for MySQL (version 4.1
+ or above, as desired). For more information how to clone
+ the source tree, see the instructions at:
+
+ http://www.mysql.com/doc/en/Installing_source_tree.html
+
+- Configure and build the distribution so that you have a
+ server binary to work with. One way to do this is to run
+ the following command in the top-level directory of your
+ source tree:
+
+ ./BUILD/compile-pentium-max
+
+- After making sure that the build process completed successfully,
+ run the following utility script from top-level directory
+ of your source tree:
+
+ ./scripts/make_win_src_distribution
+
+ This script creates a Windows source package, to be used on
+ your Windows system. You can supply different options to the
+ script based on your needs. It accepts the following options:
+
+ --debug Debug, without creating the package
+ --tmp Specify the temporary location
+ --suffix Suffix name for the package
+ --dirname Directory name to copy files (intermediate)
+ --silent Do not list verbosely files processed
+ --tar Create tar.gz package instead of .zip
+ --help Show this help message
+
+ By default, make_win_src_distribution creates a zipped
+ archive with the name mysql-$version-win-src.zip, where
+ $version represents the version of your MySQL source tree.
+
+ - Copy or upload to your Windows machine the Windows source
+ package that you have just created. To compile it, use
+ the instructions in the next section.
+
+---------------------------------------------------------
+4. BUILDING 'mysql server & clients' FROM VC++ WORKSPACE
+---------------------------------------------------------
+
+NOTE: MySQL 4.1 and above VC++ workspace files are compatible
+ with Microsoft Visual Studio 6.0 and above(7.0/.NET)
+ editions and tested by MySQL folks before each
+ release.
+
+Unpack the Windows source zipped archive to a folder and open
+mysql.dsw from your top-level directory.
+
+If you want to build both release and debug versions, then
+select 'build' -> 'buildall' option. To build only release
+or debug versions, select all appropriate workspaces from
+the 'build' -> 'batch build' option.
+
+The simplest solution to building the basic clients and core
+server is to set your current active workspace as 'mysqld'
+release or debug version, and just hit 'build' or 'F7', which
+creates the necessary client binaries in the 'client_release'
+or 'client_debug' directories. The libraries are placed in the
+'lib_release' and 'lib_debug' directories for release and
+debug versions, respectively.
+
+Now you have built the distribution. If you get any compiler
+errors, please cross check and email the compiler output to
+win32@lists.mysql.com for further assistance.
+
+---------------------------------------------------------
+5. BUILDING FROM 'nmake' MAKEFILES
+---------------------------------------------------------
+TODO from MySQL PIEFU team.
+
+---------------------------------------------------------
+6. STARTING THE MYSQL SERVER FOR THE FIRST TIME
+---------------------------------------------------------
+
+The server built using the preceding instructions will
+expect that the MySQL base directory and data directory
+are C:\mysql and C:\mysql\data by default. If you want to
+test your server using the source root directory and its
+data directory as the base directory and data directory,
+you will need to tell the server their pathnames. You can
+either do this on the command line with the --basedir
+and --data-dir options, or place appropriate options in
+an option file (C:\my.cnf or the my.ini file in your
+Windows directory). If you have an existing data directory
+elsewhere that you want to use, you can specify its pathname
+instead.
+
+Start your server from the 'client_release' or 'client_debug'
+directory (depending on which server you want to use). The
+general instructions are given here:
+
+http://www.mysql.com/doc/en/Windows_installation.html
+
+You'll have to adapt the instructions appropriately if you
+want to use a different base directory and/or data directory.
+
+That's all!!! See, it's as simple to build MySQL on Windows
+as on any other platform!!!
+
+---------------------------------------------------------
+7. TESTING THE CONNECTION
+---------------------------------------------------------
+
+Once the server is running in standalone fashion or as a
+service based on your configuration, try to connect to it
+from the 'mysql' command line SQL interactive utility that
+exists in your 'client_release' or 'client_debug' directory.
+
+---------------------------------------------------------
+8. SPECIAL NOTES AND CONSIDERATIONS
+---------------------------------------------------------
+
+- For production use, MySQL AB does not advise using a MySQL
+ server built by yourself from source. It is preferable to
+ stick to using binaries shipped by MySQL AB.
+
+- If you find something not working as expected, or you have
+ suggestions about ways to improve the current build process
+ on Windows, please email to win32@lists.mysql.com.
+
+Thanks
+MySQL Team
diff --git a/Makefile.am b/Makefile.am
index 1fcf498a84b..ffebf891795 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,7 +22,7 @@ AUTOMAKE_OPTIONS = foreign
EXTRA_DIST = INSTALL-SOURCE README \
COPYING COPYING.LIB
SUBDIRS = . include @docs_dirs@ \
- @readline_topdir@ \
+ @readline_topdir@ sql-common \
@thread_dirs@ pstack @sql_client_dirs@ \
@sql_server_dirs@ scripts man tests \
BUILD @netware_dir@ os2 @libmysqld_dirs@ \
diff --git a/VC++Files/client/mysql.dsp b/VC++Files/client/mysql.dsp
index 1cd03ee2fcc..c0fd1e785d5 100644
--- a/VC++Files/client/mysql.dsp
+++ b/VC++Files/client/mysql.dsp
@@ -87,7 +87,7 @@ LINK32=link.exe
# Name "mysql - Win32 Debug"
# Begin Source File
-SOURCE=..\mysys\my_gethostbyname.c
+SOURCE=.\completion_hash.cpp
# End Source File
# Begin Source File
@@ -102,5 +102,13 @@ SOURCE=.\mysql.cpp
!ENDIF
# End Source File
+# Begin Source File
+
+SOURCE=.\readline.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sql_string.cpp
+# End Source File
# End Target
# End Project
diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp
index 2f66d99b33c..0f4c46acd2a 100644
--- a/VC++Files/client/mysqlclient.dsp
+++ b/VC++Files/client/mysqlclient.dsp
@@ -25,7 +25,7 @@ CFG=mysqlclient - Win32 Debug
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=xicl6.exe
+CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "mysqlclient - Win32 Release"
@@ -48,7 +48,7 @@ RSC=rc.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=xilink6.exe -lib
+LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_release\mysqlclient.lib"
@@ -72,7 +72,7 @@ LIB32=xilink6.exe -lib
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LIB32=xilink6.exe -lib
+LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib_debug\mysqlclient.lib"
@@ -108,14 +108,6 @@ SOURCE=..\libmysql\client.c
# End Source File
# Begin Source File
-SOURCE=.\completion_hash.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\completion_hash.h
-# End Source File
-# Begin Source File
-
SOURCE="..\strings\ctype-big5.c"
# End Source File
# Begin Source File
@@ -426,10 +418,6 @@ SOURCE=..\libmysql\password.c
# End Source File
# Begin Source File
-SOURCE=.\readline.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\mysys\safemalloc.c
# End Source File
# Begin Source File
@@ -438,14 +426,6 @@ SOURCE=..\mysys\sha1.c
# End Source File
# Begin Source File
-SOURCE=.\sql_string.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\sql_string.h
-# End Source File
-# Begin Source File
-
SOURCE=..\strings\str2int.c
# End Source File
# Begin Source File
diff --git a/VC++Files/libmysqld/examples/test_libmysqld.dsp b/VC++Files/libmysqld/examples/test_libmysqld.dsp
index d5fd0a0982d..0f4b09d963e 100644
--- a/VC++Files/libmysqld/examples/test_libmysqld.dsp
+++ b/VC++Files/libmysqld/examples/test_libmysqld.dsp
@@ -7,18 +7,18 @@
CFG=test_libmysqld - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "test_libmysqld.mak".
-!MESSAGE
+!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
+!MESSAGE
!MESSAGE NMAKE /f "test_libmysqld.mak" CFG="test_libmysqld - Win32 Release"
-!MESSAGE
+!MESSAGE
!MESSAGE Possible choices for configuration are:
-!MESSAGE
+!MESSAGE
!MESSAGE "test_libmysqld - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE
+!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@@ -55,7 +55,19 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
+SOURCE=..\..\client\completion_hash.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\client\mysql.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\client\readline.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\client\sql_string.cpp
# End Source File
# End Group
# Begin Source File
diff --git a/VC++Files/libmysqld/libmysqld.def b/VC++Files/libmysqld/libmysqld.def
index c6615ee971c..c3f757b5f1a 100644
--- a/VC++Files/libmysqld/libmysqld.def
+++ b/VC++Files/libmysqld/libmysqld.def
@@ -1,65 +1,130 @@
LIBRARY LIBMYSQLD
-DESCRIPTION 'MySQL 4.0 Embedded Server Library'
-VERSION 4.0
+DESCRIPTION 'MySQL 4.1 Embedded Server Library'
+VERSION 4.1
EXPORTS
- mysql_server_end
- mysql_server_init
- mysql_use_result
- mysql_thread_safe
- mysql_thread_id
- mysql_store_result
- mysql_stat
- mysql_shutdown
- mysql_select_db
- mysql_row_tell
- mysql_row_seek
- mysql_real_query
- mysql_real_connect
- mysql_query
- mysql_ping
- mysql_options
- mysql_num_rows
- mysql_num_fields
- mysql_list_tables
- mysql_list_processes
- mysql_list_fields
- mysql_list_dbs
- mysql_kill
- mysql_insert_id
- mysql_init
- mysql_info
- mysql_get_server_info
- mysql_get_proto_info
- mysql_get_host_info
- mysql_get_client_info
- mysql_free_result
- mysql_field_tell
- mysql_field_count
- mysql_field_seek
- mysql_fetch_row
- mysql_fetch_lengths
- mysql_fetch_fields
- mysql_fetch_field_direct
- mysql_fetch_field
- mysql_escape_string
- mysql_real_escape_string
- mysql_error
- mysql_errno
- mysql_eof
- mysql_dump_debug_info
- mysql_drop_db
- mysql_debug
- mysql_data_seek
- mysql_create_db
- mysql_character_set_name
+ _dig_vec
+ bmove_upp
+ delete_dynamic
+ free_defaults
+ getopt_compare_strings
+ getopt_ull_limit_value
+ handle_options
+ init_dynamic_array
+ insert_dynamic
+ int2str
+ is_prefix
+ list_add
+ list_delete
+ load_defaults
+ max_allowed_packet
+ my_end
+ my_getopt_print_errors
+ my_init
+ my_malloc
+ my_memdup
+ my_no_flags_free
+ my_path
+ my_print_help
+ my_print_variables
+ my_realloc
+ my_strdup
+ my_thread_end
+ my_thread_init
+ myodbc_remove_escape
+ mysql_affected_rows
+ mysql_autocommit
mysql_change_user
- mysql_connect
+ mysql_character_set_name
mysql_close
- mysql_affected_rows
- mysql_thread_init
- mysql_thread_end
- mysql_send_query
+ mysql_commit
+ mysql_data_seek
+ mysql_debug
+ mysql_dump_debug_info
+ mysql_eof
+ mysql_errno
+ mysql_error
+ mysql_escape_string
+ mysql_fetch_field
+ mysql_fetch_field_direct
+ mysql_fetch_fields
+ mysql_fetch_lengths
+ mysql_fetch_row
+ mysql_field_count
+ mysql_field_seek
+ mysql_field_tell
+ mysql_free_result
+ mysql_get_client_info
+ mysql_get_host_info
+ mysql_get_proto_info
+ mysql_get_server_info
+ mysql_info
+ mysql_init
+ mysql_insert_id
+ mysql_kill
+ mysql_list_dbs
+ mysql_list_fields
+ mysql_list_processes
+ mysql_list_tables
+ mysql_more_results
+ mysql_next_result
+ mysql_num_fields
+ mysql_num_rows
+ mysql_odbc_escape_string
+ mysql_options
+ mysql_ping
+ mysql_query
mysql_read_query_result
+ mysql_real_connect
+ mysql_real_escape_string
+ mysql_real_query
mysql_refresh
- mysql_odbc_escape_string
- myodbc_remove_escape
+ mysql_rollback
+ mysql_row_seek
+ mysql_row_tell
+ mysql_select_db
+ mysql_send_query
+ mysql_shutdown
+ mysql_ssl_set
+ mysql_stat
+ mysql_store_result
+ mysql_sqlstate
+ mysql_thread_id
+ mysql_thread_safe
+ mysql_use_result
+ mysql_warning_count
+ net_buffer_length
+ set_dynamic
+ strcend
+ strcont
+ strdup_root
+ strfill
+ strinstr
+ strmake
+ strmov
+ strxmov
+ mysql_server_end
+ mysql_server_init
+ get_tty_password
+ sql_protocol_typelib
+ mysql_get_server_version
+ mysql_sqlstate
+ charsets_dir
+ disabled_my_option
+ my_charset_latin1
+ init_alloc_root
+ my_progname
+ get_charset_by_csname
+ print_defaults
+ find_type
+ strxnmov
+ strend
+ my_fopen
+ my_fclose
+ unpack_filename
+ str2int
+ int10_to_str
+ longlong10_to_str
+ my_snprintf_8bit
+ alloc_root
+ free_root
+ my_read
diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp
index 4db155e6ee6..691c66a074d 100644
--- a/VC++Files/libmysqld/libmysqld.dsp
+++ b/VC++Files/libmysqld/libmysqld.dsp
@@ -43,7 +43,8 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBMYSQLD_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FR /FD /mktyplib203 /win32 # ADD BASE MTL /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../sql" /I "../regex" /I "../bdb/build_win32" /I "../zlib" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FR /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
@@ -68,7 +69,8 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBMYSQLD_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MT /W3 /Gm /Zi /Od /I "../include" /I "../sql" /I "../regex" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /mktyplib203 /win32 # ADD BASE MTL /c
+# ADD CPP /nologo /MT /W3 /Gm /Zi /Od /I "../include" /I "../sql" /I "../regex" /I "../bdb/build_win32" /I "../zlib" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x416 /d "_DEBUG"
# ADD RSC /l 0x416 /d "_DEBUG"
@@ -87,7 +89,11 @@ LINK32=link.exe
# Name "libmysqld - Win32 Debug"
# Begin Source File
-SOURCE=.\client.c
+SOURCE="..\strings\ctype-latin1.c"
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\default.c
# End Source File
# Begin Source File
@@ -111,7 +117,7 @@ SOURCE=..\sql\filesort.cpp
# End Source File
# Begin Source File
-SOURCE=..\libmysql\get_password.c
+SOURCE=..\client\get_password.c
# End Source File
# Begin Source File
@@ -159,6 +165,10 @@ SOURCE=..\sql\init.cpp
# End Source File
# Begin Source File
+SOURCE=..\strings\int2str.c
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\item.cpp
# End Source File
# Begin Source File
@@ -240,6 +250,14 @@ SOURCE=..\sql\mf_iocache.cpp
# End Source File
# Begin Source File
+SOURCE=..\mysys\my_alloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mysys\my_getopt.c
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\net_serv.cpp
# End Source File
# Begin Source File
@@ -384,6 +402,10 @@ SOURCE=..\sql\sql_show.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\sql_state.c
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\sql_string.cpp
# End Source File
# Begin Source File
@@ -412,6 +434,26 @@ SOURCE=..\sql\sql_yacc.cpp
# End Source File
# Begin Source File
+SOURCE=..\strings\str2int.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strcend.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strcont.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strinstr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\strings\strxnmov.c
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\table.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/myisam/myisam.dsp b/VC++Files/myisam/myisam.dsp
index 40d157a1c75..38cac3a0aba 100644
--- a/VC++Files/myisam/myisam.dsp
+++ b/VC++Files/myisam/myisam.dsp
@@ -193,6 +193,10 @@ SOURCE=.\mi_panic.c
# End Source File
# Begin Source File
+SOURCE=.\mi_preload.c
+# End Source File
+# Begin Source File
+
SOURCE=.\mi_range.c
# End Source File
# Begin Source File
diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw
index 9903c91ba1b..d6903f4dbc7 100644
--- a/VC++Files/mysql.dsw
+++ b/VC++Files/mysql.dsw
@@ -726,18 +726,9 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
- Project_Dep_Name strings
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name mysys
- End Project Dependency
- Begin Project Dependency
Project_Dep_Name libmysqld
End Project Dependency
Begin Project Dependency
- Project_Dep_Name vio
- End Project Dependency
- Begin Project Dependency
Project_Dep_Name zlib
End Project Dependency
}}}
diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp
index 6aab591120a..8192623f957 100644
--- a/VC++Files/sql/mysqld.dsp
+++ b/VC++Files/sql/mysqld.dsp
@@ -28,7 +28,7 @@ CFG=mysqld - Win32 Release
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=xicl6.exe
+CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "mysqld - Win32 Release"
@@ -45,14 +45,14 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../zlib" /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x410 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=xilink6.exe
+LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld-opt.exe"
# SUBTRACT LINK32 /debug
@@ -71,14 +71,14 @@ LINK32=xilink6.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../regex" /I "../bdb/build_win32" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c
# SUBTRACT CPP /Fr /YX
# ADD BASE RSC /l 0x410 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=xilink6.exe
+LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\vio.lib ..\lib_debug\isam.lib ..\lib_debug\merge.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\bdb.lib ..\lib_debug\innodb.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqld.exe" /pdbtype:sept
@@ -98,14 +98,14 @@ LINK32=xilink6.exe
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G5 /MT /W3 /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__WIN32__" /D "DBUG_OFF" /FD /c
# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x410 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=xilink6.exe
+LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\dbug.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\zlib.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-nt.exe"
# SUBTRACT LINK32 /pdb:none /debug
@@ -126,14 +126,14 @@ LINK32=xilink6.exe
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /FD /c
# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../bdb/build_win32" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=xilink6.exe
+LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-nt.exe"
# SUBTRACT BASE LINK32 /pdb:none /debug
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-max-nt.exe"
@@ -155,14 +155,14 @@ LINK32=xilink6.exe
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /FD /c
# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../bdb/build_win32" /D "NDEBUG" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=xilink6.exe
+LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /out:"../client_release/mysqld-opt.exe"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\vio.lib ..\lib_release\isam.lib ..\lib_release\merge.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld-max.exe"
# SUBTRACT LINK32 /debug
@@ -893,6 +893,10 @@ SOURCE=.\sql_class.cpp
# End Source File
# Begin Source File
+SOURCE=.\sql_client.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_crypt.cpp
# End Source File
# Begin Source File
diff --git a/acinclude.m4 b/acinclude.m4
index 269b505386c..94e70f2b892 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -868,9 +868,9 @@ AC_SUBST(orbit_idl)
AC_DEFUN([MYSQL_CHECK_ISAM], [
AC_ARG_WITH([isam], [
- --without-isam Disable the ISAM table type],
+ --with-isam Enable the ISAM table type],
[with_isam="$withval"],
- [with_isam=yes])
+ [with_isam=no])
isam_libs=
if test X"$with_isam" = X"yes"
@@ -1113,7 +1113,7 @@ AC_DEFUN([MYSQL_CHECK_BDB_VERSION], [
# mysql_bdb=a
# fi
-dbl RAM:
+dnl RAM:
want_bdb_version="4.1.24"
bdb_version_ok=yes
diff --git a/client/get_password.c b/client/get_password.c
index 9928d24de32..f187c113644 100644
--- a/client/get_password.c
+++ b/client/get_password.c
@@ -23,7 +23,6 @@
#include "mysql.h"
#include <m_string.h>
#include <m_ctype.h>
-#include <dbug.h>
#if defined(HAVE_BROKEN_GETPASS) && !defined(HAVE_GETPASSPHRASE)
#undef HAVE_GETPASS
diff --git a/client/mysql.cc b/client/mysql.cc
index 45b0e4bf2ea..ed0c1bf102b 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1085,7 +1085,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
out=line;
}
}
- else if (*ml_comment && !*in_string && inchar == '*' && *(pos+1) == '/')
+ else if (*ml_comment && inchar == '*' && *(pos + 1) == '/')
{
pos++;
*ml_comment= 0;
@@ -1093,11 +1093,12 @@ static bool add_line(String &buffer,char *line,char *in_string,
else
{ // Add found char to buffer
if (inchar == *in_string)
- *in_string=0;
- else if (!*in_string && (inchar == '\'' || inchar == '"' || inchar == '`'))
- *in_string=(char) inchar;
- if (!(*ml_comment))
- *out++ = (char) inchar;
+ *in_string= 0;
+ else if (!*ml_comment && !*in_string &&
+ (inchar == '\'' || inchar == '"' || inchar == '`'))
+ *in_string= (char) inchar;
+ if (!*ml_comment)
+ *out++= (char) inchar;
}
}
if (out != line || !buffer.is_empty())
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 03a8206276f..18dd7a26f2d 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -42,7 +42,7 @@
**********************************************************************/
-#define MTEST_VERSION "1.28"
+#define MTEST_VERSION "1.29"
#include <my_global.h>
#include <mysql_embed.h>
@@ -63,9 +63,10 @@
#include <errno.h>
#include <violite.h>
-#define MAX_QUERY 65536
+#define MAX_QUERY 65536
+#define MAX_COLUMNS 256
#define PAD_SIZE 128
-#define MAX_CONS 1024
+#define MAX_CONS 128
#define MAX_INCLUDE_DEPTH 16
#define LAZY_GUESS_BUF_SIZE 8192
#define INIT_Q_LINES 1024
@@ -192,7 +193,7 @@ Q_SYNC_WITH_MASTER,
Q_SYNC_SLAVE_WITH_MASTER,
Q_ERROR,
Q_SEND, Q_REAP,
-Q_DIRTY_CLOSE, Q_REPLACE,
+Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
Q_PING, Q_EVAL,
Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
@@ -246,6 +247,7 @@ const char *command_names[]=
"reap",
"dirty_close",
"replace_result",
+ "replace_column",
"ping",
"eval",
"rpl_probe",
@@ -290,7 +292,7 @@ VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw,
int eval_expr(VAR* v, const char *p, const char** p_end);
static int read_server_arguments(const char *name);
-/* Definitions for replace */
+/* Definitions for replace result */
typedef struct st_pointer_array { /* when using array-strings */
TYPELIB typelib; /* Pointer to strings */
@@ -318,6 +320,13 @@ static char *out_buff;
static uint out_length;
static int eval_result = 0;
+/* For column replace */
+char *replace_column[MAX_COLUMNS];
+uint max_replace_column= 0;
+
+static void get_replace_column(struct st_query *q);
+static void free_replace_column();
+
/* Disable functions that only exist in MySQL 4.0 */
#if MYSQL_VERSION_ID < 40000 || defined(EMBEDDED_LIBRARY)
void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
@@ -338,7 +347,6 @@ static const char *embedded_server_groups[] = {
NullS
};
-
static void do_eval(DYNAMIC_STRING* query_eval, const char* query)
{
const char* p;
@@ -433,6 +441,7 @@ static void free_used_memory()
delete_dynamic(&q_lines);
dynstr_free(&ds_res);
free_replace();
+ free_replace_column();
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
free_defaults(default_argv);
mysql_server_end();
@@ -2048,27 +2057,35 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
dynstr_append_mem(ds, val, len);
}
+
/*
Append all results to the dynamic string separated with '\t'
+ Values may be converted with 'replace_column'
*/
static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
{
MYSQL_ROW row;
- int num_fields= mysql_num_fields(res);
+ uint num_fields= mysql_num_fields(res);
unsigned long *lengths;
while ((row = mysql_fetch_row(res)))
{
- int i;
+ uint i;
lengths = mysql_fetch_lengths(res);
for (i = 0; i < num_fields; i++)
{
const char *val= row[i];
ulonglong len= lengths[i];
+
+ if (i < max_replace_column && replace_column[i])
+ {
+ val= replace_column[i];
+ len= strlen(val);
+ }
if (!val)
{
- val = "NULL";
- len = 4;
+ val= "NULL";
+ len= 4;
}
if (i)
dynstr_append_mem(ds, "\t", 1);
@@ -2076,6 +2093,7 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
}
dynstr_append_mem(ds, "\n", 1);
}
+ free_replace_column();
}
@@ -2539,6 +2557,9 @@ int main(int argc, char **argv)
case Q_REPLACE:
get_replace(q);
break;
+ case Q_REPLACE_COLUMN:
+ get_replace_column(q);
+ break;
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
case Q_SYNC_WITH_MASTER: do_sync_with_master(q); break;
case Q_SYNC_SLAVE_WITH_MASTER:
@@ -3357,3 +3378,60 @@ static void free_replace_buffer(void)
{
my_free(out_buff,MYF(MY_WME));
}
+
+
+/****************************************************************************
+ Replace results for a column
+*****************************************************************************/
+
+static void free_replace_column()
+{
+ uint i;
+ for (i=0 ; i < max_replace_column ; i++)
+ {
+ if (replace_column[i])
+ {
+ my_free(replace_column[i], 0);
+ replace_column[i]= 0;
+ }
+ }
+ max_replace_column= 0;
+}
+
+/*
+ Get arguments for replace_columns. The syntax is:
+ replace-column column_number to_string [column_number to_string ...]
+ Where each argument may be quoted with ' or "
+ A argument may also be a variable, in which case the value of the
+ variable is replaced.
+*/
+
+static void get_replace_column(struct st_query *q)
+{
+ char *from=q->first_argument;
+ char *buff,*start;
+ DBUG_ENTER("get_replace_columns");
+
+ free_replace_column();
+ if (!*from)
+ die("Missing argument in %s\n", q->query);
+
+ /* Allocate a buffer for results */
+ start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
+ while (*from)
+ {
+ char *to;
+ uint column_number;
+
+ to= get_string(&buff, &from, q);
+ if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
+ die("Wrong column number to replace_columns in %s\n", q->query);
+ if (!*from)
+ die("Wrong number of arguments to replace in %s\n", q->query);
+ to= get_string(&buff, &from, q);
+ my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
+ replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
+ set_if_bigger(max_replace_column, column_number);
+ }
+ my_free(start, MYF(0));
+}
diff --git a/configure.in b/configure.in
index bddeeb6c989..63b33e391b2 100644
--- a/configure.in
+++ b/configure.in
@@ -2176,8 +2176,8 @@ AC_ARG_WITH(libedit,
[ with_libedit=undefined ]
)
-compile_readline= no
-compile_libedit= no
+compile_readline="no"
+compile_libedit="no"
if [test "$with_libedit" = "yes"] && [test "$with_readline" = "yes"]
then
@@ -2820,6 +2820,7 @@ AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile dnl
libmysql_r/Makefile libmysqld/Makefile libmysqld/examples/Makefile dnl
libmysql/Makefile client/Makefile dnl
pstack/Makefile pstack/aout/Makefile sql/Makefile sql/share/Makefile dnl
+ sql-common/Makefile dnl
merge/Makefile dbug/Makefile scripts/Makefile dnl
include/Makefile sql-bench/Makefile tools/Makefile dnl
tests/Makefile Docs/Makefile support-files/Makefile dnl
@@ -2840,6 +2841,7 @@ echo "Remember to check the platform specific part of the reference manual for"
echo "hints about installing MySQL on your platform. Also have a look at the"
echo "files in the Docs directory."
echo
-# The following text is checked in ./Do-compile to se that the configure ends.
+# The following text is checked in ./Do-compile to verify that configure
+# ended sucessfully - don't remove it.
echo "Thank you for choosing MySQL!"
echo
diff --git a/include/Makefile.am b/include/Makefile.am
index 3a197c310aa..2ec06d71fbe 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -21,7 +21,8 @@ pkginclude_HEADERS = my_dbug.h m_string.h my_sys.h my_list.h my_xml.h \
my_semaphore.h my_pthread.h my_no_pthread.h raid.h \
errmsg.h my_global.h my_net.h my_alloc.h \
my_getopt.h sslopt-longopts.h my_dir.h typelib.h \
- sslopt-vars.h sslopt-case.h $(BUILT_SOURCES)
+ sslopt-vars.h sslopt-case.h sql_common.h \
+ sql_state.h $(BUILT_SOURCES)
noinst_HEADERS = config-win.h config-os2.h config-netware.h \
nisam.h heap.h merge.h my_bitmap.h\
myisam.h myisampack.h myisammrg.h ft_global.h\
diff --git a/include/my_base.h b/include/my_base.h
index ac41d9e50ef..8c5496cc2e0 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -123,7 +123,8 @@ enum ha_extra_function {
HA_EXTRA_NO_IGNORE_DUP_KEY,
HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE, /* Cursor will not be used for update */
HA_EXTRA_PREPARE_FOR_DELETE,
- HA_EXTRA_PREPARE_FOR_UPDATE /* Remove read cache if problems */
+ HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */
+ HA_EXTRA_PRELOAD_BUFFER_SIZE /* Set buffer size for preloading */
};
/* The following is parameter to ha_panic() */
@@ -256,6 +257,7 @@ enum ha_base_keytype {
#define HA_ERR_CANNOT_ADD_FOREIGN 150 /* Cannot add a foreign key constr. */
#define HA_ERR_NO_REFERENCED_ROW 151 /* Cannot add a child row */
#define HA_ERR_ROW_IS_REFERENCED 152 /* Cannot delete a parent row */
+#define HA_ERR_NON_UNIQUE_BLOCK_SIZE 153 /* Non unique key block size */
/* Other constants */
diff --git a/include/my_getopt.h b/include/my_getopt.h
index 3b4551b445e..148238f8d1b 100644
--- a/include/my_getopt.h
+++ b/include/my_getopt.h
@@ -17,7 +17,12 @@
C_MODE_START
enum get_opt_var_type { GET_NO_ARG, GET_BOOL, GET_INT, GET_UINT, GET_LONG,
- GET_ULONG, GET_LL, GET_ULL, GET_STR, GET_STR_ALLOC };
+ GET_ULONG, GET_LL, GET_ULL, GET_STR, GET_STR_ALLOC
+ };
+
+#define GET_ASK_ADDR 128
+#define GET_TYPE_MASK 127
+
enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG };
struct my_option
@@ -48,6 +53,8 @@ extern int handle_options (int *argc, char ***argv,
char *));
extern void my_print_help(const struct my_option *options);
extern void my_print_variables(const struct my_option *options);
+extern void my_getopt_register_get_addr(gptr* (*func_addr)(const char *, uint,
+ const struct my_option *));
ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp);
my_bool getopt_compare_strings(const char *s, const char *t, uint length);
diff --git a/include/my_sys.h b/include/my_sys.h
index b4fc20e8471..7ea9f63a50f 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -501,6 +501,12 @@ my_off_t my_b_append_tell(IO_CACHE* info);
#define my_b_bytes_in_cache(info) (uint) (*(info)->current_end - \
*(info)->current_pos)
+/* key_cache_variables */
+typedef struct st_keycache
+{
+ ulonglong size;
+} KEY_CACHE;
+
#include <my_alloc.h>
/* Prototypes for mysys and my_func functions */
@@ -643,6 +649,8 @@ extern int init_key_cache(ulong use_mem);
extern int resize_key_cache(ulong use_mem);
extern byte *key_cache_read(File file,my_off_t filepos,byte* buff,uint length,
uint block_length,int return_buffer);
+extern int key_cache_insert(File file, my_off_t filepos,
+ byte *buff, uint length);
extern int key_cache_write(File file,my_off_t filepos,byte* buff,uint length,
uint block_length,int force_write);
extern int flush_key_blocks(int file, enum flush_type type);
diff --git a/include/myisam.h b/include/myisam.h
index 33aa6aa3f31..e85d3057672 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -410,6 +410,7 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map,
int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows);
void mi_flush_bulk_insert(MI_INFO *info, uint inx);
void mi_end_bulk_insert(MI_INFO *info);
+int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves);
#ifdef __cplusplus
}
diff --git a/include/mysql.h b/include/mysql.h
index 337e080e4cc..27d6b03bd0b 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -266,6 +266,7 @@ typedef struct st_mysql
my_bool free_me; /* If free in mysql_close */
my_ulonglong insert_id; /* id if insert on table with NEXTNR */
unsigned int last_errno;
+ unsigned int server_status;
char *last_error; /* Used by embedded server */
char sqlstate[SQLSTATE_LENGTH+1]; /* Used by embedded server */
} MYSQL;
@@ -565,6 +566,7 @@ unsigned long STDCALL mysql_param_count(MYSQL_STMT * stmt);
my_bool STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt);
+my_bool STDCALL mysql_stmt_reset(MYSQL_STMT * stmt);
my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt);
unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt);
const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt);
diff --git a/include/mysql_com.h b/include/mysql_com.h
index e87001ff27d..5eb59a1c7ab 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -44,6 +44,7 @@ enum enum_server_command
COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT,
+ COM_RESET_STMT,
COM_END /* Must be last */
};
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index ccccb188037..0468663239b 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -281,7 +281,10 @@
#define ER_WARN_DATA_OUT_OF_RANGE 1262
#define ER_WARN_DATA_TRUNCATED 1263
#define ER_WARN_USING_OTHER_HANDLER 1264
-#define ER_CANT_AGGREGATE_COLLATIONS 1265
+#define ER_CANT_AGGREGATE_2COLLATIONS 1265
#define ER_DROP_USER 1266
#define ER_REVOKE_GRANTS 1267
-#define ER_ERROR_MESSAGES 266
+#define ER_CANT_AGGREGATE_3COLLATIONS 1268
+#define ER_CANT_AGGREGATE_NCOLLATIONS 1269
+#define ER_VARIABLE_IS_NOT_STRUCT 1270
+#define ER_ERROR_MESSAGES 271
diff --git a/include/sql_state.h b/include/sql_state.h
index c998beaf578..26568ac3e0d 100644
--- a/include/sql_state.h
+++ b/include/sql_state.h
@@ -36,8 +36,8 @@ ER_CON_COUNT_ERROR, "08004", "",
ER_BAD_HOST_ERROR, "08S01", "",
ER_HANDSHAKE_ERROR, "08S01", "",
ER_DBACCESS_DENIED_ERROR, "42000", "",
-ER_ACCESS_DENIED_ERROR, "42000", "28000",
-ER_NO_DB_ERROR, "42000", "",
+ER_ACCESS_DENIED_ERROR, "28000", "",
+ER_NO_DB_ERROR, "3D000", "",
ER_UNKNOWN_COM_ERROR, "08S01", "",
ER_BAD_NULL_ERROR, "23000", "",
ER_BAD_DB_ERROR, "42000", "",
@@ -68,7 +68,7 @@ ER_BLOB_USED_AS_KEY, "42000", "S1009",
ER_TOO_BIG_FIELDLENGTH, "42000", "S1009",
ER_WRONG_AUTO_KEY, "42000", "S1009",
ER_FORCING_CLOSE, "08S01", "",
-ER_IPSOCK_ERROR, "088S01", "",
+ER_IPSOCK_ERROR, "08S01", "",
ER_NO_SUCH_INDEX, "42S12", "S1009",
ER_WRONG_FIELD_TERMINATORS, "42000", "S1009",
ER_BLOBS_AND_NO_TERMINATED, "42000", "S1009",
diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am
index 128f1c03967..0125bd2b98d 100644
--- a/libmysql/Makefile.am
+++ b/libmysql/Makefile.am
@@ -28,6 +28,7 @@ libmysqlclient_la_SOURCES = $(target_sources)
libmysqlclient_la_LIBADD = $(target_libadd)
libmysqlclient_la_LDFLAGS = $(target_ldflags)
EXTRA_DIST = Makefile.shared
+noinst_HEADERS = client_settings.h
# This is called from the toplevel makefile
link_sources:
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 771278c1dbb..1461d2fa128 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -3316,6 +3316,7 @@ mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row)
}
else
DBUG_PRINT("exit", ("stmt doesn't contain any resultset"));
+ DBUG_VOID_RETURN;
}
@@ -3422,6 +3423,28 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
}
/*
+ Reset the statement buffers in server
+*/
+
+my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
+{
+ char buff[MYSQL_STMT_HEADER];
+ MYSQL *mysql;
+ DBUG_ENTER("mysql_stmt_reset");
+ DBUG_ASSERT(stmt != 0);
+
+ mysql= stmt->mysql->last_used_con;
+ int4store(buff, stmt->stmt_id); /* Send stmt id to server */
+ if (advanced_command(mysql, COM_RESET_STMT,buff,MYSQL_STMT_HEADER,0,0,1))
+ {
+ set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
+ mysql->net.sqlstate);
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+/*
Return statement error code
*/
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 8c97ef45aa3..51869eacc4b 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -2,8 +2,43 @@ LIBRARY LIBMYSQL
DESCRIPTION 'MySQL 4.1 Client Library'
VERSION 6.0
EXPORTS
+ _dig_vec
+ bmove_upp
+ delete_dynamic
+ free_defaults
+ getopt_compare_strings
+ getopt_ull_limit_value
+ handle_options
+ init_dynamic_array
+ insert_dynamic
+ int2str
+ is_prefix
+ list_add
+ list_delete
+ load_defaults
+ max_allowed_packet
+ my_end
+ my_getopt_print_errors
+ my_init
+ my_malloc
+ my_memdup
+ my_no_flags_free
+ my_path
+ my_print_help
+ my_print_variables
+ my_realloc
+ my_strdup
+ my_thread_end
+ my_thread_init
+ myodbc_remove_escape
mysql_affected_rows
+ mysql_autocommit
+ mysql_bind_param
+ mysql_bind_result
+ mysql_change_user
+ mysql_character_set_name
mysql_close
+ mysql_commit
mysql_data_seek
mysql_debug
mysql_dump_debug_info
@@ -11,6 +46,9 @@ EXPORTS
mysql_errno
mysql_error
mysql_escape_string
+ mysql_execute
+ mysql_fetch
+ mysql_fetch_column
mysql_fetch_field
mysql_fetch_field_direct
mysql_fetch_fields
@@ -32,113 +70,55 @@ EXPORTS
mysql_list_fields
mysql_list_processes
mysql_list_tables
+ mysql_more_results
+ mysql_next_result
mysql_num_fields
mysql_num_rows
mysql_odbc_escape_string
mysql_options
+ mysql_param_count
+ mysql_param_result
mysql_ping
+ mysql_prepare
+ mysql_prepare_result
mysql_query
+ mysql_read_query_result
mysql_real_connect
+ mysql_real_escape_string
mysql_real_query
mysql_refresh
+ mysql_rollback
mysql_row_seek
mysql_row_tell
mysql_select_db
+ mysql_send_long_data
+ mysql_send_query
mysql_shutdown
+ mysql_ssl_set
mysql_stat
+ mysql_stmt_affected_rows
+ mysql_stmt_close
+ mysql_stmt_reset
+ mysql_stmt_data_seek
+ mysql_stmt_errno
+ mysql_stmt_error
+ mysql_stmt_free_result
+ mysql_stmt_num_rows
+ mysql_stmt_row_seek
+ mysql_stmt_row_tell
+ mysql_stmt_store_result
mysql_store_result
mysql_thread_id
+ mysql_thread_safe
mysql_use_result
- bmove_upp
- delete_dynamic
- _dig_vec
- init_dynamic_array
- insert_dynamic
- int2str
- is_prefix
- list_add
- list_delete
- max_allowed_packet
- my_init
- my_end
- my_strdup
- my_malloc
- my_memdup
- my_no_flags_free
- my_realloc
- my_thread_end
- my_thread_init
+ mysql_warning_count
net_buffer_length
set_dynamic
strcend
+ strcont
strdup_root
strfill
strinstr
strmake
strmov
strxmov
- myodbc_remove_escape
- mysql_thread_safe
- mysql_character_set_name
- mysql_change_user
- mysql_send_query
- mysql_read_query_result
- mysql_real_escape_string
- mysql_ssl_set
- mysql_real_connect
- mysql_master_query
- mysql_master_send_query
- mysql_slave_query
- mysql_slave_send_query
- mysql_enable_rpl_parse
- mysql_disable_rpl_parse
- mysql_rpl_parse_enabled
- mysql_enable_reads_from_master
- mysql_disable_reads_from_master
- mysql_reads_from_master_enabled
- mysql_rpl_query_type
- mysql_rpl_probe
- mysql_set_master
- mysql_add_slave
- my_getopt_print_errors
- handle_options
- my_print_help
- my_print_variables
- getopt_ull_limit_value
- getopt_compare_strings
- mysql_warning_count
- mysql_prepare
- mysql_execute
- mysql_param_count
- mysql_bind_param
- mysql_bind_result
- mysql_param_result
- mysql_prepare_result
- mysql_stmt_close
- mysql_stmt_free_result
- mysql_stmt_error
- mysql_stmt_errno
- mysql_fetch
- mysql_fetch_column
- mysql_send_long_data
- mysql_next_result
- mysql_stmt_affected_rows
- mysql_stmt_store_result
- mysql_stmt_data_seek
- mysql_stmt_row_seek
- mysql_stmt_row_tell
- mysql_stmt_num_rows
- mysql_more_results
- mysql_commit
- mysql_rollback
- mysql_autocommit
- load_defaults
- free_defaults
- my_path
-
-
-
-
-
-
-
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index a2d69b30c0d..ba2dfd68c00 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -49,6 +49,8 @@
static my_bool mysql_client_init=0;
uint mysql_port=0;
my_string mysql_unix_port=0;
+const char *not_error_sqlstate= "00000";
+
const char *sql_protocol_names_lib[] =
{ "TCP", "SOCKET", "PIPE", "MEMORY",NullS };
TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
@@ -516,6 +518,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
client_flag&= ~CLIENT_COMPRESS;
if (db)
client_flag|=CLIENT_CONNECT_WITH_DB;
+ mysql->server_status= SERVER_STATUS_AUTOCOMMIT;
if (mysql->options.init_commands)
{
@@ -1040,9 +1043,9 @@ mysql_list_fields(MYSQL *mysql __attribute__((unused)), const char *table __attr
/* List all running processes (threads) in server */
MYSQL_RES * STDCALL
-mysql_list_processes(MYSQL *mysql)
+mysql_list_processes(MYSQL *mysql __attribute__((unused)))
{
-#ifdef DUMMY
+#ifdef FOR_THE_FUTURE
MYSQL_DATA *fields;
uint field_count;
uchar *pos;
@@ -1063,7 +1066,7 @@ mysql_list_processes(MYSQL *mysql)
mysql->status=MYSQL_STATUS_GET_RESULT;
mysql->field_count=field_count;
DBUG_RETURN(mysql_store_result(mysql));
-#endif /*DUMMY*/
+#endif /* FOR_THE_FUTURE */
return 0;
}
@@ -1535,3 +1538,96 @@ myodbc_remove_escape(MYSQL *mysql,char *name)
}
*to=0;
}
+
+
+/********************************************************************
+ Transactional APIs
+*********************************************************************/
+
+/*
+ Commit the current transaction
+*/
+
+my_bool STDCALL mysql_commit(MYSQL * mysql)
+{
+ DBUG_ENTER("mysql_commit");
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "commit", 6));
+}
+
+/*
+ Rollback the current transaction
+*/
+
+my_bool STDCALL mysql_rollback(MYSQL * mysql)
+{
+ DBUG_ENTER("mysql_rollback");
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "rollback", 8));
+}
+
+
+/*
+ Set autocommit to either true or false
+*/
+
+my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode)
+{
+ DBUG_ENTER("mysql_autocommit");
+ DBUG_PRINT("enter", ("mode : %d", auto_mode));
+
+ if (auto_mode) /* set to true */
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=1", 16));
+ DBUG_RETURN((my_bool) mysql_real_query(mysql, "set autocommit=0", 16));
+}
+
+
+/********************************************************************
+ Multi query execution + SPs APIs
+*********************************************************************/
+
+/*
+ Returns if there are any more query results exists to be read using
+ mysql_next_result()
+*/
+
+my_bool STDCALL mysql_more_results(MYSQL *mysql)
+{
+ my_bool res;
+ DBUG_ENTER("mysql_more_results");
+
+ res= ((mysql->server_status & SERVER_MORE_RESULTS_EXISTS) ?
+ 1: 0);
+ DBUG_PRINT("exit",("More results exists ? %d", res));
+ DBUG_RETURN(res);
+}
+
+
+/*
+ Reads and returns the next query results
+*/
+
+my_bool STDCALL mysql_next_result(MYSQL *mysql)
+{
+ DBUG_ENTER("mysql_next_result");
+
+ mysql->last_error[0]= 0;
+ mysql->last_errno= 0;
+ strmov(mysql->sqlstate, not_error_sqlstate);
+ mysql->affected_rows= ~(my_ulonglong) 0;
+
+ if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
+ DBUG_RETURN(mysql_read_query_result(mysql));
+
+ DBUG_RETURN(0);
+}
+
+
+my_bool STDCALL
+mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
+ const char *key __attribute__((unused)),
+ const char *cert __attribute__((unused)),
+ const char *ca __attribute__((unused)),
+ const char *capath __attribute__((unused)),
+ const char *cipher __attribute__((unused)))
+{
+ return 0;
+}
diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def
index c6615ee971c..c3f757b5f1a 100644
--- a/libmysqld/libmysqld.def
+++ b/libmysqld/libmysqld.def
@@ -1,65 +1,130 @@
LIBRARY LIBMYSQLD
-DESCRIPTION 'MySQL 4.0 Embedded Server Library'
-VERSION 4.0
+DESCRIPTION 'MySQL 4.1 Embedded Server Library'
+VERSION 4.1
EXPORTS
- mysql_server_end
- mysql_server_init
- mysql_use_result
- mysql_thread_safe
- mysql_thread_id
- mysql_store_result
- mysql_stat
- mysql_shutdown
- mysql_select_db
- mysql_row_tell
- mysql_row_seek
- mysql_real_query
- mysql_real_connect
- mysql_query
- mysql_ping
- mysql_options
- mysql_num_rows
- mysql_num_fields
- mysql_list_tables
- mysql_list_processes
- mysql_list_fields
- mysql_list_dbs
- mysql_kill
- mysql_insert_id
- mysql_init
- mysql_info
- mysql_get_server_info
- mysql_get_proto_info
- mysql_get_host_info
- mysql_get_client_info
- mysql_free_result
- mysql_field_tell
- mysql_field_count
- mysql_field_seek
- mysql_fetch_row
- mysql_fetch_lengths
- mysql_fetch_fields
- mysql_fetch_field_direct
- mysql_fetch_field
- mysql_escape_string
- mysql_real_escape_string
- mysql_error
- mysql_errno
- mysql_eof
- mysql_dump_debug_info
- mysql_drop_db
- mysql_debug
- mysql_data_seek
- mysql_create_db
- mysql_character_set_name
+ _dig_vec
+ bmove_upp
+ delete_dynamic
+ free_defaults
+ getopt_compare_strings
+ getopt_ull_limit_value
+ handle_options
+ init_dynamic_array
+ insert_dynamic
+ int2str
+ is_prefix
+ list_add
+ list_delete
+ load_defaults
+ max_allowed_packet
+ my_end
+ my_getopt_print_errors
+ my_init
+ my_malloc
+ my_memdup
+ my_no_flags_free
+ my_path
+ my_print_help
+ my_print_variables
+ my_realloc
+ my_strdup
+ my_thread_end
+ my_thread_init
+ myodbc_remove_escape
+ mysql_affected_rows
+ mysql_autocommit
mysql_change_user
- mysql_connect
+ mysql_character_set_name
mysql_close
- mysql_affected_rows
- mysql_thread_init
- mysql_thread_end
- mysql_send_query
+ mysql_commit
+ mysql_data_seek
+ mysql_debug
+ mysql_dump_debug_info
+ mysql_eof
+ mysql_errno
+ mysql_error
+ mysql_escape_string
+ mysql_fetch_field
+ mysql_fetch_field_direct
+ mysql_fetch_fields
+ mysql_fetch_lengths
+ mysql_fetch_row
+ mysql_field_count
+ mysql_field_seek
+ mysql_field_tell
+ mysql_free_result
+ mysql_get_client_info
+ mysql_get_host_info
+ mysql_get_proto_info
+ mysql_get_server_info
+ mysql_info
+ mysql_init
+ mysql_insert_id
+ mysql_kill
+ mysql_list_dbs
+ mysql_list_fields
+ mysql_list_processes
+ mysql_list_tables
+ mysql_more_results
+ mysql_next_result
+ mysql_num_fields
+ mysql_num_rows
+ mysql_odbc_escape_string
+ mysql_options
+ mysql_ping
+ mysql_query
mysql_read_query_result
+ mysql_real_connect
+ mysql_real_escape_string
+ mysql_real_query
mysql_refresh
- mysql_odbc_escape_string
- myodbc_remove_escape
+ mysql_rollback
+ mysql_row_seek
+ mysql_row_tell
+ mysql_select_db
+ mysql_send_query
+ mysql_shutdown
+ mysql_ssl_set
+ mysql_stat
+ mysql_store_result
+ mysql_sqlstate
+ mysql_thread_id
+ mysql_thread_safe
+ mysql_use_result
+ mysql_warning_count
+ net_buffer_length
+ set_dynamic
+ strcend
+ strcont
+ strdup_root
+ strfill
+ strinstr
+ strmake
+ strmov
+ strxmov
+ mysql_server_end
+ mysql_server_init
+ get_tty_password
+ sql_protocol_typelib
+ mysql_get_server_version
+ mysql_sqlstate
+ charsets_dir
+ disabled_my_option
+ my_charset_latin1
+ init_alloc_root
+ my_progname
+ get_charset_by_csname
+ print_defaults
+ find_type
+ strxnmov
+ strend
+ my_fopen
+ my_fclose
+ unpack_filename
+ str2int
+ int10_to_str
+ longlong10_to_str
+ my_snprintf_8bit
+ alloc_root
+ free_root
+ my_read
diff --git a/myisam/Makefile.am b/myisam/Makefile.am
index f8225868d96..d4cd953ac66 100644
--- a/myisam/Makefile.am
+++ b/myisam/Makefile.am
@@ -47,6 +47,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
mi_range.c mi_dbug.c mi_checksum.c mi_log.c \
mi_changed.c mi_static.c mi_delete_all.c \
mi_delete_table.c mi_rename.c mi_check.c \
+ mi_preload.c \
ft_parser.c ft_stopwords.c ft_static.c \
ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c \
rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c
diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c
index 75057dd4e6a..4b71f3a867b 100644
--- a/myisam/mi_extra.c
+++ b/myisam/mi_extra.c
@@ -367,6 +367,9 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
if (!share->state.header.uniques)
info->opt_flag|= OPT_NO_ROWS;
break;
+ case HA_EXTRA_PRELOAD_BUFFER_SIZE:
+ info->preload_buff_size= *((ulong *) extra_arg);
+ break;
case HA_EXTRA_KEY_CACHE:
case HA_EXTRA_NO_KEY_CACHE:
default:
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 178365577aa..5d8f384a5af 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -335,7 +335,6 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
{ /* 4.0 compatibility code, to be removed in 5.0 */
share->keyinfo[i].seg=pos-FT_SEGS;
share->keyinfo[i].keysegs-=FT_SEGS;
- share->state.header.fulltext_keys++;
}
else
{
diff --git a/myisam/mi_preload.c b/myisam/mi_preload.c
new file mode 100644
index 00000000000..a5d9bec160e
--- /dev/null
+++ b/myisam/mi_preload.c
@@ -0,0 +1,114 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Preload indexes into key cache
+*/
+
+#include "myisamdef.h"
+
+
+/*
+ Preload pages of the index file for a table into the key cache
+
+ SYNOPSIS
+ mi_preload()
+ info open table
+ map map of indexes to preload into key cache
+ ignore_leaves only non-leaves pages are to be preloaded
+
+ RETURN VALUE
+ 0 if a success. error code - otherwise.
+
+ NOTES.
+ At present pages for all indexes are preloaded.
+ In future only pages for indexes specified in the key_map parameter
+ of the table will be preloaded.
+*/
+
+int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
+{
+ uint i;
+ ulong length, block_length= 0;
+ uchar *buff= NULL;
+ MYISAM_SHARE* share= info->s;
+ uint keys= share->state.header.keys;
+ MI_KEYDEF *keyinfo= share->keyinfo;
+ my_off_t key_file_length= share->state.state.key_file_length;
+ my_off_t pos= share->base.keystart;
+ DBUG_ENTER("mi_preload");
+
+ if (!keys || !key_map || key_file_length == pos)
+ DBUG_RETURN(0);
+
+ block_length= keyinfo[0].block_length;
+
+ /* Check whether all indexes use the same block size */
+ for (i= 1 ; i < keys ; i++)
+ {
+ if (keyinfo[i].block_length != block_length)
+ DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE);
+ }
+
+ length= info->preload_buff_size/block_length * block_length;
+ set_if_bigger(length, block_length);
+
+ if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME))))
+ DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM);
+
+ if (flush_key_blocks(share->kfile, FLUSH_RELEASE))
+ goto err;
+
+ do
+ {
+ /* Read the next block of index file into the preload buffer */
+ if ((my_off_t) length > (key_file_length-pos))
+ length= (ulong) (key_file_length-pos);
+ if (my_pread(share->kfile, (byte*) buff, length, pos, MYF(MY_FAE)))
+ goto err;
+
+ if (ignore_leaves)
+ {
+ uchar *end= buff+length;
+ do
+ {
+ if (mi_test_if_nod(buff))
+ {
+ if (key_cache_insert(share->kfile, pos, (byte*) buff, block_length))
+ goto err;
+ }
+ pos+= block_length;
+ }
+ while ((buff+= block_length) != end);
+ buff= end-length;
+ }
+ else
+ {
+ if (key_cache_insert(share->kfile, pos, (byte*) buff, length))
+ goto err;
+ pos+= length;
+ }
+ }
+ while (pos != key_file_length);
+
+ my_free(buff, MYF(0));
+ DBUG_RETURN(0);
+
+err:
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
+ DBUG_RETURN(my_errno= errno);
+}
+
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index 72b2567278e..b7f8d561a5b 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -876,7 +876,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
}
else
{
- if (share->state.header.fulltext_keys && !stopwords_inited++)
+ if (!stopwords_inited++)
ft_init_stopwords();
if (!(param->testflag & T_READONLY))
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index c986c483902..83e28a42797 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -262,6 +262,7 @@ struct st_myisam_info {
int save_lastinx;
LIST open_list;
IO_CACHE rec_cache; /* When cacheing records */
+ uint preload_buff_size; /* When preloading indexes */
myf lock_wait; /* is 0 or MY_DONT_WAIT */
my_bool was_locked; /* Was locked in panic */
my_bool quick_mode;
diff --git a/mysql-test/include/have_openssl_2.inc b/mysql-test/include/have_openssl_2.inc
index 724d295a398..9671ce29573 100644
--- a/mysql-test/include/have_openssl_2.inc
+++ b/mysql-test/include/have_openssl_2.inc
@@ -1,4 +1,4 @@
-- require r/have_openssl_2.require
disable_query_log;
-SHOW STATUS LIKE "SSL_get_cipher";
+SHOW STATUS LIKE "Ssl_cipher";
enable_query_log;
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index cb11e680910..7fa5a0f601f 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -281,3 +281,42 @@ ALTER TABLE t1 DISABLE KEYS;
INSERT DELAYED INTO t1 VALUES(1),(2),(3);
ALTER TABLE t1 ENABLE KEYS;
drop table t1;
+set names koi8r;
+create table t1 (a char(10) character set koi8r);
+insert into t1 values ('ÔÅÓÔ');
+select a,hex(a) from t1;
+a hex(a)
+ÔÅÓÔ D4C5D3D4
+alter table t1 change a a char(10) character set cp1251;
+select a,hex(a) from t1;
+a hex(a)
+ÔÅÓÔ F2E5F1F2
+alter table t1 change a a char(10) binary;
+select a,hex(a) from t1;
+a hex(a)
+òåñò F2E5F1F2
+alter table t1 change a a char(10) character set cp1251;
+select a,hex(a) from t1;
+a hex(a)
+ÔÅÓÔ F2E5F1F2
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+a hex(a)
+ÔÅÓÔ D4C5D3D4
+alter table t1 change a a varchar(10) character set cp1251;
+select a,hex(a) from t1;
+a hex(a)
+ÔÅÓÔ F2E5F1F2
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+a hex(a)
+ÔÅÓÔ D4C5D3D4
+alter table t1 change a a text character set cp1251;
+select a,hex(a) from t1;
+a hex(a)
+ÔÅÓÔ F2E5F1F2
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+a hex(a)
+ÔÅÓÔ D4C5D3D4
+drop table t1;
diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result
index 5553f718799..19f8ffa84d4 100644
--- a/mysql-test/r/auto_increment.result
+++ b/mysql-test/r/auto_increment.result
@@ -111,11 +111,16 @@ insert into t1 set i = null;
select last_insert_id();
last_insert_id()
255
+insert into t1 set i = 254;
+ERROR 23000: Duplicate entry '254' for key 1
+select last_insert_id();
+last_insert_id()
+255
insert into t1 set i = null;
ERROR 23000: Duplicate entry '255' for key 1
select last_insert_id();
last_insert_id()
-255
+0
drop table t1;
create table t1 (i tinyint unsigned not null auto_increment, key (i));
insert into t1 set i = 254;
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index 914e05efa7a..08f148f94c0 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -10,10 +10,10 @@ CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END
3
select CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END;
CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END
-0
+ok
select CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END;
CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END
-0
+ok
select CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end;
CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end
a
@@ -71,3 +71,66 @@ orange
yellow
green
drop table t1;
+SET NAMES latin1;
+CREATE TABLE t1 SELECT
+CASE WHEN 1 THEN _latin1'a' COLLATE latin1_danish_ci ELSE _latin1'a' END AS c1,
+CASE WHEN 1 THEN _latin1'a' ELSE _latin1'a' COLLATE latin1_danish_ci END AS c2,
+CASE WHEN 1 THEN 'a' ELSE 1 END AS c3,
+CASE WHEN 1 THEN 1 ELSE 'a' END AS c4,
+CASE WHEN 1 THEN 'a' ELSE 1.0 END AS c5,
+CASE WHEN 1 THEN 1.0 ELSE 'a' END AS c6,
+CASE WHEN 1 THEN 1 ELSE 1.0 END AS c7,
+CASE WHEN 1 THEN 1.0 ELSE 1 END AS c8
+;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` char(1) character set latin1 collate latin1_danish_ci default NULL,
+ `c2` char(1) character set latin1 collate latin1_danish_ci default NULL,
+ `c3` char(1) default NULL,
+ `c4` char(1) default NULL,
+ `c5` char(3) default NULL,
+ `c6` char(3) default NULL,
+ `c7` double(3,1) default NULL,
+ `c8` double(3,1) default NULL
+) TYPE=MyISAM CHARSET=latin1
+DROP TABLE t1;
+SELECT CASE
+WHEN 1
+THEN _latin1'a' COLLATE latin1_danish_ci
+ELSE _latin1'a' COLLATE latin1_swedish_ci
+END;
+ERROR HY000: Illegal mix of collations (latin1_danish_ci,EXPLICIT) and (latin1_swedish_ci,EXPLICIT) for operation 'case'
+SELECT CASE _latin1'a' COLLATE latin1_general_ci
+WHEN _latin1'a' COLLATE latin1_danish_ci THEN 1
+WHEN _latin1'a' COLLATE latin1_swedish_ci THEN 2
+END;
+ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_danish_ci,EXPLICIT), (latin1_swedish_ci,EXPLICIT) for operation 'case'
+SELECT
+CASE _latin1'a' COLLATE latin1_general_ci WHEN _latin1'A' THEN '1' ELSE 2 END,
+CASE _latin1'a' COLLATE latin1_bin WHEN _latin1'A' THEN '1' ELSE 2 END,
+CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_swedish_ci THEN '1' ELSE 2 END,
+CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_bin THEN '1' ELSE 2 END
+;
+CASE _latin1'a' COLLATE latin1_general_ci WHEN _latin1'A' THEN '1' ELSE 2 END CASE _latin1'a' COLLATE latin1_bin WHEN _latin1'A' THEN '1' ELSE 2 END CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_swedish_ci THEN '1' ELSE 2 END CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_bin THEN '1' ELSE 2 END
+1 2 1 2
+CREATE TABLE t1 SELECT COALESCE(_latin1'a',_latin2'a');
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'coalesce'
+CREATE TABLE t1 SELECT COALESCE('a' COLLATE latin1_swedish_ci,'b' COLLATE latin1_bin);
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'coalesce'
+CREATE TABLE t1 SELECT
+COALESCE(1), COALESCE(1.0),COALESCE('a'),
+COALESCE(1,1.0), COALESCE(1,'1'),COALESCE(1.1,'1'),
+COALESCE('a' COLLATE latin1_bin,'b');
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `COALESCE(1)` int(1) NOT NULL default '0',
+ `COALESCE(1.0)` double(3,1) NOT NULL default '0.0',
+ `COALESCE('a')` char(1) NOT NULL default '',
+ `COALESCE(1,1.0)` double(3,1) NOT NULL default '0.0',
+ `COALESCE(1,'1')` char(1) NOT NULL default '',
+ `COALESCE(1.1,'1')` char(3) NOT NULL default '',
+ `COALESCE('a' COLLATE latin1_bin,'b')` char(1) character set latin1 collate latin1_bin NOT NULL default ''
+) TYPE=MyISAM CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index a14ea4d61a6..5d185bee005 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -44,10 +44,10 @@ t1 CREATE TABLE `t1` (
drop table t1;
select cast("2001-1-1" as date) = "2001-01-01";
cast("2001-1-1" as date) = "2001-01-01"
-0
+1
select cast("2001-1-1" as datetime) = "2001-01-01 00:00:00";
cast("2001-1-1" as datetime) = "2001-01-01 00:00:00"
-0
+1
select cast("1:2:3" as TIME) = "1:02:03";
cast("1:2:3" as TIME) = "1:02:03"
0
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 70814aa899e..9a0eca52b84 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -50,7 +50,7 @@ create table t1 (t1.index int);
drop table t1;
drop database if exists test_$1;
Warnings:
-Note 1008 Can't drop database 'test_$1'. Database doesn't exist
+Note 1008 Can't drop database 'test_$1'; database doesn't exist
create database test_$1;
create table test_$1.$test1 (a$1 int, $b int, c$ int);
insert into test_$1.$test1 values (1,2,3);
@@ -252,7 +252,7 @@ id name
drop table t2, t3;
drop database if exists test_$1;
Warnings:
-Note 1008 Can't drop database 'test_$1'. Database doesn't exist
+Note 1008 Can't drop database 'test_$1'; database doesn't exist
create database test_$1;
create table test_$1.t3 like t1;
create temporary table t3 like test_$1.t3;
diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result
index 630fef9b679..e0cb7008899 100644
--- a/mysql-test/r/ctype_latin1_de.result
+++ b/mysql-test/r/ctype_latin1_de.result
@@ -215,21 +215,21 @@ drop table t1;
create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
update t1 set word2=word;
-select word, word=0xdf as t from t1 having t > 0;
+select word, word=binary 0xdf as t from t1 having t > 0;
word t
ß 1
select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0;
word t
ss 1
ß 1
-select * from t1 where word=0xDF;
+select * from t1 where word=binary 0xDF;
word word2
ß ß
select * from t1 where word=CAST(0xDF as CHAR);
word word2
ss ss
ß ß
-select * from t1 where word2=0xDF;
+select * from t1 where word2=binary 0xDF;
word word2
ß ß
select * from t1 where word2=CAST(0xDF as CHAR);
@@ -244,7 +244,7 @@ select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR);
word word2
ä ä
ae ae
-select * from t1 where word between 0xDF and 0xDF;
+select * from t1 where word between binary 0xDF and binary 0xDF;
word word2
ß ß
select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR);
@@ -257,7 +257,7 @@ ae ae
select * from t1 where word like 'AE';
word word2
ae ae
-select * from t1 where word like 0xDF;
+select * from t1 where word like binary 0xDF;
word word2
ß ß
select * from t1 where word like CAST(0xDF as CHAR);
diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result
index 9ebcd1fb915..c5841f28830 100644
--- a/mysql-test/r/distinct.result
+++ b/mysql-test/r/distinct.result
@@ -173,9 +173,9 @@ INSERT INTO t2 values (1),(2),(3);
INSERT INTO t3 VALUES (1,'1'),(2,'2'),(1,'1'),(2,'2');
explain SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 index a a 5 NULL 6 Using index; Using temporary
-1 SIMPLE t2 index a a 4 NULL 5 Using index; Distinct
-1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using where; Distinct
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 2 Using temporary
+1 SIMPLE t2 ref a a 4 test.t1.a 2 Using index
+1 SIMPLE t3 ref a a 5 test.t1.b 2 Using where; Using index
SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
a
1
diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result
index 2b878455bea..9555ea452ca 100644
--- a/mysql-test/r/drop.result
+++ b/mysql-test/r/drop.result
@@ -13,7 +13,7 @@ n
1
drop database if exists mysqltest;
Warnings:
-Note 1008 Can't drop database 'mysqltest'. Database doesn't exist
+Note 1008 Can't drop database 'mysqltest'; database doesn't exist
create database mysqltest;
drop database if exists mysqltest;
create database mysqltest;
@@ -27,7 +27,7 @@ create database mysqltest;
drop database mysqltest;
drop database if exists mysqltest;
Warnings:
-Note 1008 Can't drop database 'mysqltest'. Database doesn't exist
+Note 1008 Can't drop database 'mysqltest'; database doesn't exist
flush tables with read lock;
create database mysqltest;
Got one of the listed errors
@@ -48,4 +48,4 @@ Database
mysql
test
drop database mysqltest;
-ERROR HY000: Can't drop database 'mysqltest'. Database doesn't exist
+ERROR HY000: Can't drop database 'mysqltest'; database doesn't exist
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index 51b61dbb3e6..15b406bcdda 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -1,6 +1,4 @@
-drop table if exists t1;
-Warnings:
-Note 1051 Unknown table 't1'
+drop table if exists t1, t2;
create table t1 (grp int, a bigint unsigned, c char(10) not null, d char(10) not null);
insert into t1 values (1,1,"a","a");
insert into t1 values (2,2,"b","a");
@@ -154,8 +152,29 @@ Warning 1258 1 line(s) was(were) cut by group_concat()
show warnings;
Level Code Message
Warning 1258 1 line(s) was(were) cut by group_concat()
+set group_concat_max_len = 1024;
select group_concat(sum(a)) from t1 group by grp;
ERROR HY000: Invalid use of group function
select grp,group_concat(c order by 2) from t1 group by grp;
ERROR 42S22: Unknown column '2' in 'group statement'
-drop table if exists t1;
+drop table t1;
+create table t1 ( URL_ID int(11), URL varchar(80));
+create table t2 ( REQ_ID int(11), URL_ID int(11));
+insert into t1 values (4,'www.host.com'), (5,'www.google.com'),(5,'www.help.com');
+insert into t2 values (1,4), (5,4), (5,5);
+select REQ_ID, Group_Concat(URL) as URL from t1, t2 where
+t2.URL_ID = t1.URL_ID group by REQ_ID;
+REQ_ID URL
+1 X
+5 X,X,X
+drop table t1;
+drop table t2;
+create table t1 (id int, name varchar(16));
+insert into t1 values (1,'longername'),(1,'evenlongername');
+select ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'without distinct: how it should be' from t1;
+without distinct: how it should be
+1:longername,1:evenlongername
+select distinct ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'with distinct: cutoff at length of shortname' from t1;
+with distinct: cutoff at length of shortname
+1:longername,1:evenlongername
+drop table t1;
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index 99d7bd2d087..26ef391024e 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -603,3 +603,12 @@ a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
2 1 1 1.0000 0.0000 1 1 1 1
3 1 1 1.0000 0.0000 1 1 1 1
drop table t1;
+create table t1 (USR_ID integer not null, MAX_REQ integer not null, constraint PK_SEA_USER primary key (USR_ID)) type=InnoDB;
+insert into t1 values (1, 3);
+select count(*) + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ from t1 group by MAX_REQ;
+count(*) + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ
+1
+select Case When Count(*) < MAX_REQ Then 1 Else 0 End from t1 where t1.USR_ID = 1 group by MAX_REQ;
+Case When Count(*) < MAX_REQ Then 1 Else 0 End
+1
+drop table t1;
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index 006dc8abef0..a197371b345 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -111,3 +111,56 @@ id
5
9
drop table t1;
+create table t1 (
+a char(1) character set latin1 collate latin1_general_ci,
+b char(1) character set latin1 collate latin1_swedish_ci,
+c char(1) character set latin1 collate latin1_danish_ci
+);
+insert into t1 values ('A','B','C');
+insert into t1 values ('a','c','c');
+select * from t1 where a in (b);
+ERROR HY000: Illegal mix of collations (latin1_general_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation ' IN '
+select * from t1 where a in (b,c);
+ERROR HY000: Illegal mix of collations (latin1_general_ci,IMPLICIT), (latin1_swedish_ci,IMPLICIT), (latin1_danish_ci,IMPLICIT) for operation ' IN '
+select * from t1 where 'a' in (a,b,c);
+ERROR HY000: Illegal mix of collations for operation ' IN '
+select * from t1 where 'a' in (a);
+a b c
+A B C
+a c c
+select * from t1 where a in ('a');
+a b c
+A B C
+a c c
+select * from t1 where 'a' collate latin1_general_ci in (a,b,c);
+a b c
+A B C
+a c c
+select * from t1 where 'a' collate latin1_bin in (a,b,c);
+a b c
+a c c
+select * from t1 where 'a' in (a,b,c collate latin1_bin);
+a b c
+a c c
+drop table t1;
+select '1.0' in (1,2);
+'1.0' in (1,2)
+1
+select 1 in ('1.0',2);
+1 in ('1.0',2)
+1
+select 1 in (1,'2.0');
+1 in (1,'2.0')
+1
+select 1 in ('1.0',2.0);
+1 in ('1.0',2.0)
+1
+select 1 in (1.0,'2.0');
+1 in (1.0,'2.0')
+1
+select 1 in ('1.1',2);
+1 in ('1.1',2)
+0
+select 1 in ('1.1',2.0);
+1 in ('1.1',2.0)
+0
diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result
new file mode 100644
index 00000000000..e330c73727b
--- /dev/null
+++ b/mysql-test/r/func_sapdb.result
@@ -0,0 +1,200 @@
+drop table if exists t1, test;
+select extract(DAY_MICROSECOND FROM "1999-01-02 10:11:12.000123");
+extract(DAY_MICROSECOND FROM "1999-01-02 10:11:12.000123")
+2101112000123
+select extract(HOUR_MICROSECOND FROM "1999-01-02 10:11:12.000123");
+extract(HOUR_MICROSECOND FROM "1999-01-02 10:11:12.000123")
+101112000123
+select extract(MINUTE_MICROSECOND FROM "1999-01-02 10:11:12.000123");
+extract(MINUTE_MICROSECOND FROM "1999-01-02 10:11:12.000123")
+1112000123
+select extract(SECOND_MICROSECOND FROM "1999-01-02 10:11:12.000123");
+extract(SECOND_MICROSECOND FROM "1999-01-02 10:11:12.000123")
+12000123
+select extract(MICROSECOND FROM "1999-01-02 10:11:12.000123");
+extract(MICROSECOND FROM "1999-01-02 10:11:12.000123")
+123
+select date_format("1997-12-31 23:59:59.000002", "%f");
+date_format("1997-12-31 23:59:59.000002", "%f")
+000002
+select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000 99:99:99.999999" DAY_MICROSECOND);
+date_add("1997-12-31 23:59:59.000002",INTERVAL "10000 99:99:99.999999" DAY_MICROSECOND)
+2025-05-23 04:40:39.000001
+select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99:99.999999" HOUR_MICROSECOND);
+date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99:99.999999" HOUR_MICROSECOND)
+1999-02-21 17:40:39.000001
+select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99.999999" MINUTE_MICROSECOND);
+date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99.999999" MINUTE_MICROSECOND)
+1998-01-07 22:41:39.000001
+select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000.999999" SECOND_MICROSECOND);
+date_add("1997-12-31 23:59:59.000002",INTERVAL "10000.999999" SECOND_MICROSECOND)
+1998-01-01 02:46:40.000001
+select date_add("1997-12-31 23:59:59.000002",INTERVAL "999999" MICROSECOND);
+date_add("1997-12-31 23:59:59.000002",INTERVAL "999999" MICROSECOND)
+1998-01-01 00:00:00.000001
+select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1 1:1:1.000002" DAY_MICROSECOND);
+date_sub("1998-01-01 00:00:00.000001",INTERVAL "1 1:1:1.000002" DAY_MICROSECOND)
+1997-12-30 22:58:58.999999
+select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1:1.000002" HOUR_MICROSECOND);
+date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1:1.000002" HOUR_MICROSECOND)
+1997-12-31 22:58:58.999999
+select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1.000002" MINUTE_MICROSECOND);
+date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1.000002" MINUTE_MICROSECOND)
+1997-12-31 23:58:58.999999
+select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1.000002" SECOND_MICROSECOND);
+date_sub("1998-01-01 00:00:00.000001",INTERVAL "1.000002" SECOND_MICROSECOND)
+1997-12-31 23:59:58.999999
+select date_sub("1998-01-01 00:00:00.000001",INTERVAL "000002" MICROSECOND);
+date_sub("1998-01-01 00:00:00.000001",INTERVAL "000002" MICROSECOND)
+1997-12-31 23:59:59.999999
+select adddate("1997-12-31 23:59:59.000001", 10);
+adddate("1997-12-31 23:59:59.000001", 10)
+1998-01-10 23:59:59.000001
+select subdate("1997-12-31 23:59:59.000001", 10);
+subdate("1997-12-31 23:59:59.000001", 10)
+1997-12-21 23:59:59.000001
+select datediff("1997-12-31 23:59:59.000001","1997-12-30");
+datediff("1997-12-31 23:59:59.000001","1997-12-30")
+1
+select datediff("1997-11-31 23:59:59.000001","1997-12-31");
+datediff("1997-11-31 23:59:59.000001","1997-12-31")
+-30
+select datediff("1997-11-31 23:59:59.000001",null);
+datediff("1997-11-31 23:59:59.000001",null)
+NULL
+select weekofyear("1997-11-31 23:59:59.000001");
+weekofyear("1997-11-31 23:59:59.000001")
+49
+select makedate(1997,1);
+makedate(1997,1)
+1997-01-01
+select makedate(1997,0);
+makedate(1997,0)
+NULL
+select addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002");
+addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002")
+1998-01-02 01:01:01.000001
+select subtime("1997-12-31 23:59:59.000001", "1 1:1:1.000002");
+subtime("1997-12-31 23:59:59.000001", "1 1:1:1.000002")
+1997-12-30 22:58:57.999999
+select addtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999");
+addtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999")
+NULL
+select subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999");
+subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999")
+NULL
+select subtime("01:00:00.999999", "02:00:00.999998");
+subtime("01:00:00.999999", "02:00:00.999998")
+-00:59:59.999999
+select subtime("02:01:01.999999", "01:01:01.999999");
+subtime("02:01:01.999999", "01:01:01.999999")
+01:00:00.000000
+select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002");
+timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002")
+8807:59:59.999999
+select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002");
+timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002")
+46:58:57.999999
+select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002");
+timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002")
+-23:59:59.999999
+select timediff("1997-12-31 23:59:59.000001","23:59:59.000001");
+timediff("1997-12-31 23:59:59.000001","23:59:59.000001")
+NULL
+select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001");
+timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001")
+-00:00:00.000001
+select maketime(10,11,12);
+maketime(10,11,12)
+10:11:12
+select maketime(25,11,12);
+maketime(25,11,12)
+25:11:12
+select maketime(-25,11,12);
+maketime(-25,11,12)
+-25:11:12
+select timestamp("2001-12-01", "01:01:01.999999");
+timestamp("2001-12-01", "01:01:01.999999")
+2001-12-01 01:01:01.999999
+select timestamp("2001-13-01", "01:01:01.000001");
+timestamp("2001-13-01", "01:01:01.000001")
+NULL
+select timestamp("2001-12-01", "25:01:01");
+timestamp("2001-12-01", "25:01:01")
+2001-12-02 01:01:01
+select timestamp("2001-12-01 01:01:01.000100");
+timestamp("2001-12-01 01:01:01.000100")
+2001-12-01 01:01:01.000100
+select timestamp("2001-12-01");
+timestamp("2001-12-01")
+2001-12-01 00:00:00
+select day("1997-12-31 23:59:59.000001");
+day("1997-12-31 23:59:59.000001")
+31
+select date("1997-12-31 23:59:59.000001");
+date("1997-12-31 23:59:59.000001")
+1997-12-31
+select date("1997-13-31 23:59:59.000001");
+date("1997-13-31 23:59:59.000001")
+NULL
+select time("1997-12-31 23:59:59.000001");
+time("1997-12-31 23:59:59.000001")
+23:59:59.000001
+select time("1997-12-31 25:59:59.000001");
+time("1997-12-31 25:59:59.000001")
+NULL
+select microsecond("1997-12-31 23:59:59.000001");
+microsecond("1997-12-31 23:59:59.000001")
+1
+create table t1
+select makedate(1997,1) as f1,
+addtime(cast("1997-12-31 23:59:59.000001" as datetime), "1 1:1:1.000002") as f2,
+addtime(cast("23:59:59.999999" as time) , "1 1:1:1.000002") as f3,
+timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") as f4,
+timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") as f5,
+maketime(10,11,12) as f6,
+timestamp(cast("2001-12-01" as date), "01:01:01") as f7,
+date("1997-12-31 23:59:59.000001") as f8,
+time("1997-12-31 23:59:59.000001") as f9;
+describe t1;
+Field Type Null Key Default Extra
+f1 date 0000-00-00
+f2 datetime 0000-00-00 00:00:00
+f3 time 00:00:00
+f4 time 00:00:00
+f5 time 00:00:00
+f6 time 00:00:00
+f7 datetime 0000-00-00 00:00:00
+f8 date 0000-00-00
+f9 time 00:00:00
+select * from t1;
+f1 f2 f3 f4 f5 f6 f7 f8 f9
+1997-01-01 1998-01-02 01:01:00 49:01:01 46:58:57 -23:59:59 10:11:12 2001-12-01 01:01:01 1997-12-31 23:59:59
+create table test(t1 datetime, t2 time, t3 time, t4 datetime);
+insert into test values
+('2001-01-01 01:01:01', '01:01:01', null, '2001-02-01 01:01:01'),
+('2001-01-01 01:01:01', '-01:01:01', '-23:59:59', "1997-12-31 23:59:59.000001"),
+('1997-12-31 23:59:59.000001', '-23:59:59', '-01:01:01', '2001-01-01 01:01:01'),
+('2001-01-01 01:01:01', '01:01:01', '-1 01:01:01', null),
+('2001-01-01 01:01:01', null, '-1 01:01:01', null),
+(null, null, null, null),
+('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01');
+SELECT ADDTIME(t1,t2) As ttt, ADDTIME(t2, t3) As qqq from test;
+ttt qqq
+2001-01-01 02:02:02 NULL
+2001-01-01 00:00:00 -25:01:00
+1997-12-31 00:00:00 -25:01:00
+2001-01-01 02:02:02 -24:00:00
+NULL NULL
+NULL NULL
+2001-01-01 02:02:02 26:02:02
+SELECT TIMEDIFF(t1,t4) As ttt, TIMEDIFF(t2, t3) As qqq from test;
+ttt qqq
+-744:00:00 NULL
+26305:01:02 22:58:58
+-26305:01:02 -22:58:58
+NULL 26:02:02
+NULL NULL
+NULL NULL
+00:00:00 -24:00:00
+drop table t1, test;
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index ffb7f2cd911..37694ad2f0a 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -1,4 +1,5 @@
drop table if exists t1;
+set names latin1;
select 'hello',"'hello'",'""hello""','''h''e''l''l''o''',"hel""lo",'hel\'lo';
hello 'hello' ""hello"" 'h'e'l'l'o' hel"lo hel'lo
hello 'hello' ""hello"" 'h'e'l'l'o' hel"lo hel'lo
@@ -249,6 +250,146 @@ INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf');
SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password");
1
DROP TABLE t1;
+select 1=_latin1'1';
+1=_latin1'1'
+1
+select _latin1'1'=1;
+_latin1'1'=1
+1
+select _latin2'1'=1;
+_latin2'1'=1
+1
+select 1=_latin2'1';
+1=_latin2'1'
+1
+select _latin1'1'=_latin2'1';
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation '='
+select row('a','b','c') = row('a','b','c');
+row('a','b','c') = row('a','b','c')
+1
+select row('A','b','c') = row('a','b','c');
+row('A','b','c') = row('a','b','c')
+1
+select row('A' COLLATE latin1_bin,'b','c') = row('a','b','c');
+row('A' COLLATE latin1_bin,'b','c') = row('a','b','c')
+0
+select row('A','b','c') = row('a' COLLATE latin1_bin,'b','c');
+row('A','b','c') = row('a' COLLATE latin1_bin,'b','c')
+0
+select row('A' COLLATE latin1_general_ci,'b','c') = row('a' COLLATE latin1_bin,'b','c');
+ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation '='
+select concat(_latin1'a',_latin2'a');
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat'
+select concat(_latin1'a',_latin2'a',_latin5'a');
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE), (latin5_turkish_ci,COERCIBLE) for operation 'concat'
+select concat(_latin1'a',_latin2'a',_latin5'a',_latin7'a');
+ERROR HY000: Illegal mix of collations for operation 'concat'
+select FIELD('b','A','B');
+FIELD('b','A','B')
+2
+select FIELD('B','A','B');
+FIELD('B','A','B')
+2
+select FIELD('b' COLLATE latin1_bin,'A','B');
+FIELD('b' COLLATE latin1_bin,'A','B')
+0
+select FIELD('b','A' COLLATE latin1_bin,'B');
+FIELD('b','A' COLLATE latin1_bin,'B')
+0
+select FIELD(_latin2'b','A','B');
+ERROR HY000: Illegal mix of collations (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation 'field'
+select FIELD('b',_latin2'A','B');
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation 'field'
+select FIELD('b',_latin2'A','B',1);
+FIELD('b',_latin2'A','B',1)
+1
+select POSITION(_latin1'B' IN _latin1'abcd');
+POSITION(_latin1'B' IN _latin1'abcd')
+2
+select POSITION(_latin1'B' IN _latin1'abcd' COLLATE latin1_bin);
+POSITION(_latin1'B' IN _latin1'abcd' COLLATE latin1_bin)
+0
+select POSITION(_latin1'B' COLLATE latin1_bin IN _latin1'abcd');
+POSITION(_latin1'B' COLLATE latin1_bin IN _latin1'abcd')
+0
+select POSITION(_latin1'B' COLLATE latin1_general_ci IN _latin1'abcd' COLLATE latin1_bin);
+ERROR HY000: Illegal mix of collations (latin1_bin,EXPLICIT) and (latin1_general_ci,EXPLICIT) for operation 'locate'
+select POSITION(_latin1'B' IN _latin2'abcd');
+ERROR HY000: Illegal mix of collations (latin2_general_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation 'locate'
+select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d');
+FIND_IN_SET(_latin1'B',_latin1'a,b,c,d')
+2
+select FIND_IN_SET(_latin1'B' COLLATE latin1_general_ci,_latin1'a,b,c,d' COLLATE latin1_bin);
+ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'find_in_set'
+select FIND_IN_SET(_latin1'B',_latin2'a,b,c,d');
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'find_in_set'
+select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2);
+SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2)
+abcdabc
+select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2);
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'substr_index'
+select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2);
+ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'substr_index'
+select _latin1'B' between _latin1'a' and _latin1'c';
+_latin1'B' between _latin1'a' and _latin1'c'
+1
+select _latin1'B' collate latin1_bin between _latin1'a' and _latin1'c';
+_latin1'B' collate latin1_bin between _latin1'a' and _latin1'c'
+0
+select _latin1'B' between _latin1'a' collate latin1_bin and _latin1'c';
+_latin1'B' between _latin1'a' collate latin1_bin and _latin1'c'
+0
+select _latin1'B' between _latin1'a' and _latin1'c' collate latin1_bin;
+_latin1'B' between _latin1'a' and _latin1'c' collate latin1_bin
+0
+select _latin2'B' between _latin1'a' and _latin1'b';
+ERROR HY000: Illegal mix of collations (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation 'between'
+select _latin1'B' between _latin2'a' and _latin1'b';
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation 'between'
+select _latin1'B' between _latin1'a' and _latin2'b';
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE) for operation 'between'
+select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b';
+ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_bin,EXPLICIT), (latin1_swedish_ci,COERCIBLE) for operation 'between'
+select _latin1'B' in (_latin1'a',_latin1'b');
+_latin1'B' in (_latin1'a',_latin1'b')
+1
+select _latin1'B' collate latin1_bin in (_latin1'a',_latin1'b');
+_latin1'B' collate latin1_bin in (_latin1'a',_latin1'b')
+0
+select _latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b');
+_latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b')
+0
+select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin);
+_latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin)
+0
+select _latin2'B' in (_latin1'a',_latin1'b');
+ERROR HY000: Illegal mix of collations (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation ' IN '
+select _latin1'B' in (_latin2'a',_latin1'b');
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation ' IN '
+select _latin1'B' in (_latin1'a',_latin2'b');
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE) for operation ' IN '
+select _latin1'B' COLLATE latin1_general_ci in (_latin1'a' COLLATE latin1_bin,_latin1'b');
+ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_bin,EXPLICIT), (latin1_swedish_ci,COERCIBLE) for operation ' IN '
+select _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE latin1_bin);
+ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_swedish_ci,COERCIBLE), (latin1_bin,EXPLICIT) for operation ' IN '
+select collation(bin(130)), coercibility(bin(130));
+collation(bin(130)) coercibility(bin(130))
+latin1_swedish_ci 3
+select collation(oct(130)), coercibility(oct(130));
+collation(oct(130)) coercibility(oct(130))
+latin1_swedish_ci 3
+select collation(conv(130,16,10)), coercibility(conv(130,16,10));
+collation(conv(130,16,10)) coercibility(conv(130,16,10))
+latin1_swedish_ci 3
+select collation(hex(130)), coercibility(hex(130));
+collation(hex(130)) coercibility(hex(130))
+latin1_swedish_ci 3
+select collation(char(130)), coercibility(hex(130));
+collation(char(130)) coercibility(hex(130))
+binary 3
+select collation(format(130,10)), coercibility(format(130,10));
+collation(format(130,10)) coercibility(format(130,10))
+latin1_swedish_ci 3
select collation(lcase(_latin2'a')), coercibility(lcase(_latin2'a'));
collation(lcase(_latin2'a')) coercibility(lcase(_latin2'a'))
latin2_general_ci 3
@@ -267,9 +408,21 @@ latin2_general_ci 3
select collation(concat(_latin2'a',_latin2'b')), coercibility(concat(_latin2'a',_latin2'b'));
collation(concat(_latin2'a',_latin2'b')) coercibility(concat(_latin2'a',_latin2'b'))
latin2_general_ci 3
+select collation(lpad(_latin2'a',4,_latin2'b')), coercibility(lpad(_latin2'a',4,_latin2'b'));
+collation(lpad(_latin2'a',4,_latin2'b')) coercibility(lpad(_latin2'a',4,_latin2'b'))
+binary 3
+select collation(rpad(_latin2'a',4,_latin2'b')), coercibility(rpad(_latin2'a',4,_latin2'b'));
+collation(rpad(_latin2'a',4,_latin2'b')) coercibility(rpad(_latin2'a',4,_latin2'b'))
+latin2_general_ci 3
select collation(concat_ws(_latin2'a',_latin2'b')), coercibility(concat_ws(_latin2'a',_latin2'b'));
collation(concat_ws(_latin2'a',_latin2'b')) coercibility(concat_ws(_latin2'a',_latin2'b'))
latin2_general_ci 3
+select collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')), coercibility(make_set(255,_latin2'a',_latin2'b',_latin2'c'));
+collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')) coercibility(make_set(255,_latin2'a',_latin2'b',_latin2'c'))
+latin2_general_ci 3
+select collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')), coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' '));
+collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')) coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' '))
+binary 3
select collation(trim(_latin2' a ')), coercibility(trim(_latin2' a '));
collation(trim(_latin2' a ')) coercibility(trim(_latin2' a '))
latin2_general_ci 3
@@ -306,15 +459,28 @@ latin2_general_ci 3
select collation(insert(_latin2'abcd',2,3,_latin2'ef')), coercibility(insert(_latin2'abcd',2,3,_latin2'ef'));
collation(insert(_latin2'abcd',2,3,_latin2'ef')) coercibility(insert(_latin2'abcd',2,3,_latin2'ef'))
latin2_general_ci 3
+select collation(replace(_latin2'abcd',_latin2'b',_latin2'B')), coercibility(replace(_latin2'abcd',_latin2'b',_latin2'B'));
+collation(replace(_latin2'abcd',_latin2'b',_latin2'B')) coercibility(replace(_latin2'abcd',_latin2'b',_latin2'B'))
+latin2_general_ci 3
create table t1
select
+bin(130),
+oct(130),
+conv(130,16,10),
+hex(130),
+char(130),
+format(130,10),
left(_latin2'a',1),
right(_latin2'a',1),
lcase(_latin2'a'),
ucase(_latin2'a'),
substring(_latin2'a',1,1),
concat(_latin2'a',_latin2'b'),
+lpad(_latin2'a',4,_latin2'b'),
+rpad(_latin2'a',4,_latin2'b'),
concat_ws(_latin2'a',_latin2'b'),
+make_set(255,_latin2'a',_latin2'b',_latin2'c'),
+export_set(255,_latin2'y',_latin2'n',_latin2' '),
trim(_latin2' a '),
ltrim(_latin2' a '),
rtrim(_latin2' a '),
@@ -326,18 +492,31 @@ reverse(_latin2'ab'),
quote(_latin2'ab'),
soundex(_latin2'ab'),
substring(_latin2'ab',1),
-insert(_latin2'abcd',2,3,_latin2'ef')
+insert(_latin2'abcd',2,3,_latin2'ef'),
+replace(_latin2'abcd',_latin2'b',_latin2'B')
;
+Warnings:
+Warning 1263 Data truncated for column 'format(130,10)' at row 1
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
+ `bin(130)` char(64) NOT NULL default '',
+ `oct(130)` char(64) NOT NULL default '',
+ `conv(130,16,10)` char(64) NOT NULL default '',
+ `hex(130)` char(6) NOT NULL default '',
+ `char(130)` char(1) NOT NULL default '',
+ `format(130,10)` char(4) NOT NULL default '',
`left(_latin2'a',1)` char(1) character set latin2 NOT NULL default '',
`right(_latin2'a',1)` char(1) character set latin2 NOT NULL default '',
`lcase(_latin2'a')` char(1) character set latin2 NOT NULL default '',
`ucase(_latin2'a')` char(1) character set latin2 NOT NULL default '',
`substring(_latin2'a',1,1)` char(1) character set latin2 NOT NULL default '',
`concat(_latin2'a',_latin2'b')` char(2) character set latin2 NOT NULL default '',
+ `lpad(_latin2'a',4,_latin2'b')` char(4) character set latin2 NOT NULL default '',
+ `rpad(_latin2'a',4,_latin2'b')` char(4) character set latin2 NOT NULL default '',
`concat_ws(_latin2'a',_latin2'b')` char(1) character set latin2 NOT NULL default '',
+ `make_set(255,_latin2'a',_latin2'b',_latin2'c')` char(5) character set latin2 NOT NULL default '',
+ `export_set(255,_latin2'y',_latin2'n',_latin2' ')` char(127) character set latin2 NOT NULL default '',
`trim(_latin2' a ')` char(3) character set latin2 NOT NULL default '',
`ltrim(_latin2' a ')` char(3) character set latin2 NOT NULL default '',
`rtrim(_latin2' a ')` char(3) character set latin2 NOT NULL default '',
@@ -349,6 +528,28 @@ t1 CREATE TABLE `t1` (
`quote(_latin2'ab')` char(6) character set latin2 NOT NULL default '',
`soundex(_latin2'ab')` char(4) character set latin2 NOT NULL default '',
`substring(_latin2'ab',1)` char(2) character set latin2 NOT NULL default '',
- `insert(_latin2'abcd',2,3,_latin2'ef')` char(6) character set latin2 NOT NULL default ''
+ `insert(_latin2'abcd',2,3,_latin2'ef')` char(6) character set latin2 NOT NULL default '',
+ `replace(_latin2'abcd',_latin2'b',_latin2'B')` char(4) character set latin2 NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1
drop table t1;
+select SUBSTR('abcdefg',3,2);
+SUBSTR('abcdefg',3,2)
+cd
+select SUBSTRING('abcdefg',3,2);
+SUBSTRING('abcdefg',3,2)
+cd
+select SUBSTR('abcdefg',-3,2) FROM DUAL;
+SUBSTR('abcdefg',-3,2)
+ef
+select SUBSTR('abcdefg',-1,5) FROM DUAL;
+SUBSTR('abcdefg',-1,5)
+g
+select SUBSTR('abcdefg',0,0) FROM DUAL;
+SUBSTR('abcdefg',0,0)
+
+select SUBSTR('abcdefg',-1,-1) FROM DUAL;
+SUBSTR('abcdefg',-1,-1)
+
+select SUBSTR('abcdefg',1,-1) FROM DUAL;
+SUBSTR('abcdefg',1,-1)
+
diff --git a/mysql-test/r/grant_cache.result b/mysql-test/r/grant_cache.result
index 0ffc48ad879..c8ae0b4d9b3 100644
--- a/mysql-test/r/grant_cache.result
+++ b/mysql-test/r/grant_cache.result
@@ -122,7 +122,7 @@ select "user4";
user4
user4
select a from t1;
-ERROR 42000: No Database Selected
+ERROR 3D000: No Database Selected
select * from mysqltest.t1,test.t1;
a b c a
1 1 1 test.t1
diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result
index 26b3c700d59..4e0153006f8 100644
--- a/mysql-test/r/handler.result
+++ b/mysql-test/r/handler.result
@@ -148,3 +148,22 @@ alter table t1 type=MyISAM;
handler t2 read first;
ERROR 42S02: Unknown table 't2' in HANDLER
drop table t1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3),(4),(5),(6);
+delete from t1 limit 2;
+handler t1 open;
+handler t1 read first;
+a
+3
+handler t1 read first limit 1,1;
+a
+4
+handler t1 read first limit 2,2;
+a
+5
+6
+delete from t1 limit 3;
+handler t1 read first;
+a
+6
+drop table t1;
diff --git a/mysql-test/r/have_openssl_2.require b/mysql-test/r/have_openssl_2.require
index 09a65d7d9bc..032b60d544a 100644
--- a/mysql-test/r/have_openssl_2.require
+++ b/mysql-test/r/have_openssl_2.require
@@ -1,2 +1,2 @@
Variable_name Value
-jkhjkhfs
+Ssl_cipher EDH-RSA-DES-CBC3-SHA
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 8409ca59784..523862052e0 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -788,7 +788,7 @@ id id3
UNLOCK TABLES;
DROP TABLE t1;
create table t1 (a char(20), unique (a(5))) type=innodb;
-ERROR HY000: Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the store engine doesn't support unique sub keys
+ERROR HY000: Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the storage engine doesn't support unique sub keys
create table t1 (a char(20), index (a(5))) type=innodb;
show create table t1;
Table Create Table
diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result
new file mode 100644
index 00000000000..8ec507b2a3f
--- /dev/null
+++ b/mysql-test/r/key_cache.result
@@ -0,0 +1,43 @@
+SET @save_key_buffer=@@key_buffer_size;
+SELECT @@key_buffer_size, @@small.key_buffer_size;
+@@key_buffer_size @@small.key_buffer_size
+2097152 131072
+SET @@global.key_buffer_size=16*1024*1024;
+SET @@global.default.key_buffer_size=16*1024*1024;
+SET @@global.default.key_buffer_size=16*1024*1024;
+SET @@global.small.key_buffer_size=1*1024*1024;
+SET @@global.medium.key_buffer_size=4*1024*1024;
+SET @@global.medium.key_buffer_size=0;
+SET @@global.medium.key_buffer_size=0;
+SHOW VARIABLES like "key_buffer_size";
+Variable_name Value
+key_buffer_size 16777216
+SELECT @@key_buffer_size;
+@@key_buffer_size
+16777216
+SELECT @@global.key_buffer_size;
+@@global.key_buffer_size
+16777216
+SELECT @@global.default.key_buffer_size;
+@@global.default.key_buffer_size
+16777216
+SELECT @@global.default.`key_buffer_size`;
+@@global.default.key_buffer_size
+16777216
+SELECT @@global.`default`.`key_buffer_size`;
+@@global.default.key_buffer_size
+16777216
+SELECT @@`default`.key_buffer_size;
+@@default.key_buffer_size
+16777216
+SELECT @@small.key_buffer_size;
+@@small.key_buffer_size
+1048576
+SELECT @@medium.key_buffer_size;
+@@medium.key_buffer_size
+4194304
+SET @@global.key_buffer_size=@save_key_buffer;
+SELECT @@default.key_buffer_size;
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'default.key_buffer_size' at line 1
+SELECT @@skr.table_type="test";
+ERROR HY000: Variable 'table_type' is not a variable component (Can't be used as XXXX.variable_name)
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 323931ae3eb..507ceb8951c 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -1,4 +1,5 @@
drop table if exists t1,t2,t3,t4,t5,t6;
+drop database if exists mysqltest;
create table t1 (a int not null primary key auto_increment, message char(20));
create table t2 (a int not null primary key auto_increment, message char(20));
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1");
@@ -174,15 +175,26 @@ t3 CREATE TABLE `t3` (
`a` int(11) NOT NULL default '0',
`b` char(20) default NULL,
KEY `a` (`a`)
-) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2);
select * from t4;
-ERROR HY000: Can't open file: 't4.MRG'. (errno: 143)
-create table t5 (a int not null, b char(10), key(a)) type=MERGE UNION=(test.t1,test_2.t2);
-ERROR HY000: Incorrect table definition; All MERGE tables must be in the same database
-drop table if exists t5,t4,t3,t1,t2;
-Warnings:
-Note 1051 Unknown table 't5'
+ERROR HY000: Can't open file: 't4.MRG' (errno: 143)
+alter table t4 add column c int;
+ERROR HY000: Can't open file: 't4.MRG' (errno: 143)
+create database mysqltest;
+create table mysqltest.t6 (a int not null primary key auto_increment, message char(20));
+create table t5 (a int not null, b char(20), key(a)) type=MERGE UNION=(test.t1,mysqltest.t6);
+show create table t5;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `a` int(11) NOT NULL default '0',
+ `b` char(20) default NULL,
+ KEY `a` (`a`)
+) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`mysqltest`.`t6`)
+alter table t5 type=myisam;
+drop table t5, mysqltest.t6;
+drop database mysqltest;
+drop table t4,t3,t1,t2;
create table t1 (c char(10)) type=myisam;
create table t2 (c char(10)) type=myisam;
create table t3 (c char(10)) union=(t1,t2) type=merge;
@@ -251,14 +263,14 @@ t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0',
`othr` int(11) NOT NULL default '0',
PRIMARY KEY (`incr`)
-) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
alter table t3 drop primary key;
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0',
`othr` int(11) NOT NULL default '0'
-) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
drop table t3,t2,t1;
create table t1 (a int not null, key(a)) type=merge;
select * from t1;
@@ -294,21 +306,21 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
-) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
show create table t5;
Table Create Table
t5 CREATE TABLE `t5` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`)
-) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`)
show create table t6;
Table Create Table
t6 CREATE TABLE `t6` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`)
-) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=LAST UNION=(t1,t2)
+) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
insert into t1 values (1,NULL),(1,NULL),(1,NULL),(1,NULL);
insert into t2 values (2,NULL),(2,NULL),(2,NULL),(2,NULL);
select * from t3 order by b,a limit 3;
@@ -373,7 +385,7 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
-) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2,t3)
+) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`,`t3`)
select * from t4 order by a,b;
a b
1 1
@@ -399,7 +411,7 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
-) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(t1,t2,t3)
+) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`,`t3`)
insert into t4 values (4,1),(4,2);
select * from t1 order by a,b;
a b
@@ -528,7 +540,11 @@ a b
6 1
6 2
6 3
-drop table if exists t6, t5, t4, t3, t2, t1;
+insert into t1 values (99,NULL);
+select * from t4 where a+0 > 90;
+a b
+99 1
+drop table t6, t5, t4, t3, t2, t1;
CREATE TABLE t1 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) TYPE=MyISAM;
INSERT INTO t1 VALUES (1,1), (2,1);
CREATE TABLE t2 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) TYPE=MyISAM;
@@ -540,7 +556,7 @@ max(b)
select max(b) from t1 where a = 2;
max(b)
1
-drop table if exists t3,t1,t2;
+drop table t3,t1,t2;
create table t1 (a int not null);
create table t2 (a int not null);
insert into t1 values (1);
@@ -559,7 +575,7 @@ select * from t6;
a
1
2
-drop table if exists t6, t3, t1, t2, t4, t5;
+drop table t6, t3, t1, t2, t4, t5;
CREATE TABLE t1 (
fileset_id tinyint(3) unsigned NOT NULL default '0',
file_code varchar(32) NOT NULL default '',
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index fd621d06c2b..0dd9754d0c5 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -7,7 +7,7 @@ select 1 | NULL,1 & NULL,1+NULL,1-NULL;
NULL NULL NULL NULL
select NULL=NULL,NULL<>NULL,IFNULL(NULL,1.1)+0,IFNULL(NULL,1) | 0;
NULL=NULL NULL<>NULL IFNULL(NULL,1.1)+0 IFNULL(NULL,1) | 0
-NULL NULL 1 1
+NULL NULL 1.1 1
select strcmp("a",NULL),(1<NULL)+0.0,NULL regexp "a",null like "a%","a%" like null;
strcmp("a",NULL) (1<NULL)+0.0 NULL regexp "a" null like "a%" "a%" like null
NULL NULL NULL NULL NULL
diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result
index 289290ba08c..7dc0b4bfdd3 100644
--- a/mysql-test/r/null_key.result
+++ b/mysql-test/r/null_key.result
@@ -21,7 +21,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a,b a 9 NULL 3 Using where; Using index
explain select * from t1 where (a is null or a = 7) and b=7;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b b 4 const 2 Using where
+1 SIMPLE t1 ref_or_null a,b a 9 const,const 2 Using where; Using index
+explain select * from t1 where (a is null or a = 7) and b=7 order by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref_or_null a,b a 9 const,const 2 Using where; Using index; Using filesort
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 3 Using where; Using index
@@ -56,13 +59,15 @@ NULL 9
NULL 9
select * from t1 where (a is null or a = 7) and b=7;
a b
-NULL 7
7 7
+NULL 7
select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
a b
NULL 7
NULL 9
NULL 9
+create table t2 like t1;
+insert into t2 select * from t1;
alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
explain select * from t1 where a is null and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
@@ -84,7 +89,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a,b a 5 NULL 5 Using where
explain select * from t1 where (a is null or a = 7) and b=7 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL a,b NULL NULL NULL 12 Using where
+1 SIMPLE t1 ref_or_null a,b a 5 const 4 Using where
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 3 Using where
@@ -125,8 +130,8 @@ NULL 9 0
NULL 9 0
select * from t1 where (a is null or a = 7) and b=7 and c=0;
a b c
-NULL 7 0
7 7 0
+NULL 7 0
select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
a b c
NULL 7 0
@@ -136,6 +141,103 @@ select * from t1 where b like "6%";
a b c
6 6 0
drop table t1;
+rename table t2 to t1;
+alter table t1 modify b int null;
+insert into t1 values (7,null), (8,null), (8,7);
+explain select * from t1 where a = 7 and (b=7 or b is null);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref_or_null a,b a 10 const,const 2 Using where; Using index
+select * from t1 where a = 7 and (b=7 or b is null);
+a b
+7 7
+7 NULL
+explain select * from t1 where (a = 7 or a is null) and (b=7 or b is null);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a,b a 10 NULL 4 Using where; Using index
+select * from t1 where (a = 7 or a is null) and (b=7 or b is null);
+a b
+NULL 7
+7 NULL
+7 7
+explain select * from t1 where (a = 7 or a is null) and (a = 7 or a is null);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref_or_null a a 5 const 5 Using where; Using index
+select * from t1 where (a = 7 or a is null) and (a = 7 or a is null);
+a b
+7 NULL
+7 7
+NULL 7
+NULL 9
+NULL 9
+create table t2 (a int);
+insert into t2 values (7),(8);
+explain select * from t2 straight_join t1 where t1.a=t2.a and b is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t1 ref a,b a 10 test.t2.a,const 2 Using where; Using index
+drop index b on t1;
+explain select * from t2,t1 where t1.a=t2.a and b is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t1 ref a a 10 test.t2.a,const 2 Using where; Using index
+select * from t2,t1 where t1.a=t2.a and b is null;
+a a b
+7 7 NULL
+8 8 NULL
+explain select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t1 ref_or_null a a 10 test.t2.a,const 4 Using where; Using index
+select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null);
+a a b
+7 7 7
+7 7 NULL
+8 8 7
+8 8 NULL
+explain select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t1 ref_or_null a a 10 test.t2.a,const 4 Using where; Using index
+select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7;
+a a b
+7 7 7
+7 NULL 7
+8 8 7
+8 NULL 7
+explain select * from t2,t1 where (t1.a=t2.a or t1.a is null) and (b= 7 or b is null);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t1 ref_or_null a a 5 test.t2.a 4 Using where; Using index
+select * from t2,t1 where (t1.a=t2.a or t1.a is null) and (b= 7 or b is null);
+a a b
+7 7 NULL
+7 7 7
+7 NULL 7
+8 8 NULL
+8 8 7
+8 NULL 7
+insert into t2 values (null),(6);
+delete from t1 where a=8;
+explain select * from t2,t1 where t1.a=t2.a or t1.a is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 4
+1 SIMPLE t1 ref_or_null a a 5 test.t2.a 4 Using where; Using index
+explain select * from t2,t1 where t1.a<=>t2.a or (t1.a is null and t1.b <> 9);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 4
+1 SIMPLE t1 ref_or_null a a 5 test.t2.a 4 Using where; Using index
+select * from t2,t1 where t1.a<=>t2.a or (t1.a is null and t1.b <> 9);
+a a b
+7 7 NULL
+7 7 7
+7 NULL 7
+8 NULL 7
+NULL NULL 7
+NULL NULL 9
+NULL NULL 9
+6 6 6
+6 NULL 7
+drop table t1,t2;
CREATE TABLE t1 (
id int(10) unsigned NOT NULL auto_increment,
uniq_id int(10) unsigned default NULL,
diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result
index 65b882c0a9b..afc4b12a341 100644
--- a/mysql-test/r/openssl_1.result
+++ b/mysql-test/r/openssl_1.result
@@ -10,22 +10,22 @@ select * from t1;
f1
5
delete from t1;
-Access denied for user: 'ssl_user1@localhost' to database 'test'
+ERROR 42000: Access denied for user: 'ssl_user1@localhost' to database 'test'
select * from t1;
f1
5
delete from t1;
-Access denied for user: 'ssl_user2@localhost' to database 'test'
+ERROR 42000: Access denied for user: 'ssl_user2@localhost' to database 'test'
select * from t1;
f1
5
delete from t1;
-Access denied for user: 'ssl_user3@localhost' to database 'test'
+ERROR 42000: Access denied for user: 'ssl_user3@localhost' to database 'test'
select * from t1;
f1
5
delete from t1;
-Access denied for user: 'ssl_user4@localhost' to database 'test'
+ERROR 42000: Access denied for user: 'ssl_user4@localhost' to database 'test'
delete from mysql.user where user='ssl_user%';
delete from mysql.db where user='ssl_user%';
flush privileges;
diff --git a/mysql-test/r/openssl_2.result b/mysql-test/r/openssl_2.result
index b5c67dfbcb0..879c623dd40 100644
--- a/mysql-test/r/openssl_2.result
+++ b/mysql-test/r/openssl_2.result
@@ -1,2 +1,25 @@
-SHOW STATUS LIKE 'SSL%';
+SHOW STATUS LIKE 'Ssl%';
Variable_name Value
+Ssl_accepts 1
+Ssl_finished_accepts 1
+Ssl_finished_connects 0
+Ssl_accept_renegotiates 0
+Ssl_connect_renegotiates 0
+Ssl_callback_cache_hits 0
+Ssl_session_cache_hits 0
+Ssl_session_cache_misses 0
+Ssl_session_cache_timeouts 0
+Ssl_used_session_cache_entries 1
+Ssl_client_connects 0
+Ssl_session_cache_overflows 0
+Ssl_session_cache_size 128
+Ssl_session_cache_mode SERVER
+Ssl_sessions_reused 0
+Ssl_ctx_verify_mode 7
+Ssl_ctx_verify_depth 4294967295
+Ssl_verify_mode 7
+Ssl_verify_depth 4294967295
+Ssl_version TLSv1
+Ssl_cipher EDH-RSA-DES-CBC3-SHA
+Ssl_cipher_list
+Ssl_default_timeout 7200
diff --git a/mysql-test/r/preload.result b/mysql-test/r/preload.result
new file mode 100644
index 00000000000..4d9293c7929
--- /dev/null
+++ b/mysql-test/r/preload.result
@@ -0,0 +1,167 @@
+drop table if exists t1, t2;
+create table t1 (
+a int not null auto_increment,
+b char(16) not null,
+primary key (a),
+key (b)
+);
+create table t2(
+a int not null auto_increment,
+b char(16) not null,
+primary key (a),
+key (b)
+);
+insert into t1(b) values
+('test0'),
+('test1'),
+('test2'),
+('test3'),
+('test4'),
+('test5'),
+('test6'),
+('test7');
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+select count(*) from t1;
+count(*)
+33448
+select count(*) from t2;
+count(*)
+20672
+flush tables;
+flush status;
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 0
+Key_reads 0
+select count(*) from t1 where b = 'test1';
+count(*)
+4181
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 217
+Key_reads 45
+select count(*) from t1 where b = 'test1';
+count(*)
+4181
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 434
+Key_reads 45
+flush tables;
+flush status;
+select @@preload_buffer_size;
+@@preload_buffer_size
+32768
+load index into cache t1 keys;
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 0
+Key_reads 0
+select count(*) from t1 where b = 'test1';
+count(*)
+4181
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 217
+Key_reads 45
+flush tables;
+flush status;
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 0
+Key_reads 0
+set session preload_buffer_size=256*1024;
+select @@preload_buffer_size;
+@@preload_buffer_size
+262144
+load index into cache t1 keys ignore leaves;
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 0
+Key_reads 0
+select count(*) from t1 where b = 'test1';
+count(*)
+4181
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 217
+Key_reads 45
+flush tables;
+flush status;
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 0
+Key_reads 0
+set session preload_buffer_size=1*1024;
+select @@preload_buffer_size;
+@@preload_buffer_size
+1024
+load index into cache t1 keys, t2 keys (primary,b) ignore leaves;
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+test.t2 preload_keys status OK
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 0
+Key_reads 0
+select count(*) from t1 where b = 'test1';
+count(*)
+4181
+select count(*) from t2 where b = 'test1';
+count(*)
+2584
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 351
+Key_reads 73
+flush tables;
+flush status;
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 0
+Key_reads 0
+load index into cache t3 keys, t2 keys (primary,b) ;
+Table Op Msg_type Msg_text
+test.t3 preload_keys error Table 'test.t3' doesn't exist
+test.t2 preload_keys status OK
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 0
+Key_reads 0
+flush tables;
+flush status;
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 0
+Key_reads 0
+load index into cache t3 keys (b), t2 keys (c) ;
+Table Op Msg_type Msg_text
+test.t3 preload_keys error Table 'test.t3' doesn't exist
+test.t2 preload_keys error Key column 'c' doesn't exist in table
+test.t2 preload_keys status Operation failed
+show status like "key_read%";
+Variable_name Value
+Key_read_requests 0
+Key_reads 0
+drop table t1, t2;
diff --git a/mysql-test/r/repair_part2.result b/mysql-test/r/repair_part2.result
index 77aa98c3da9..c9cf6c019f7 100644
--- a/mysql-test/r/repair_part2.result
+++ b/mysql-test/r/repair_part2.result
@@ -1,6 +1,6 @@
repair table t1;
Table Op Msg_type Msg_text
-test.t1 repair error Can't open file: 't1.MYI'. (errno: 130)
+test.t1 repair error Can't open file: 't1.MYI' (errno: 130)
repair table t1 use_frm;
Table Op Msg_type Msg_text
test.t1 repair warning Number of rows changed from 0 to 1
diff --git a/mysql-test/r/rpl000009.result b/mysql-test/r/rpl000009.result
index dc1d8c4872e..d0faf0435e3 100644
--- a/mysql-test/r/rpl000009.result
+++ b/mysql-test/r/rpl000009.result
@@ -21,7 +21,7 @@ n m
drop database mysqltest;
drop database if exists mysqltest2;
drop database mysqltest;
-ERROR HY000: Can't drop database 'mysqltest'. Database doesn't exist
+ERROR HY000: Can't drop database 'mysqltest'; database doesn't exist
drop database mysqltest2;
set sql_log_bin = 0;
create database mysqltest2;
@@ -48,8 +48,8 @@ mysql
test
load data from master;
Warnings:
-Note 1008 Can't drop database 'mysqltest'. Database doesn't exist
-Note 1008 Can't drop database 'mysqltest2'. Database doesn't exist
+Note 1008 Can't drop database 'mysqltest'; database doesn't exist
+Note 1008 Can't drop database 'mysqltest2'; database doesn't exist
show databases;
Database
mysql
diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result
index 66209d2b852..c3c83947578 100644
--- a/mysql-test/r/rpl_rotate_logs.result
+++ b/mysql-test/r/rpl_rotate_logs.result
@@ -41,11 +41,16 @@ insert into t2 values(NULL);
set global sql_slave_skip_counter=1;
start slave;
purge master logs to 'master-bin.000002';
+show master logs;
+Log_name
+master-bin.000002
+master-bin.000003
+purge binary logs to 'master-bin.000002';
show binary logs;
Log_name
master-bin.000002
master-bin.000003
-purge logs before now();
+purge master logs before now();
show binary logs;
Log_name
master-bin.000003
diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result
index e73161996b8..0f2a781d073 100644
--- a/mysql-test/r/select_safe.result
+++ b/mysql-test/r/select_safe.result
@@ -37,7 +37,7 @@ delete from t1 where b="test" limit 1;
delete from t1 where a+0=1 limit 2;
SET MAX_JOIN_SIZE=2;
SELECT @@MAX_JOIN_SIZE, @@SQL_BIG_SELECTS;
-@@max_join_size @@sql_big_selects
+@@MAX_JOIN_SIZE @@SQL_BIG_SELECTS
2 0
insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a");
SELECT * from t1;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index c41434336e5..bba86ff8891 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -583,12 +583,12 @@ a b
drop table t11, t12, t2;
CREATE TABLE t1 (x int);
create table t2 (a int);
-create table t3 (a int);
+create table t3 (b int);
insert into t2 values (1);
insert into t3 values (1),(2);
INSERT INTO t1 (x) VALUES ((SELECT x FROM t1));
ERROR HY000: You can't specify target table 't1' for update in FROM clause
-INSERT INTO t1 (x) VALUES ((SELECT a FROM t3));
+INSERT INTO t1 (x) VALUES ((SELECT b FROM t3));
ERROR 21000: Subselect returns more than 1 record
INSERT INTO t1 (x) VALUES ((SELECT a FROM t2));
select * from t1;
@@ -609,6 +609,8 @@ x
3
INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
+INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2));
+ERROR 42S22: Unknown column 'x' in 'field list'
INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2));
select * from t1;
x
@@ -827,7 +829,7 @@ a t1.a in (select t2.a from t2)
explain SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 Using index
-2 DEPENDENT SUBQUERY t2 index a a 5 NULL 3 Using where; Using index
+2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 const 2 Using where; Using index
drop table t1,t2;
create table t1 (a float);
select 10.5 IN (SELECT * from t1 LIMIT 1);
@@ -1151,3 +1153,75 @@ INSERT INTO t1 VALUES (1,0,NULL,NULL),(2,0,NULL,NULL);
SELECT DISTINCT REF_ID FROM t1 WHERE ID= (SELECT DISTINCT REF_ID FROM t1 WHERE ID=2);
REF_ID
DROP TABLE t1;
+create table t1 (a int, b int);
+create table t2 (a int, b int);
+insert into t1 values (1,0), (2,0), (3,0);
+insert into t2 values (1,1), (2,1), (3,1), (2,2);
+update ignore t1 set b=(select b from t2 where t1.a=t2.a);
+Warnings:
+Error 1240 Subselect returns more than 1 record
+select * from t1;
+a b
+1 1
+2 NULL
+3 1
+drop table t1, t2;
+create table t1(City VARCHAR(30),Location geometry);
+insert into t1 values("Paris",GeomFromText('POINT(2.33 48.87)'));
+select City from t1 where (select intersects(GeomFromText(AsText(Location)),GeomFromText('Polygon((2 50, 2.5 50, 2.5 47, 2 47, 2 50))'))=0);
+City
+drop table t1;
+CREATE TABLE `t1` (
+`id` mediumint(8) unsigned NOT NULL auto_increment,
+`pseudo` varchar(35) NOT NULL default '',
+`email` varchar(60) NOT NULL default '',
+PRIMARY KEY (`id`),
+UNIQUE KEY `email` (`email`),
+UNIQUE KEY `pseudo` (`pseudo`),
+) TYPE=MyISAM CHARSET=latin1 PACK_KEYS=1 ROW_FORMAT=DYNAMIC;
+INSERT INTO t1 (id,pseudo,email) VALUES (1,'test','test'),(2,'test1','test1');
+SELECT pseudo as a, pseudo as b FROM t1 GROUP BY (SELECT a) ORDER BY (SELECT id*1);
+a b
+test test
+test1 test1
+drop table if exists t1;
+(SELECT 1 as a) UNION (SELECT 1) ORDER BY (SELECT a+0);
+a
+1
+CREATE TABLE t1
+(
+FOLDERID VARCHAR(32)BINARY NOT NULL
+, FOLDERNAME VARCHAR(255)BINARY NOT NULL
+, CREATOR VARCHAR(255)BINARY
+, CREATED TIMESTAMP NOT NULL
+, DESCRIPTION VARCHAR(255)BINARY
+, FOLDERTYPE INTEGER NOT NULL
+, MODIFIED TIMESTAMP
+, MODIFIER VARCHAR(255)BINARY
+, FOLDERSIZE INTEGER NOT NULL
+, PARENTID VARCHAR(32)BINARY
+, REPID VARCHAR(32)BINARY
+, ORIGINATOR INTEGER
+, PRIMARY KEY ( FOLDERID )
+) TYPE=InnoDB;
+CREATE INDEX FFOLDERID_IDX ON t1 (FOLDERID);
+CREATE INDEX CMFLDRPARNT_IDX ON t1 (PARENTID);
+INSERT INTO t1 VALUES("0c9aab05b15048c59bc35c8461507deb", "System", "System", "2003-06-05 16:30:00", "The system content repository folder.", "3", "2003-06-05 16:30:00", "System", "0", NULL, "9c9aab05b15048c59bc35c8461507deb", "1");
+INSERT INTO t1 VALUES("2f6161e879db43c1a5b82c21ddc49089", "Default", "System", "2003-06-09 10:52:02", "The default content repository folder.", "3", "2003-06-05 16:30:00", "System", "0", NULL, "03eea05112b845949f3fd03278b5fe43", "1");
+INSERT INTO t1 VALUES("c373e9f5ad0791724315444553544200", "AddDocumentTest", "admin", "2003-06-09 10:51:25", "Movie Reviews", "0", "2003-06-09 10:51:25", "admin", "0", "2f6161e879db43c1a5b82c21ddc49089", "03eea05112b845949f3fd03278b5fe43", NULL);
+SELECT 'c373e9f5ad0791a0dab5444553544200' IN(SELECT t1.FOLDERID FROM t1 WHERE t1.PARENTID='2f6161e879db43c1a5b82c21ddc49089' AND t1.FOLDERNAME = 'Level1');
+'c373e9f5ad0791a0dab5444553544200' IN(SELECT t1.FOLDERID FROM t1 WHERE t1.PARENTID='2f6161e879db43c1a5b82c21ddc49089' AND t1.FOLDERNAME = 'Level1')
+0
+drop table t1;
+create table t1 (a int, b int);
+create table t2 (a int, b int);
+create table t3 (a int, b int);
+insert into t1 values (0,100),(1,2), (1,3), (2,2), (2,7), (2,-1), (3,10);
+insert into t2 values (0,0), (1,1), (2,1), (3,1), (4,1);
+insert into t3 values (3,3), (2,2), (1,1);
+select a,(select count(distinct t1.b) as sum from t1,t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1) from t3;
+a (select count(distinct t1.b) as sum from t1,t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1)
+3 1
+2 2
+1 2
+drop table t1,t2,t3;
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
index 3efc69d2f64..f12b98ba041 100644
--- a/mysql-test/r/symlink.result
+++ b/mysql-test/r/symlink.result
@@ -46,7 +46,7 @@ rename table t7 to t9;
drop table t1;
Got one of the listed errors
Warnings:
-Note 1008 Can't drop database 'test_mysqltest'. Database doesn't exist
+Note 1008 Can't drop database 'test_mysqltest'; database doesn't exist
Got one of the listed errors
Got one of the listed errors
Got one of the listed errors
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index d39f72cbe0b..592c787031f 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -347,7 +347,7 @@ a 1
hello 1
drop table t1;
create table t1 (a text, key (a(300)));
-ERROR HY000: Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the store engine doesn't support unique sub keys
+ERROR HY000: Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the storage engine doesn't support unique sub keys
create table t1 (a text, key (a(255)));
drop table t1;
CREATE TABLE t1 (
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index 1a773acd23e..4db791c993e 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -77,7 +77,7 @@ select last_insert_id(345);
last_insert_id(345)
345
select @@IDENTITY,last_insert_id(), @@identity;
-@@identity last_insert_id() @@identity
+@@IDENTITY last_insert_id() @@identity
345 345 345
set big_tables=OFF, big_tables=ON, big_tables=0, big_tables=1, big_tables="OFF", big_tables="ON";
set global concurrent_insert=ON;
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
index add9051ddfb..d84c284d7b4 100644
--- a/mysql-test/r/warnings.result
+++ b/mysql-test/r/warnings.result
@@ -32,7 +32,7 @@ Level Code Message
Note 1051 Unknown table 'not_exists_table'
drop database if exists not_exists_db;
Warnings:
-Note 1008 Can't drop database 'not_exists_db'. Database doesn't exist
+Note 1008 Can't drop database 'not_exists_db'; database doesn't exist
show count(*) warnings;
@@session.warning_count
1
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index 04229bd1882..346ad8fe80e 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -144,3 +144,30 @@ ALTER TABLE t1 DISABLE KEYS;
INSERT DELAYED INTO t1 VALUES(1),(2),(3);
ALTER TABLE t1 ENABLE KEYS;
drop table t1;
+
+#
+# Test that data get converted when character set is changed
+# Test that data doesn't get converted when src or dst is BINARY/BLOB
+#
+set names koi8r;
+create table t1 (a char(10) character set koi8r);
+insert into t1 values ('ÔÅÓÔ');
+select a,hex(a) from t1;
+alter table t1 change a a char(10) character set cp1251;
+select a,hex(a) from t1;
+alter table t1 change a a char(10) binary;
+select a,hex(a) from t1;
+alter table t1 change a a char(10) character set cp1251;
+select a,hex(a) from t1;
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+alter table t1 change a a varchar(10) character set cp1251;
+select a,hex(a) from t1;
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+alter table t1 change a a text character set cp1251;
+select a,hex(a) from t1;
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+
+drop table t1;
diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test
index 63fdfded6d0..189320a8dcb 100644
--- a/mysql-test/t/auto_increment.test
+++ b/mysql-test/t/auto_increment.test
@@ -80,6 +80,9 @@ insert into t1 set i = 254;
insert into t1 set i = null;
select last_insert_id();
--error 1062
+insert into t1 set i = 254;
+select last_insert_id();
+--error 1062
insert into t1 set i = null;
select last_insert_id();
drop table t1;
@@ -100,5 +103,6 @@ select last_insert_id();
--error 1062
insert into t1 values (NULL, 10);
select last_insert_id();
+
drop table t1;
diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test
index 6131d1500de..8aa17061174 100644
--- a/mysql-test/t/case.test
+++ b/mysql-test/t/case.test
@@ -41,3 +41,62 @@ create table t1 (row int not null, col int not null, val varchar(255) not null);
insert into t1 values (1,1,'orange'),(1,2,'large'),(2,1,'yellow'),(2,2,'medium'),(3,1,'green'),(3,2,'small');
select max(case col when 1 then val else null end) as color from t1 group by row;
drop table t1;
+
+SET NAMES latin1;
+
+#
+# CASE and argument types/collations aggregation into result
+#
+CREATE TABLE t1 SELECT
+ CASE WHEN 1 THEN _latin1'a' COLLATE latin1_danish_ci ELSE _latin1'a' END AS c1,
+ CASE WHEN 1 THEN _latin1'a' ELSE _latin1'a' COLLATE latin1_danish_ci END AS c2,
+ CASE WHEN 1 THEN 'a' ELSE 1 END AS c3,
+ CASE WHEN 1 THEN 1 ELSE 'a' END AS c4,
+ CASE WHEN 1 THEN 'a' ELSE 1.0 END AS c5,
+ CASE WHEN 1 THEN 1.0 ELSE 'a' END AS c6,
+ CASE WHEN 1 THEN 1 ELSE 1.0 END AS c7,
+ CASE WHEN 1 THEN 1.0 ELSE 1 END AS c8
+;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--error 1265
+SELECT CASE
+ WHEN 1
+ THEN _latin1'a' COLLATE latin1_danish_ci
+ ELSE _latin1'a' COLLATE latin1_swedish_ci
+ END;
+
+--error 1268
+SELECT CASE _latin1'a' COLLATE latin1_general_ci
+ WHEN _latin1'a' COLLATE latin1_danish_ci THEN 1
+ WHEN _latin1'a' COLLATE latin1_swedish_ci THEN 2
+ END;
+
+SELECT
+CASE _latin1'a' COLLATE latin1_general_ci WHEN _latin1'A' THEN '1' ELSE 2 END,
+CASE _latin1'a' COLLATE latin1_bin WHEN _latin1'A' THEN '1' ELSE 2 END,
+CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_swedish_ci THEN '1' ELSE 2 END,
+CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_bin THEN '1' ELSE 2 END
+;
+
+#
+# COALESCE is a CASE abbrevation:
+#
+# COALESCE(v1,v2) == CASE WHEN v1 IS NOT NULL THEN v1 ELSE v2 END
+#
+# COALESCE(V1, V2, . . . ,Vn ) =
+# CASE WHEN V1 IS NOT NULL THEN V1 ELSE COALESCE (V2, . . . ,Vn) END
+#
+# Check COALESCE argument types aggregation
+
+--error 1265
+CREATE TABLE t1 SELECT COALESCE(_latin1'a',_latin2'a');
+--error 1265
+CREATE TABLE t1 SELECT COALESCE('a' COLLATE latin1_swedish_ci,'b' COLLATE latin1_bin);
+CREATE TABLE t1 SELECT
+ COALESCE(1), COALESCE(1.0),COALESCE('a'),
+ COALESCE(1,1.0), COALESCE(1,'1'),COALESCE(1.1,'1'),
+ COALESCE('a' COLLATE latin1_bin,'b');
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test
index b63af87601b..22a4e14158d 100644
--- a/mysql-test/t/ctype_latin1_de.test
+++ b/mysql-test/t/ctype_latin1_de.test
@@ -52,21 +52,24 @@ drop table t1;
# Test bug report #152 (problem with index on latin1_de)
#
+#
+# The below checks both binary and character comparisons.
+#
create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
update t1 set word2=word;
-select word, word=0xdf as t from t1 having t > 0;
+select word, word=binary 0xdf as t from t1 having t > 0;
select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0;
-select * from t1 where word=0xDF;
+select * from t1 where word=binary 0xDF;
select * from t1 where word=CAST(0xDF as CHAR);
-select * from t1 where word2=0xDF;
+select * from t1 where word2=binary 0xDF;
select * from t1 where word2=CAST(0xDF as CHAR);
select * from t1 where word='ae';
select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR);
-select * from t1 where word between 0xDF and 0xDF;
+select * from t1 where word between binary 0xDF and binary 0xDF;
select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR);
select * from t1 where word like 'ae';
select * from t1 where word like 'AE';
-select * from t1 where word like 0xDF;
+select * from t1 where word like binary 0xDF;
select * from t1 where word like CAST(0xDF as CHAR);
drop table t1;
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index 0a95410e842..f426f9ca4ee 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -1,8 +1,10 @@
#
# simple test of group_concat function
#
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
-drop table if exists t1;
create table t1 (grp int, a bigint unsigned, c char(10) not null, d char(10) not null);
insert into t1 values (1,1,"a","a");
insert into t1 values (2,2,"b","a");
@@ -68,6 +70,7 @@ select grp,group_concat(c order by c) from t1 group by grp;
set group_concat_max_len = 5;
select grp,group_concat(c) from t1 group by grp;
show warnings;
+set group_concat_max_len = 1024;
# Test errors
@@ -76,4 +79,23 @@ select group_concat(sum(a)) from t1 group by grp;
--error 1054
select grp,group_concat(c order by 2) from t1 group by grp;
-drop table if exists t1;
+drop table t1;
+
+# Test variable length
+
+create table t1 ( URL_ID int(11), URL varchar(80));
+create table t2 ( REQ_ID int(11), URL_ID int(11));
+insert into t1 values (4,'www.host.com'), (5,'www.google.com'),(5,'www.help.com');
+insert into t2 values (1,4), (5,4), (5,5);
+# Make this order independent
+--replace_result www.help.com X www.host.com X www.google.com X
+select REQ_ID, Group_Concat(URL) as URL from t1, t2 where
+t2.URL_ID = t1.URL_ID group by REQ_ID;
+drop table t1;
+drop table t2;
+
+create table t1 (id int, name varchar(16));
+insert into t1 values (1,'longername'),(1,'evenlongername');
+select ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'without distinct: how it should be' from t1;
+select distinct ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'with distinct: cutoff at length of shortname' from t1;
+drop table t1;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index aca9530ffc3..fed19cbe07c 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -328,7 +328,6 @@ explain
select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME';
drop table t1, t2;
-
#
# Test of group function and NULL values
#
@@ -349,3 +348,10 @@ insert into t1 values (3,1);
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
drop table t1;
+--disable_warnings
+create table t1 (USR_ID integer not null, MAX_REQ integer not null, constraint PK_SEA_USER primary key (USR_ID)) type=InnoDB;
+--enable_warnings
+insert into t1 values (1, 3);
+select count(*) + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ from t1 group by MAX_REQ;
+select Case When Count(*) < MAX_REQ Then 1 Else 0 End from t1 where t1.USR_ID = 1 group by MAX_REQ;
+drop table t1;
diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test
index 723f1707a42..105612bf238 100644
--- a/mysql-test/t/func_in.test
+++ b/mysql-test/t/func_in.test
@@ -54,3 +54,30 @@ insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
select * from t1 where id in (2,5,9);
drop table t1;
+create table t1 (
+a char(1) character set latin1 collate latin1_general_ci,
+b char(1) character set latin1 collate latin1_swedish_ci,
+c char(1) character set latin1 collate latin1_danish_ci
+);
+insert into t1 values ('A','B','C');
+insert into t1 values ('a','c','c');
+--error 1265
+select * from t1 where a in (b);
+--error 1268
+select * from t1 where a in (b,c);
+--error 1269
+select * from t1 where 'a' in (a,b,c);
+select * from t1 where 'a' in (a);
+select * from t1 where a in ('a');
+select * from t1 where 'a' collate latin1_general_ci in (a,b,c);
+select * from t1 where 'a' collate latin1_bin in (a,b,c);
+select * from t1 where 'a' in (a,b,c collate latin1_bin);
+drop table t1;
+
+select '1.0' in (1,2);
+select 1 in ('1.0',2);
+select 1 in (1,'2.0');
+select 1 in ('1.0',2.0);
+select 1 in (1.0,'2.0');
+select 1 in ('1.1',2);
+select 1 in ('1.1',2.0);
diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test
new file mode 100644
index 00000000000..afd84fe9630
--- /dev/null
+++ b/mysql-test/t/func_sapdb.test
@@ -0,0 +1,99 @@
+--disable_warnings
+drop table if exists t1, test;
+--enable_warnings
+
+
+#
+# time functions
+#
+select extract(DAY_MICROSECOND FROM "1999-01-02 10:11:12.000123");
+select extract(HOUR_MICROSECOND FROM "1999-01-02 10:11:12.000123");
+select extract(MINUTE_MICROSECOND FROM "1999-01-02 10:11:12.000123");
+select extract(SECOND_MICROSECOND FROM "1999-01-02 10:11:12.000123");
+select extract(MICROSECOND FROM "1999-01-02 10:11:12.000123");
+select date_format("1997-12-31 23:59:59.000002", "%f");
+
+select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000 99:99:99.999999" DAY_MICROSECOND);
+select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99:99.999999" HOUR_MICROSECOND);
+select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99.999999" MINUTE_MICROSECOND);
+select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000.999999" SECOND_MICROSECOND);
+select date_add("1997-12-31 23:59:59.000002",INTERVAL "999999" MICROSECOND);
+
+select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1 1:1:1.000002" DAY_MICROSECOND);
+select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1:1.000002" HOUR_MICROSECOND);
+select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1.000002" MINUTE_MICROSECOND);
+select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1.000002" SECOND_MICROSECOND);
+select date_sub("1998-01-01 00:00:00.000001",INTERVAL "000002" MICROSECOND);
+
+#Date functions
+select adddate("1997-12-31 23:59:59.000001", 10);
+select subdate("1997-12-31 23:59:59.000001", 10);
+
+select datediff("1997-12-31 23:59:59.000001","1997-12-30");
+select datediff("1997-11-31 23:59:59.000001","1997-12-31");
+select datediff("1997-11-31 23:59:59.000001",null);
+
+select weekofyear("1997-11-31 23:59:59.000001");
+
+select makedate(1997,1);
+select makedate(1997,0);
+
+#Time functions
+
+select addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002");
+select subtime("1997-12-31 23:59:59.000001", "1 1:1:1.000002");
+select addtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999");
+select subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999");
+select subtime("01:00:00.999999", "02:00:00.999998");
+select subtime("02:01:01.999999", "01:01:01.999999");
+
+select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002");
+select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002");
+select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002");
+select timediff("1997-12-31 23:59:59.000001","23:59:59.000001");
+select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001");
+
+select maketime(10,11,12);
+select maketime(25,11,12);
+select maketime(-25,11,12);
+
+#Extraction functions
+select timestamp("2001-12-01", "01:01:01.999999");
+select timestamp("2001-13-01", "01:01:01.000001");
+select timestamp("2001-12-01", "25:01:01");
+select timestamp("2001-12-01 01:01:01.000100");
+select timestamp("2001-12-01");
+select day("1997-12-31 23:59:59.000001");
+select date("1997-12-31 23:59:59.000001");
+select date("1997-13-31 23:59:59.000001");
+select time("1997-12-31 23:59:59.000001");
+select time("1997-12-31 25:59:59.000001");
+select microsecond("1997-12-31 23:59:59.000001");
+
+create table t1
+select makedate(1997,1) as f1,
+ addtime(cast("1997-12-31 23:59:59.000001" as datetime), "1 1:1:1.000002") as f2,
+ addtime(cast("23:59:59.999999" as time) , "1 1:1:1.000002") as f3,
+ timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") as f4,
+ timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") as f5,
+ maketime(10,11,12) as f6,
+ timestamp(cast("2001-12-01" as date), "01:01:01") as f7,
+ date("1997-12-31 23:59:59.000001") as f8,
+ time("1997-12-31 23:59:59.000001") as f9;
+describe t1;
+select * from t1;
+
+create table test(t1 datetime, t2 time, t3 time, t4 datetime);
+insert into test values
+('2001-01-01 01:01:01', '01:01:01', null, '2001-02-01 01:01:01'),
+('2001-01-01 01:01:01', '-01:01:01', '-23:59:59', "1997-12-31 23:59:59.000001"),
+('1997-12-31 23:59:59.000001', '-23:59:59', '-01:01:01', '2001-01-01 01:01:01'),
+('2001-01-01 01:01:01', '01:01:01', '-1 01:01:01', null),
+('2001-01-01 01:01:01', null, '-1 01:01:01', null),
+(null, null, null, null),
+('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01');
+
+SELECT ADDTIME(t1,t2) As ttt, ADDTIME(t2, t3) As qqq from test;
+SELECT TIMEDIFF(t1,t4) As ttt, TIMEDIFF(t2, t3) As qqq from test;
+
+drop table t1, test;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 93e35efa455..f158eaa3764 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -8,6 +8,8 @@
drop table if exists t1;
--enable_warnings
+set names latin1;
+
select 'hello',"'hello'",'""hello""','''h''e''l''l''o''',"hel""lo",'hel\'lo';
select 'hello' 'monty';
select length('\n\t\r\b\0\_\%\\');
@@ -136,13 +138,113 @@ DROP TABLE t1;
#
# Test collation and coercibility
#
+
+select 1=_latin1'1';
+select _latin1'1'=1;
+select _latin2'1'=1;
+select 1=_latin2'1';
+--error 1265
+select _latin1'1'=_latin2'1';
+select row('a','b','c') = row('a','b','c');
+select row('A','b','c') = row('a','b','c');
+select row('A' COLLATE latin1_bin,'b','c') = row('a','b','c');
+select row('A','b','c') = row('a' COLLATE latin1_bin,'b','c');
+--error 1265
+select row('A' COLLATE latin1_general_ci,'b','c') = row('a' COLLATE latin1_bin,'b','c');
+
+--error 1265
+select concat(_latin1'a',_latin2'a');
+--error 1268
+select concat(_latin1'a',_latin2'a',_latin5'a');
+--error 1269
+select concat(_latin1'a',_latin2'a',_latin5'a',_latin7'a');
+
+
+#
+# Test FIELD() and collations
+#
+select FIELD('b','A','B');
+select FIELD('B','A','B');
+select FIELD('b' COLLATE latin1_bin,'A','B');
+select FIELD('b','A' COLLATE latin1_bin,'B');
+--error 1268
+select FIELD(_latin2'b','A','B');
+--error 1268
+select FIELD('b',_latin2'A','B');
+select FIELD('b',_latin2'A','B',1);
+
+
+select POSITION(_latin1'B' IN _latin1'abcd');
+select POSITION(_latin1'B' IN _latin1'abcd' COLLATE latin1_bin);
+select POSITION(_latin1'B' COLLATE latin1_bin IN _latin1'abcd');
+--error 1265
+select POSITION(_latin1'B' COLLATE latin1_general_ci IN _latin1'abcd' COLLATE latin1_bin);
+--error 1265
+select POSITION(_latin1'B' IN _latin2'abcd');
+
+select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d');
+--fix this:
+--select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d' COLLATE latin1_bin);
+--select FIND_IN_SET(_latin1'B' COLLATE latin1_bin,_latin1'a,b,c,d');
+--error 1265
+select FIND_IN_SET(_latin1'B' COLLATE latin1_general_ci,_latin1'a,b,c,d' COLLATE latin1_bin);
+--error 1265
+select FIND_IN_SET(_latin1'B',_latin2'a,b,c,d');
+
+select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2);
+--fix this:
+--select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_bin,_latin1'd',2);
+--select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd' COLLATE latin1_bin,2);
+--error 1265
+select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2);
+--error 1265
+select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2);
+
+select _latin1'B' between _latin1'a' and _latin1'c';
+select _latin1'B' collate latin1_bin between _latin1'a' and _latin1'c';
+select _latin1'B' between _latin1'a' collate latin1_bin and _latin1'c';
+select _latin1'B' between _latin1'a' and _latin1'c' collate latin1_bin;
+--error 1268
+select _latin2'B' between _latin1'a' and _latin1'b';
+--error 1268
+select _latin1'B' between _latin2'a' and _latin1'b';
+--error 1268
+select _latin1'B' between _latin1'a' and _latin2'b';
+--error 1268
+select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b';
+
+select _latin1'B' in (_latin1'a',_latin1'b');
+select _latin1'B' collate latin1_bin in (_latin1'a',_latin1'b');
+select _latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b');
+select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin);
+--error 1268
+select _latin2'B' in (_latin1'a',_latin1'b');
+--error 1268
+select _latin1'B' in (_latin2'a',_latin1'b');
+--error 1268
+select _latin1'B' in (_latin1'a',_latin2'b');
+--error 1268
+select _latin1'B' COLLATE latin1_general_ci in (_latin1'a' COLLATE latin1_bin,_latin1'b');
+--error 1268
+select _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE latin1_bin);
+
+select collation(bin(130)), coercibility(bin(130));
+select collation(oct(130)), coercibility(oct(130));
+select collation(conv(130,16,10)), coercibility(conv(130,16,10));
+select collation(hex(130)), coercibility(hex(130));
+select collation(char(130)), coercibility(hex(130));
+select collation(format(130,10)), coercibility(format(130,10));
select collation(lcase(_latin2'a')), coercibility(lcase(_latin2'a'));
select collation(ucase(_latin2'a')), coercibility(ucase(_latin2'a'));
select collation(left(_latin2'a',1)), coercibility(left(_latin2'a',1));
select collation(right(_latin2'a',1)), coercibility(right(_latin2'a',1));
select collation(substring(_latin2'a',1,1)), coercibility(substring(_latin2'a',1,1));
select collation(concat(_latin2'a',_latin2'b')), coercibility(concat(_latin2'a',_latin2'b'));
+select collation(lpad(_latin2'a',4,_latin2'b')), coercibility(lpad(_latin2'a',4,_latin2'b'));
+select collation(rpad(_latin2'a',4,_latin2'b')), coercibility(rpad(_latin2'a',4,_latin2'b'));
select collation(concat_ws(_latin2'a',_latin2'b')), coercibility(concat_ws(_latin2'a',_latin2'b'));
+select collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')), coercibility(make_set(255,_latin2'a',_latin2'b',_latin2'c'));
+select collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')), coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' '));
select collation(trim(_latin2' a ')), coercibility(trim(_latin2' a '));
select collation(ltrim(_latin2' a ')), coercibility(ltrim(_latin2' a '));
select collation(rtrim(_latin2' a ')), coercibility(rtrim(_latin2' a '));
@@ -155,16 +257,27 @@ select collation(quote(_latin2'ab')), coercibility(quote(_latin2'ab'));
select collation(soundex(_latin2'ab')), coercibility(soundex(_latin2'ab'));
select collation(substring(_latin2'ab',1)), coercibility(substring(_latin2'ab',1));
select collation(insert(_latin2'abcd',2,3,_latin2'ef')), coercibility(insert(_latin2'abcd',2,3,_latin2'ef'));
+select collation(replace(_latin2'abcd',_latin2'b',_latin2'B')), coercibility(replace(_latin2'abcd',_latin2'b',_latin2'B'));
create table t1
select
+ bin(130),
+ oct(130),
+ conv(130,16,10),
+ hex(130),
+ char(130),
+ format(130,10),
left(_latin2'a',1),
right(_latin2'a',1),
lcase(_latin2'a'),
ucase(_latin2'a'),
substring(_latin2'a',1,1),
concat(_latin2'a',_latin2'b'),
+ lpad(_latin2'a',4,_latin2'b'),
+ rpad(_latin2'a',4,_latin2'b'),
concat_ws(_latin2'a',_latin2'b'),
+ make_set(255,_latin2'a',_latin2'b',_latin2'c'),
+ export_set(255,_latin2'y',_latin2'n',_latin2' '),
trim(_latin2' a '),
ltrim(_latin2' a '),
rtrim(_latin2' a '),
@@ -176,8 +289,19 @@ select
quote(_latin2'ab'),
soundex(_latin2'ab'),
substring(_latin2'ab',1),
- insert(_latin2'abcd',2,3,_latin2'ef')
+ insert(_latin2'abcd',2,3,_latin2'ef'),
+ replace(_latin2'abcd',_latin2'b',_latin2'B')
;
-
show create table t1;
drop table t1;
+
+#
+# test for SUBSTR
+#
+select SUBSTR('abcdefg',3,2);
+select SUBSTRING('abcdefg',3,2);
+select SUBSTR('abcdefg',-3,2) FROM DUAL;
+select SUBSTR('abcdefg',-1,5) FROM DUAL;
+select SUBSTR('abcdefg',0,0) FROM DUAL;
+select SUBSTR('abcdefg',-1,-1) FROM DUAL;
+select SUBSTR('abcdefg',1,-1) FROM DUAL;
diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test
index 30746f10c62..15d2e954a95 100644
--- a/mysql-test/t/handler.test
+++ b/mysql-test/t/handler.test
@@ -85,3 +85,17 @@ alter table t1 type=MyISAM;
handler t2 read first;
drop table t1;
+#
+# test case for the bug #787
+#
+
+create table t1 (a int);
+insert into t1 values (1),(2),(3),(4),(5),(6);
+delete from t1 limit 2;
+handler t1 open;
+handler t1 read first;
+handler t1 read first limit 1,1;
+handler t1 read first limit 2,2;
+delete from t1 limit 3;
+handler t1 read first;
+drop table t1;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 3736f4a2ddc..17df79a69fa 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -22,7 +22,7 @@ drop table t1;
#
# A bit bigger test
-# The 'replace_result' statements are needed because the cardinality calculated
+# The 'replace_column' statements are needed because the cardinality calculated
# by innodb is not always the same between runs
#
@@ -51,7 +51,7 @@ select * from t1 where parent_id=102;
select level,id from t1 where level=1;
select level,id,parent_id from t1 where level=1;
optimize table t1;
---replace_result 87 # 50 # 48 # 43 # 25 # 24 # 6 # 3 #
+--replace_column 7 #
show keys from t1;
drop table t1;
diff --git a/mysql-test/t/key_cache-master.opt b/mysql-test/t/key_cache-master.opt
new file mode 100644
index 00000000000..66e19c18a8a
--- /dev/null
+++ b/mysql-test/t/key_cache-master.opt
@@ -0,0 +1 @@
+--key_buffer_size=2M --small.key_buffer_size=256K --small.key_buffer_size=128K
diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test
new file mode 100644
index 00000000000..2da18b68624
--- /dev/null
+++ b/mysql-test/t/key_cache.test
@@ -0,0 +1,42 @@
+#
+# Test of key cache
+#
+
+SET @save_key_buffer=@@key_buffer_size;
+
+SELECT @@key_buffer_size, @@small.key_buffer_size;
+
+# Change default key cache size
+SET @@global.key_buffer_size=16*1024*1024;
+SET @@global.default.key_buffer_size=16*1024*1024;
+SET @@global.default.key_buffer_size=16*1024*1024;
+
+SET @@global.small.key_buffer_size=1*1024*1024;
+SET @@global.medium.key_buffer_size=4*1024*1024;
+# Drop buffer
+SET @@global.medium.key_buffer_size=0;
+# Test double drop
+SET @@global.medium.key_buffer_size=0;
+
+# Print key buffer with different syntaxes
+SHOW VARIABLES like "key_buffer_size";
+SELECT @@key_buffer_size;
+SELECT @@global.key_buffer_size;
+SELECT @@global.default.key_buffer_size;
+SELECT @@global.default.`key_buffer_size`;
+SELECT @@global.`default`.`key_buffer_size`;
+SELECT @@`default`.key_buffer_size;
+
+SELECT @@small.key_buffer_size;
+SELECT @@medium.key_buffer_size;
+
+SET @@global.key_buffer_size=@save_key_buffer;
+
+#
+# Errors
+#
+
+--error 1064
+SELECT @@default.key_buffer_size;
+--error 1270
+SELECT @@skr.table_type="test";
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index 7a7678afca1..01ba8986474 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -4,6 +4,7 @@
--disable_warnings
drop table if exists t1,t2,t3,t4,t5,t6;
+drop database if exists mysqltest;
--enable_warnings
create table t1 (a int not null primary key auto_increment, message char(20));
@@ -48,13 +49,23 @@ show create table t3;
create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2);
--error 1016
select * from t4;
---error 1212
-create table t5 (a int not null, b char(10), key(a)) type=MERGE UNION=(test.t1,test_2.t2);
+--error 1016
+alter table t4 add column c int;
-# Because of windows, it's important that we drop the merge tables first!
-# This should give a warning on table t5
-drop table if exists t5,t4,t3,t1,t2;
+#
+# Test tables in different databases
+#
+create database mysqltest;
+create table mysqltest.t6 (a int not null primary key auto_increment, message char(20));
+create table t5 (a int not null, b char(20), key(a)) type=MERGE UNION=(test.t1,mysqltest.t6);
+show create table t5;
+alter table t5 type=myisam;
+drop table t5, mysqltest.t6;
+drop database mysqltest;
+# Because of windows, it's important that we drop the merge tables first!
+drop table t4,t3,t1,t2;
+
create table t1 (c char(10)) type=myisam;
create table t2 (c char(10)) type=myisam;
create table t3 (c char(10)) union=(t1,t2) type=merge;
@@ -177,7 +188,9 @@ select * from t1 order by a,b;
select * from t2 order by a,b;
select * from t5 order by a,b;
select * from t6 order by a,b;
-drop table if exists t6, t5, t4, t3, t2, t1;
+insert into t1 values (99,NULL);
+select * from t4 where a+0 > 90;
+drop table t6, t5, t4, t3, t2, t1;
CREATE TABLE t1 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) TYPE=MyISAM;
INSERT INTO t1 VALUES (1,1), (2,1);
@@ -186,7 +199,7 @@ INSERT INTO t2 VALUES (1,2), (2,2);
CREATE TABLE t3 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', KEY a (a,b)) TYPE=MRG_MyISAM UNION=(t1,t2);
select max(b) from t3 where a = 2;
select max(b) from t1 where a = 2;
-drop table if exists t3,t1,t2;
+drop table t3,t1,t2;
#
# temporary merge tables
@@ -203,7 +216,7 @@ insert into t4 values (1);
insert into t5 values (2);
create temporary table t6 (a int not null) TYPE=MERGE UNION=(t4,t5);
select * from t6;
-drop table if exists t6, t3, t1, t2, t4, t5;
+drop table t6, t3, t1, t2, t4, t5;
#
# testing merge::records_in_range and optimizer
diff --git a/mysql-test/t/null_key.test b/mysql-test/t/null_key.test
index 18d0d368891..7d9500e90dd 100644
--- a/mysql-test/t/null_key.test
+++ b/mysql-test/t/null_key.test
@@ -14,6 +14,7 @@ explain select * from t1 where a=2 and b = 2;
explain select * from t1 where a<=>b limit 2;
explain select * from t1 where (a is null or a > 0 and a < 3) and b < 5 limit 3;
explain select * from t1 where (a is null or a = 7) and b=7;
+explain select * from t1 where (a is null or a = 7) and b=7 order by a;
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
explain select * from t1 where a > 1 and a < 3 limit 1;
@@ -25,6 +26,8 @@ select * from t1 where (a is null or a > 0 and a < 3) and b < 5 limit 3;
select * from t1 where (a is null or a > 0 and a < 3) and b > 7 limit 3;
select * from t1 where (a is null or a = 7) and b=7;
select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
+create table t2 like t1;
+insert into t2 select * from t1;
alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
explain select * from t1 where a is null and b = 2;
explain select * from t1 where a is null and b = 2 and c=0;
@@ -47,8 +50,38 @@ select * from t1 where (a is null or a > 0 and a < 3) and b > 7 limit 3;
select * from t1 where (a is null or a = 7) and b=7 and c=0;
select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
select * from t1 where b like "6%";
-drop table t1;
+#
+# Test ref_or_null optimization
+#
+drop table t1;
+rename table t2 to t1;
+alter table t1 modify b int null;
+insert into t1 values (7,null), (8,null), (8,7);
+explain select * from t1 where a = 7 and (b=7 or b is null);
+select * from t1 where a = 7 and (b=7 or b is null);
+explain select * from t1 where (a = 7 or a is null) and (b=7 or b is null);
+select * from t1 where (a = 7 or a is null) and (b=7 or b is null);
+explain select * from t1 where (a = 7 or a is null) and (a = 7 or a is null);
+select * from t1 where (a = 7 or a is null) and (a = 7 or a is null);
+create table t2 (a int);
+insert into t2 values (7),(8);
+explain select * from t2 straight_join t1 where t1.a=t2.a and b is null;
+drop index b on t1;
+explain select * from t2,t1 where t1.a=t2.a and b is null;
+select * from t2,t1 where t1.a=t2.a and b is null;
+explain select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null);
+select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null);
+explain select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7;
+select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7;
+explain select * from t2,t1 where (t1.a=t2.a or t1.a is null) and (b= 7 or b is null);
+select * from t2,t1 where (t1.a=t2.a or t1.a is null) and (b= 7 or b is null);
+insert into t2 values (null),(6);
+delete from t1 where a=8;
+explain select * from t2,t1 where t1.a=t2.a or t1.a is null;
+explain select * from t2,t1 where t1.a<=>t2.a or (t1.a is null and t1.b <> 9);
+select * from t2,t1 where t1.a<=>t2.a or (t1.a is null and t1.b <> 9);
+drop table t1,t2;
#
# The following failed for Matt Loschert
diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test
index 3af7406cef3..c1c818efb70 100644
--- a/mysql-test/t/openssl_1.test
+++ b/mysql-test/t/openssl_1.test
@@ -2,7 +2,9 @@
# Use mysql-test-run with --with-openssl option.
-- source include/have_openssl_1.inc
+--disable_warnings
drop table if exists t1;
+--enable_warnings
create table t1(f1 int);
insert into t1 values (5);
diff --git a/mysql-test/t/openssl_2.test b/mysql-test/t/openssl_2.test
index 12f1240f3af..a8ee62db7f6 100644
--- a/mysql-test/t/openssl_2.test
+++ b/mysql-test/t/openssl_2.test
@@ -1,5 +1,5 @@
# We want to test everything with SSL turned on.
-- source include/have_openssl_2.inc
-SHOW STATUS LIKE 'SSL%';
+SHOW STATUS LIKE 'Ssl%';
diff --git a/mysql-test/t/preload.test b/mysql-test/t/preload.test
new file mode 100644
index 00000000000..7357b42c599
--- /dev/null
+++ b/mysql-test/t/preload.test
@@ -0,0 +1,100 @@
+#
+# Testing of PRELOAD
+#
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+
+create table t1 (
+ a int not null auto_increment,
+ b char(16) not null,
+ primary key (a),
+ key (b)
+);
+
+create table t2(
+ a int not null auto_increment,
+ b char(16) not null,
+ primary key (a),
+ key (b)
+);
+
+insert into t1(b) values
+ ('test0'),
+ ('test1'),
+ ('test2'),
+ ('test3'),
+ ('test4'),
+ ('test5'),
+ ('test6'),
+ ('test7');
+
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+insert into t2(b) select b from t1;
+insert into t1(b) select b from t2;
+
+select count(*) from t1;
+select count(*) from t2;
+
+flush tables; flush status;
+show status like "key_read%";
+
+select count(*) from t1 where b = 'test1';
+show status like "key_read%";
+select count(*) from t1 where b = 'test1';
+show status like "key_read%";
+
+flush tables; flush status;
+select @@preload_buffer_size;
+load index into cache t1 keys;
+show status like "key_read%";
+select count(*) from t1 where b = 'test1';
+show status like "key_read%";
+
+flush tables; flush status;
+show status like "key_read%";
+set session preload_buffer_size=256*1024;
+select @@preload_buffer_size;
+load index into cache t1 keys ignore leaves;
+show status like "key_read%";
+select count(*) from t1 where b = 'test1';
+show status like "key_read%";
+
+flush tables; flush status;
+show status like "key_read%";
+set session preload_buffer_size=1*1024;
+select @@preload_buffer_size;
+load index into cache t1 keys, t2 keys (primary,b) ignore leaves;
+show status like "key_read%";
+select count(*) from t1 where b = 'test1';
+select count(*) from t2 where b = 'test1';
+show status like "key_read%";
+
+flush tables; flush status;
+show status like "key_read%";
+load index into cache t3 keys, t2 keys (primary,b) ;
+show status like "key_read%";
+
+flush tables; flush status;
+show status like "key_read%";
+load index into cache t3 keys (b), t2 keys (c) ;
+show status like "key_read%";
+
+drop table t1, t2;
diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test
index 8ad5109d2c6..df506c08e71 100644
--- a/mysql-test/t/rpl_rotate_logs.test
+++ b/mysql-test/t/rpl_rotate_logs.test
@@ -90,9 +90,12 @@ connection master;
sync_slave_with_master;
connection master;
purge master logs to 'master-bin.000002';
+show master logs;
+# we just tests if synonyms are accepted
+purge binary logs to 'master-bin.000002';
show binary logs;
--sleep 1;
-purge logs before now();
+purge master logs before now();
show binary logs;
insert into t2 values (65);
sync_slave_with_master;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 1528f53ff0d..66d8dd2bc32 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -336,13 +336,13 @@ drop table t11, t12, t2;
#insert with subselects
CREATE TABLE t1 (x int);
create table t2 (a int);
-create table t3 (a int);
+create table t3 (b int);
insert into t2 values (1);
insert into t3 values (1),(2);
-- error 1093
INSERT INTO t1 (x) VALUES ((SELECT x FROM t1));
-- error 1240
-INSERT INTO t1 (x) VALUES ((SELECT a FROM t3));
+INSERT INTO t1 (x) VALUES ((SELECT b FROM t3));
INSERT INTO t1 (x) VALUES ((SELECT a FROM t2));
select * from t1;
insert into t2 values (1);
@@ -353,9 +353,15 @@ INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2;
select * from t1;
-- error 1093
INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2;
+-- error 1054
+INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2));
INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2));
-- sleep 1
select * from t1;
+#
+#TODO: should be uncommented after bug 380 fix pushed
+#INSERT INTO t1 (x) SELECT (SELECT SUM(a)+b FROM t2) from t3;
+#select * from t1;
drop table t1, t2, t3;
#replace with subselects
@@ -732,3 +738,83 @@ CREATE TABLE t1 (
INSERT INTO t1 VALUES (1,0,NULL,NULL),(2,0,NULL,NULL);
SELECT DISTINCT REF_ID FROM t1 WHERE ID= (SELECT DISTINCT REF_ID FROM t1 WHERE ID=2);
DROP TABLE t1;
+
+#
+# uninterruptable update
+#
+create table t1 (a int, b int);
+create table t2 (a int, b int);
+
+insert into t1 values (1,0), (2,0), (3,0);
+insert into t2 values (1,1), (2,1), (3,1), (2,2);
+
+update ignore t1 set b=(select b from t2 where t1.a=t2.a);
+select * from t1;
+
+drop table t1, t2;
+
+#
+# correct behavoiur for function from reduced subselect
+#
+create table t1(City VARCHAR(30),Location geometry);
+insert into t1 values("Paris",GeomFromText('POINT(2.33 48.87)'));
+select City from t1 where (select intersects(GeomFromText(AsText(Location)),GeomFromText('Polygon((2 50, 2.5 50, 2.5 47, 2 47, 2 50))'))=0);
+drop table t1;
+
+#
+# reduced subselect in ORDER BY & GROUP BY clauses
+#
+
+CREATE TABLE `t1` (
+ `id` mediumint(8) unsigned NOT NULL auto_increment,
+ `pseudo` varchar(35) NOT NULL default '',
+ `email` varchar(60) NOT NULL default '',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `email` (`email`),
+ UNIQUE KEY `pseudo` (`pseudo`),
+) TYPE=MyISAM CHARSET=latin1 PACK_KEYS=1 ROW_FORMAT=DYNAMIC;
+INSERT INTO t1 (id,pseudo,email) VALUES (1,'test','test'),(2,'test1','test1');
+SELECT pseudo as a, pseudo as b FROM t1 GROUP BY (SELECT a) ORDER BY (SELECT id*1);
+drop table if exists t1;
+
+(SELECT 1 as a) UNION (SELECT 1) ORDER BY (SELECT a+0);
+#
+# key field overflow test
+#
+--disable_warnings
+CREATE TABLE t1
+(
+FOLDERID VARCHAR(32)BINARY NOT NULL
+, FOLDERNAME VARCHAR(255)BINARY NOT NULL
+, CREATOR VARCHAR(255)BINARY
+, CREATED TIMESTAMP NOT NULL
+, DESCRIPTION VARCHAR(255)BINARY
+, FOLDERTYPE INTEGER NOT NULL
+, MODIFIED TIMESTAMP
+, MODIFIER VARCHAR(255)BINARY
+, FOLDERSIZE INTEGER NOT NULL
+, PARENTID VARCHAR(32)BINARY
+, REPID VARCHAR(32)BINARY
+, ORIGINATOR INTEGER
+
+, PRIMARY KEY ( FOLDERID )
+) TYPE=InnoDB;
+--enable_warnings
+CREATE INDEX FFOLDERID_IDX ON t1 (FOLDERID);
+CREATE INDEX CMFLDRPARNT_IDX ON t1 (PARENTID);
+INSERT INTO t1 VALUES("0c9aab05b15048c59bc35c8461507deb", "System", "System", "2003-06-05 16:30:00", "The system content repository folder.", "3", "2003-06-05 16:30:00", "System", "0", NULL, "9c9aab05b15048c59bc35c8461507deb", "1");
+INSERT INTO t1 VALUES("2f6161e879db43c1a5b82c21ddc49089", "Default", "System", "2003-06-09 10:52:02", "The default content repository folder.", "3", "2003-06-05 16:30:00", "System", "0", NULL, "03eea05112b845949f3fd03278b5fe43", "1");
+INSERT INTO t1 VALUES("c373e9f5ad0791724315444553544200", "AddDocumentTest", "admin", "2003-06-09 10:51:25", "Movie Reviews", "0", "2003-06-09 10:51:25", "admin", "0", "2f6161e879db43c1a5b82c21ddc49089", "03eea05112b845949f3fd03278b5fe43", NULL);
+SELECT 'c373e9f5ad0791a0dab5444553544200' IN(SELECT t1.FOLDERID FROM t1 WHERE t1.PARENTID='2f6161e879db43c1a5b82c21ddc49089' AND t1.FOLDERNAME = 'Level1');
+drop table t1;
+#
+# alloc_group_fields() working
+#
+create table t1 (a int, b int);
+create table t2 (a int, b int);
+create table t3 (a int, b int);
+insert into t1 values (0,100),(1,2), (1,3), (2,2), (2,7), (2,-1), (3,10);
+insert into t2 values (0,0), (1,1), (2,1), (3,1), (4,1);
+insert into t3 values (3,3), (2,2), (1,1);
+select a,(select count(distinct t1.b) as sum from t1,t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1) from t3;
+drop table t1,t2,t3;s
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 45cbcdb3ab7..3276044fc2f 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -826,7 +826,7 @@ restart:
(uint) hash_link->file,(ulong) hash_link->diskpos));
}
}
- KEYCACHE_DBUG_ASSERT(n <= my_hash_links_used);
+ KEYCACHE_DBUG_ASSERT(cnt <= my_hash_links_used);
#endif
}
if (! hash_link)
@@ -1063,6 +1063,9 @@ restart:
KEYCACHE_DBUG_ASSERT(page_status != -1);
*page_st=page_status;
+ KEYCACHE_DBUG_PRINT("find_key_block",
+ ("file %u, filepos %lu, page_status %lu",
+ (uint) file,(ulong) filepos,(uint) page_status));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_keycache2",test_key_cache("end of find_key_block",0););
@@ -1181,7 +1184,7 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
keycache_pthread_mutex_lock(&THR_LOCK_keycache);
my_cache_r_requests++;
block=find_key_block(file,filepos,0,&page_st);
- if (page_st != PAGE_READ)
+ if (block->status != BLOCK_ERROR && page_st != PAGE_READ)
{
/* The requested page is to be read into the block buffer */
read_block(block,key_cache_block_size,read_length+offset,
@@ -1256,6 +1259,86 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
/*
+ Insert a block of file data from a buffer into key cache
+
+ SYNOPSIS
+ key_cache_insert()
+ file file descriptor
+ filepos file offset of the data from the buffer
+ buff buffer with data to insert into key cache
+ length length of the data in the buffer
+
+ RETURN VALUE
+ 0 if a success, 1 -otherwise.
+*/
+
+int key_cache_insert(File file, my_off_t filepos, byte *buff, uint length)
+{
+ DBUG_ENTER("key_cache_insert");
+ DBUG_PRINT("enter", ("file %u, filepos %lu, length %u",
+ (uint) file,(ulong) filepos, length));
+
+ if (my_disk_blocks > 0)
+ {
+ /* Key cache is used */
+ reg1 BLOCK_LINK *block;
+ uint offset= (uint) (filepos & (key_cache_block_size-1));
+ uint read_length;
+ int page_st;
+
+ /* Read data into key cache from buff in key_cache_block_size increments */
+ filepos-= offset;
+ do
+ {
+ read_length= length > key_cache_block_size ?
+ key_cache_block_size : length;
+ KEYCACHE_DBUG_ASSERT(read_length > 0);
+ keycache_pthread_mutex_lock(&THR_LOCK_keycache);
+ my_cache_r_requests++;
+ block=find_key_block(file, filepos, 0, &page_st);
+ if (block->status != BLOCK_ERROR && page_st != PAGE_READ)
+ {
+ /* The requested page is to be read into the block buffer */
+#if !defined(SERIALIZED_READ_FROM_CACHE)
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+#endif
+
+ /* Copy data from buff */
+ if (!(read_length & 511))
+ bmove512(block->buffer+offset, buff, read_length);
+ else
+ memcpy(block->buffer+offset, buff, (size_t) read_length);
+
+#if !defined(SERIALIZED_READ_FROM_CACHE)
+ keycache_pthread_mutex_lock(&THR_LOCK_keycache);
+#endif
+ block->status= BLOCK_READ;
+ block->length= read_length+offset;
+ }
+
+ remove_reader(block);
+ /*
+ Link the block into the LRU chain
+ if it's the last submitted request for the block
+ */
+ unreg_request(block,1);
+
+ keycache_pthread_mutex_unlock(&THR_LOCK_keycache);
+
+ if (block->status & BLOCK_ERROR)
+ DBUG_RETURN(1);
+
+ buff+=read_length;
+ filepos+=read_length;
+ offset=0;
+
+ } while ((length-= read_length));
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
Write a buffer into disk;
filepos must be a multiple of 'block_length', but it doesn't
have to be a multiple of key cache block size;
@@ -1303,7 +1386,7 @@ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
keycache_pthread_mutex_lock(&THR_LOCK_keycache);
my_cache_w_requests++;
block=find_key_block(file, filepos, 1, &page_st);
- if (page_st != PAGE_READ &&
+ if (block->status != BLOCK_ERROR && page_st != PAGE_READ &&
(offset || read_length < key_cache_block_size))
read_block(block,
offset + read_length >= key_cache_block_size?
diff --git a/mysys/mf_loadpath.c b/mysys/mf_loadpath.c
index 291ad62e297..a46b43c34d4 100644
--- a/mysys/mf_loadpath.c
+++ b/mysys/mf_loadpath.c
@@ -28,6 +28,7 @@ my_string my_load_path(my_string to, const char *path,
const char *own_path_prefix)
{
char buff[FN_REFLEN];
+ int is_cur;
DBUG_ENTER("my_load_path");
DBUG_PRINT("enter",("path: %s prefix: %s",path,
own_path_prefix ? own_path_prefix : ""));
@@ -35,14 +36,16 @@ my_string my_load_path(my_string to, const char *path,
if ((path[0] == FN_HOMELIB && path[1] == FN_LIBCHAR) ||
test_if_hard_path(path))
VOID(strmov(buff,path));
- else if ((path[0] == FN_CURLIB && path[1] == FN_LIBCHAR) ||
+ else if ((is_cur=(path[0] == FN_CURLIB && path[1] == FN_LIBCHAR)) ||
(is_prefix((gptr) path,FN_PARENTDIR)) ||
! own_path_prefix)
{
- if (! my_getwd(buff,(uint) (FN_REFLEN-strlen(path)),MYF(0)))
- VOID(strcat(buff,path));
+ if (is_cur)
+ is_cur=2; /* Remove current dir */
+ if (! my_getwd(buff,(uint) (FN_REFLEN-strlen(path)+is_cur),MYF(0)))
+ VOID(strcat(buff,path+is_cur));
else
- VOID(strmov(buff,path));
+ VOID(strmov(buff,path)); /* Return org file name */
}
else
VOID(strxmov(buff,own_path_prefix,path,NullS));
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 759c96462f6..d539489cf1e 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -32,8 +32,9 @@ static longlong getopt_ll(char *arg, const struct my_option *optp, int *err);
static ulonglong getopt_ull(char *arg, const struct my_option *optp,
int *err);
static void init_variables(const struct my_option *options);
-static int setval(const struct my_option *opts, char *argument,
+static int setval(const struct my_option *opts, gptr *value, char *argument,
my_bool set_maximum_value);
+static char *check_struct_option(char *cur_arg, char *key_name);
/*
The following three variables belong to same group and the number and
@@ -67,6 +68,14 @@ my_bool my_getopt_print_errors= 1;
one. Call function 'get_one_option()' once for each option.
*/
+static gptr* (*getopt_get_addr)(const char *, uint, const struct my_option *);
+
+void my_getopt_register_get_addr(gptr* (*func_addr)(const char *, uint,
+ const struct my_option *))
+{
+ getopt_get_addr= func_addr;
+}
+
int handle_options(int *argc, char ***argv,
const struct my_option *longopts,
my_bool (*get_one_option)(int,
@@ -76,8 +85,10 @@ int handle_options(int *argc, char ***argv,
uint opt_found, argvpos= 0, length, i;
my_bool end_of_options= 0, must_be_var, set_maximum_value, special_used,
option_is_loose;
- char *progname= *(*argv), **pos, **pos_end, *optend, *prev_found;
+ char **pos, **pos_end, *optend, *prev_found,
+ *opt_str, key_name[FN_REFLEN];
const struct my_option *optp;
+ gptr *value;
int error;
LINT_INIT(opt_found);
@@ -110,7 +121,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: Option '-O' requires an argument\n",
- progname);
+ my_progname);
return EXIT_ARGUMENT_REQUIRED;
}
cur_arg= *pos;
@@ -128,7 +139,7 @@ int handle_options(int *argc, char ***argv,
if (my_getopt_print_errors)
fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n",
- progname);
+ my_progname);
return EXIT_ARGUMENT_REQUIRED;
}
}
@@ -142,7 +153,7 @@ int handle_options(int *argc, char ***argv,
if (my_getopt_print_errors)
fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n",
- progname);
+ my_progname);
return EXIT_ARGUMENT_REQUIRED;
}
cur_arg= *pos;
@@ -159,19 +170,20 @@ int handle_options(int *argc, char ***argv,
continue;
}
}
- optend= strcend(cur_arg, '=');
- length= optend - cur_arg;
+ opt_str= check_struct_option(cur_arg, key_name);
+ optend= strcend(opt_str, '=');
+ length= optend - opt_str;
if (*optend == '=')
optend++;
else
- optend=0;
+ optend= 0;
/*
Find first the right option. Return error in case of an ambiguous,
or unknown option
*/
optp= longopts;
- if (!(opt_found= findopt(cur_arg, length, &optp, &prev_found)))
+ if (!(opt_found= findopt(opt_str, length, &optp, &prev_found)))
{
/*
Didn't find any matching option. Let's see if someone called
@@ -183,18 +195,18 @@ int handle_options(int *argc, char ***argv,
must_be_var= 1; /* option is followed by an argument */
for (i= 0; special_opt_prefix[i]; i++)
{
- if (!getopt_compare_strings(special_opt_prefix[i], cur_arg,
+ if (!getopt_compare_strings(special_opt_prefix[i], opt_str,
special_opt_prefix_lengths[i]) &&
- cur_arg[special_opt_prefix_lengths[i]] == '-')
+ opt_str[special_opt_prefix_lengths[i]] == '-')
{
/*
We were called with a special prefix, we can reuse opt_found
*/
special_used= 1;
- cur_arg+= (special_opt_prefix_lengths[i] + 1);
+ opt_str+= (special_opt_prefix_lengths[i] + 1);
if (i == OPT_LOOSE)
option_is_loose= 1;
- if ((opt_found= findopt(cur_arg, length -
+ if ((opt_found= findopt(opt_str, length -
(special_opt_prefix_lengths[i] + 1),
&optp, &prev_found)))
{
@@ -203,7 +215,7 @@ int handle_options(int *argc, char ***argv,
if (my_getopt_print_errors)
fprintf(stderr,
"%s: ambiguous option '--%s-%s' (--%s-%s)\n",
- progname, special_opt_prefix[i], cur_arg,
+ my_progname, special_opt_prefix[i], opt_str,
special_opt_prefix[i], prev_found);
return EXIT_AMBIGUOUS_OPTION;
}
@@ -237,8 +249,8 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr,
- "%s: %s: unknown variable '%s'\n", progname,
- option_is_loose ? "WARNING" : "ERROR", cur_arg);
+ "%s: %s: unknown variable '%s'\n", my_progname,
+ option_is_loose ? "WARNING" : "ERROR", opt_str);
if (!option_is_loose)
return EXIT_UNKNOWN_VARIABLE;
}
@@ -246,8 +258,8 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr,
- "%s: %s: unknown option '--%s'\n", progname,
- option_is_loose ? "WARNING" : "ERROR", cur_arg);
+ "%s: %s: unknown option '--%s'\n", my_progname,
+ option_is_loose ? "WARNING" : "ERROR", opt_str);
if (!option_is_loose)
return EXIT_UNKNOWN_OPTION;
}
@@ -264,57 +276,61 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: variable prefix '%s' is not unique\n",
- progname, cur_arg);
+ my_progname, opt_str);
return EXIT_VAR_PREFIX_NOT_UNIQUE;
}
else
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: ambiguous option '--%s' (%s, %s)\n",
- progname, cur_arg, prev_found, optp->name);
+ my_progname, opt_str, prev_found, optp->name);
return EXIT_AMBIGUOUS_OPTION;
}
}
- if (must_be_var && optp->var_type == GET_NO_ARG)
+ if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG)
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: option '%s' cannot take an argument\n",
- progname, optp->name);
+ my_progname, optp->name);
return EXIT_NO_ARGUMENT_ALLOWED;
}
+ value= optp->var_type & GET_ASK_ADDR ?
+ (*getopt_get_addr)(key_name, strlen(key_name), optp) : optp->value;
+
if (optp->arg_type == NO_ARG)
{
- if (optend && optp->var_type != GET_BOOL)
+ if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL)
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: option '--%s' cannot take an argument\n",
- progname, optp->name);
+ my_progname, optp->name);
return EXIT_NO_ARGUMENT_ALLOWED;
}
- if (optp->var_type == GET_BOOL)
+ if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL)
{
/*
Set bool to 1 if no argument or if the user has used
--enable-'option-name'.
*optend was set to '0' if one used --disable-option
*/
- *((my_bool*) optp->value)= (my_bool) (!optend || *optend == '1');
+ *((my_bool*) value)= (my_bool) (!optend || *optend == '1');
(*argc)--;
get_one_option(optp->id, optp, argument);
continue;
}
argument= optend;
}
- else if (optp->arg_type == OPT_ARG && optp->var_type == GET_BOOL)
+ else if (optp->arg_type == OPT_ARG &&
+ (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
{
if (optend == disabled_my_option)
- *((my_bool*) optp->value)= (my_bool) 0;
+ *((my_bool*) value)= (my_bool) 0;
else
{
if (!optend) /* No argument -> enable option */
- *((my_bool*) optp->value)= (my_bool) 1;
+ *((my_bool*) value)= (my_bool) 1;
else /* If argument differs from 0, enable option, else disable */
- *((my_bool*) optp->value)= (my_bool) atoi(optend) != 0;
+ *((my_bool*) value)= (my_bool) atoi(optend) != 0;
}
(*argc)--;
continue;
@@ -326,7 +342,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: option '--%s' requires an argument\n",
- progname, optp->name);
+ my_progname, optp->name);
return EXIT_ARGUMENT_REQUIRED;
}
argument= *pos;
@@ -346,7 +362,8 @@ int handle_options(int *argc, char ***argv,
{
/* Option recognized. Find next what to do with it */
opt_found= 1;
- if (optp->var_type == GET_BOOL && optp->arg_type == NO_ARG)
+ if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL &&
+ optp->arg_type == NO_ARG)
{
*((my_bool*) optp->value)= (my_bool) 1;
get_one_option(optp->id, optp, argument);
@@ -370,7 +387,7 @@ int handle_options(int *argc, char ***argv,
if (my_getopt_print_errors)
fprintf(stderr,
"%s: option '-%c' requires an argument\n",
- progname, optp->id);
+ my_progname, optp->id);
return EXIT_ARGUMENT_REQUIRED;
}
argument= *pos;
@@ -378,11 +395,12 @@ int handle_options(int *argc, char ***argv,
/* the other loop will break, because *optend + 1 == 0 */
}
}
- if ((error= setval(optp, argument, set_maximum_value)))
+ if ((error= setval(optp, optp->value, argument,
+ set_maximum_value)))
{
fprintf(stderr,
"%s: Error while setting value '%s' to '%s'\n",
- progname, argument, optp->name);
+ my_progname, argument, optp->name);
return error;
}
get_one_option(optp->id, optp, argument);
@@ -393,18 +411,18 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr,
- "%s: unknown option '-%c'\n", progname, *optend);
+ "%s: unknown option '-%c'\n", my_progname, *optend);
return EXIT_UNKNOWN_OPTION;
}
}
(*argc)--; /* option handled (short), decrease argument count */
continue;
}
- if ((error= setval(optp, argument, set_maximum_value)))
+ if ((error= setval(optp, value, argument, set_maximum_value)))
{
fprintf(stderr,
"%s: Error while setting value '%s' to '%s'\n",
- progname, argument, optp->name);
+ my_progname, argument, optp->name);
return error;
}
get_one_option(optp->id, optp, argument);
@@ -424,6 +442,49 @@ int handle_options(int *argc, char ***argv,
return 0;
}
+
+/*
+ function: check_struct_option
+
+ Arguments: Current argument under processing from argv and a variable
+ where to store the possible key name.
+
+ Return value: In case option is a struct option, returns a pointer to
+ the current argument at the position where the struct option (key_name)
+ ends, the next character after the dot. In case argument is not a struct
+ option, returns a pointer to the argument.
+
+ key_name will hold the name of the key, or 0 if not found.
+*/
+
+static char *check_struct_option(char *cur_arg, char *key_name)
+{
+ char *ptr, *end;
+
+ ptr= strcend(cur_arg + 1, '.'); // Skip the first character
+ end= strcend(cur_arg, '=');
+
+ /*
+ If the first dot is after an equal sign, then it is part
+ of a variable value and the option is not a struct option.
+ Also, if the last character in the string before the ending
+ NULL, or the character right before equal sign is the first
+ dot found, the option is not a struct option.
+ */
+ if (end - ptr > 1)
+ {
+ uint len= ptr - cur_arg;
+ set_if_smaller(len, FN_REFLEN-1);
+ strmake(key_name, cur_arg, len);
+ return ++ptr;
+ }
+ else
+ {
+ key_name[0]= 0;
+ return cur_arg;
+ }
+}
+
/*
function: setval
@@ -431,20 +492,20 @@ int handle_options(int *argc, char ***argv,
Will set the option value to given value
*/
-static int setval(const struct my_option *opts, char *argument,
+static int setval(const struct my_option *opts, gptr *value, char *argument,
my_bool set_maximum_value)
{
int err= 0;
- if (opts->value && argument)
+ if (value && argument)
{
gptr *result_pos= ((set_maximum_value) ?
- opts->u_max_value : opts->value);
+ opts->u_max_value : value);
if (!result_pos)
return EXIT_NO_PTR_TO_VARIABLE;
- switch (opts->var_type) {
+ switch ((opts->var_type & GET_TYPE_MASK)) {
case GET_INT:
case GET_UINT: /* fall through */
*((int*) result_pos)= (int) getopt_ll(argument, opts, &err);
@@ -632,43 +693,45 @@ static void init_variables(const struct my_option *options)
{
for (; options->name; options++)
{
- if (options->value)
+ gptr *value= (options->var_type & GET_ASK_ADDR ?
+ (*getopt_get_addr)("", 0, options) : options->value);
+ if (value)
{
- switch (options->var_type) {
+ switch ((options->var_type & GET_TYPE_MASK)) {
case GET_BOOL:
if (options->u_max_value)
*((my_bool*) options->u_max_value)= (my_bool) options->max_value;
- *((my_bool*) options->value)= (my_bool) options->def_value;
+ *((my_bool*) value)= (my_bool) options->def_value;
break;
case GET_INT:
if (options->u_max_value)
*((int*) options->u_max_value)= (int) options->max_value;
- *((int*) options->value)= (int) options->def_value;
+ *((int*) value)= (int) options->def_value;
break;
case GET_UINT:
if (options->u_max_value)
*((uint*) options->u_max_value)= (uint) options->max_value;
- *((uint*) options->value)= (uint) options->def_value;
+ *((uint*) value)= (uint) options->def_value;
break;
case GET_LONG:
if (options->u_max_value)
*((long*) options->u_max_value)= (long) options->max_value;
- *((long*) options->value)= (long) options->def_value;
+ *((long*) value)= (long) options->def_value;
break;
case GET_ULONG:
if (options->u_max_value)
*((ulong*) options->u_max_value)= (ulong) options->max_value;
- *((ulong*) options->value)= (ulong) options->def_value;
+ *((ulong*) value)= (ulong) options->def_value;
break;
case GET_LL:
if (options->u_max_value)
*((longlong*) options->u_max_value)= (longlong) options->max_value;
- *((longlong*) options->value)= (longlong) options->def_value;
+ *((longlong*) value)= (longlong) options->def_value;
break;
case GET_ULL:
if (options->u_max_value)
*((ulonglong*) options->u_max_value)= (ulonglong) options->max_value;
- *((ulonglong*) options->value)= (ulonglong) options->def_value;
+ *((ulonglong*) value)= (ulonglong) options->def_value;
break;
default: /* dummy default to avoid compiler warnings */
break;
@@ -706,13 +769,15 @@ void my_print_help(const struct my_option *options)
{
printf("--%s", optp->name);
col+= 2 + strlen(optp->name);
- if (optp->var_type == GET_STR || optp->var_type == GET_STR_ALLOC)
+ if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
+ (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC)
{
printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "",
optp->arg_type == OPT_ARG ? "]" : "");
col+= (optp->arg_type == OPT_ARG) ? 8 : 6;
}
- else if (optp->var_type == GET_NO_ARG || optp->var_type == GET_BOOL)
+ else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
+ (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
{
putchar(' ');
col++;
@@ -769,38 +834,40 @@ void my_print_variables(const struct my_option *options)
printf("--------------------------------- -----------------------------\n");
for (optp= options; optp->id; optp++)
{
- if (optp->value)
+ gptr *value= (optp->var_type & GET_ASK_ADDR ?
+ (*getopt_get_addr)("", 0, optp) : optp->value);
+ if (value)
{
printf("%s", optp->name);
length= strlen(optp->name);
for (; length < name_space; length++)
putchar(' ');
- switch (optp->var_type) {
+ switch ((optp->var_type & GET_TYPE_MASK)) {
case GET_STR:
case GET_STR_ALLOC: /* fall through */
- printf("%s\n", *((char**) optp->value) ? *((char**) optp->value) :
+ printf("%s\n", *((char**) value) ? *((char**) value) :
"(No default value)");
break;
case GET_BOOL:
- printf("%s\n", *((my_bool*) optp->value) ? "TRUE" : "FALSE");
+ printf("%s\n", *((my_bool*) value) ? "TRUE" : "FALSE");
break;
case GET_INT:
- printf("%d\n", *((int*) optp->value));
+ printf("%d\n", *((int*) value));
break;
case GET_UINT:
- printf("%d\n", *((uint*) optp->value));
+ printf("%d\n", *((uint*) value));
break;
case GET_LONG:
- printf("%lu\n", *((long*) optp->value));
+ printf("%lu\n", *((long*) value));
break;
case GET_ULONG:
- printf("%lu\n", *((ulong*) optp->value));
+ printf("%lu\n", *((ulong*) value));
break;
case GET_LL:
- printf("%s\n", llstr(*((longlong*) optp->value), buff));
+ printf("%s\n", llstr(*((longlong*) value), buff));
break;
case GET_ULL:
- longlong2str(*((ulonglong*) optp->value), buff, 10);
+ longlong2str(*((ulonglong*) value), buff, 10);
printf("%s\n", buff);
break;
default: /* dummy default to avoid compiler warnings */
diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c
index abef0096e28..b9468d42cfc 100644
--- a/mysys/my_symlink.c
+++ b/mysys/my_symlink.c
@@ -123,20 +123,22 @@ int my_realpath(char *to, const char *filename,
}
else
{
- /* Realpath didn't work; Use original name */
+ /*
+ Realpath didn't work; Use my_load_path() which is a poor substitute
+ original name but will at least be able to resolve paths that starts
+ with '.'.
+ */
DBUG_PRINT("error",("realpath failed with errno: %d", errno));
my_errno=errno;
if (MyFlags & MY_WME)
my_error(EE_REALPATH, MYF(0), filename, my_errno);
- if (to != filename)
- strmov(to,filename);
+ my_load_path(to, filename, NullS);
result= -1;
}
}
DBUG_RETURN(result);
#else
- if (to != filename)
- strmov(to,filename);
+ my_load_path(to, filename, NullS);
return 0;
#endif
}
diff --git a/mysys/tree.c b/mysys/tree.c
index a3b69ebff5e..91d2f9771b5 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -46,6 +46,16 @@
Implemented by monty.
*/
+/*
+ NOTE:
+ tree->compare function should be ALWAYS called as
+ (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), key)
+ and not other way around, as
+ (*tree->compare)(custom_arg, key, ELEMENT_KEY(tree,element))
+
+ ft_boolean_search.c (at least) relies on that.
+*/
+
#include "mysys_priv.h"
#include <m_string.h>
#include <my_tree.h>
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 6006222992e..ff35170dcf3 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -62,7 +62,7 @@ EXTRA_DIST = $(EXTRA_SCRIPTS) \
mysqlaccess.conf \
mysqlbug
-pkgdata_DATA = fill_help_tables.sql mysql_fix_privilege_tables.sql
+dist_pkgdata_DATA = fill_help_tables.sql mysql_fix_privilege_tables.sql
# mysqlbug should be distributed built so that people can report build
# failures with it.
diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh
index f76fe02e2bd..df7ac29ee0d 100755
--- a/scripts/make_win_src_distribution.sh
+++ b/scripts/make_win_src_distribution.sh
@@ -59,6 +59,8 @@ show_usage()
echo ""
echo " --debug Debug, without creating the package"
echo " --tmp Specify the temporary location"
+ echo " --suffix Suffix name for the package"
+ echo " --dirname Directory name to copy files (intermediate)"
echo " --silent Do not list verbosely files processed"
echo " --tar Create tar.gz package instead of .zip"
echo " --help Show this help message"
@@ -249,7 +251,7 @@ touch $BASE/innobase/ib_config.h
cd $SOURCE
for i in COPYING ChangeLog README \
INSTALL-SOURCE INSTALL-WIN \
- INSTALL-SOURCE-WIN \
+ INSTALL-WIN-SOURCE \
Docs/manual_toc.html Docs/manual.html \
Docs/mysqld_error.txt Docs/INSTALL-BINARY
@@ -348,7 +350,7 @@ set_tarzip_options()
else
ZIPFILE1=zip
ZIPFILE2=""
- OPT="-vr"
+ OPT="-r"
EXT=".zip"
NEED_COMPRESS=0
if [ "$SILENT" = "1" ] ; then
@@ -380,6 +382,7 @@ print_debug "Using $tar to create archive"
cd $TMP
+rm -f $SOURCE/$NEW_NAME$EXT
$tar $OPT $SOURCE/$NEW_NAME$EXT $NEW_DIR_NAME
cd $SOURCE
diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh
index 51fbb8a8097..2739c45e750 100644
--- a/scripts/mysql_create_system_tables.sh
+++ b/scripts/mysql_create_system_tables.sh
@@ -149,16 +149,16 @@ then
INSERT INTO user (host,user) values ('localhost','');
INSERT INTO user (host,user) values ('$hostname','');"
else
- i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
- REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
- INSERT INTO user (host,user) values ('localhost','');"
+ i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);"
if test "$windows" -eq 0
then
i_u="$i_u
INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
- REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
- INSERT INTO user (host,user) values ('$hostname','');"
- fi
+ INSERT INTO user (host,user) values ('$hostname','');
+ INSERT INTO user (host,user) values ('localhost','');"
+ else
+ i_u="INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);"
+ fi
fi
fi
diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh
index 5d392f719f0..4b6f74eae06 100644
--- a/scripts/mysql_fix_privilege_tables.sh
+++ b/scripts/mysql_fix_privilege_tables.sh
@@ -57,6 +57,9 @@ then
elif test -x @bindir@/mysql_print_defaults
then
print_defaults="@bindir@/mysql_print_defaults"
+elif test -x extra/my_print_defaults
+then
+ print_defaults="extra/my_print_defaults"
else
print_defaults="my_print_defaults"
fi
diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql
index 3466e3cf799..43dc6d89481 100644
--- a/scripts/mysql_fix_privilege_tables.sql
+++ b/scripts/mysql_fix_privilege_tables.sql
@@ -4,7 +4,7 @@ ALTER TABLE host type=MyISAM;
ALTER TABLE func type=MyISAM;
ALTER TABLE columns_priv type=MyISAM;
ALTER TABLE tables_priv type=MyISAM;
-ALTER TABLE user change password password char(45) not null;
+ALTER TABLE user change Password Password char(45) not null;
ALTER TABLE user add File_priv enum('N','Y') NOT NULL;
CREATE TABLE IF NOT EXISTS func (
name char(64) DEFAULT '' NOT NULL,
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index 9e4f35dd5e1..a69995e51a0 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -191,7 +191,7 @@ then
echo "Installing all prepared tables"
fi
if (
- $pkgdatadir/mysql_create_system_tables $create_option $mdata $hostname $windows
+ $bindir/mysql_create_system_tables $create_option $mdata $hostname $windows
if test -n "$fill_help_tables"
then
cat $fill_help_tables
diff --git a/sql-common/Makefile.am b/sql-common/Makefile.am
new file mode 100644
index 00000000000..1f397c0ea87
--- /dev/null
+++ b/sql-common/Makefile.am
@@ -0,0 +1,21 @@
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+## Process this file with automake to create Makefile.in
+EXTRA_DIST = client.c pack.c
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/sql-common/client.c b/sql-common/client.c
index 33f2b996971..721164c8301 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -2022,7 +2022,6 @@ my_bool mysql_reconnect(MYSQL *mysql)
}
mysql_init(&tmp_mysql);
tmp_mysql.options=mysql->options;
- bzero((char*) &mysql->options,sizeof(mysql->options));
tmp_mysql.rpl_pivot = mysql->rpl_pivot;
if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
mysql->db, mysql->port, mysql->unix_socket,
@@ -2033,7 +2032,9 @@ my_bool mysql_reconnect(MYSQL *mysql)
strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
DBUG_RETURN(1);
}
- tmp_mysql.free_me=mysql->free_me;
+ tmp_mysql.free_me= mysql->free_me;
+ /* Don't free options as these are now used in tmp_mysql */
+ bzero((char*) &mysql->options,sizeof(mysql->options));
mysql->free_me=0;
mysql_close(mysql);
*mysql=tmp_mysql;
@@ -2070,9 +2071,6 @@ mysql_select_db(MYSQL *mysql, const char *db)
static void mysql_close_free_options(MYSQL *mysql)
{
- my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
@@ -2099,14 +2097,17 @@ static void mysql_close_free_options(MYSQL *mysql)
if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
#endif /* HAVE_SMEM */
- bzero((char*) &mysql->options,sizeof(mysql->options));
+ bzero((char*) &mysql->options,sizeof(mysql->options));
}
static void mysql_close_free(MYSQL *mysql)
{
- /* Clear pointers for better safety */
my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+ /* Clear pointers for better safety */
mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
}
diff --git a/sql/Makefile.am b/sql/Makefile.am
index fd02cc906d7..5781b6181d2 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -117,7 +117,7 @@ gen_lex_hash.o: gen_lex_hash.cc lex.h
sql_yacc.cc: sql_yacc.yy
sql_yacc.h: sql_yacc.yy
-sql_yacc.o: sql_yacc.cc sql_yacc.h
+sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS)
@echo "Note: The following compile may take a long time."
@echo "If it fails, re-run configure with --with-low-memory"
$(CXXCOMPILE) $(LM_CFLAGS) -c $<
diff --git a/sql/field.cc b/sql/field.cc
index 484eab5e130..2f89dd43c3f 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -183,7 +183,7 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
field_name(field_name_arg),
query_id(0),key_start(0),part_of_key(0),part_of_sortkey(0),
unireg_check(unireg_check_arg),
- field_length(length_arg),null_bit(null_bit_arg)
+ field_length(length_arg),null_bit(null_bit_arg),abs_offset(0)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
comment.str= (char*) "";
@@ -2672,6 +2672,7 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg,
:Field_str(ptr_arg, 19, (uchar*) 0,0,
unireg_check_arg, field_name_arg, table_arg, cs)
{
+ flags|=ZEROFILL_FLAG; /* 4.0 MYD compatibility */
if (table && !table->timestamp_field)
{
table->timestamp_field= this; // Automatic timestamp
@@ -3151,11 +3152,13 @@ bool Field_time::get_time(TIME *ltime)
ltime->neg= 1;
tmp=-tmp;
}
+ ltime->day= 0;
ltime->hour= (int) (tmp/10000);
tmp-=ltime->hour*10000;
ltime->minute= (int) tmp/100;
ltime->second= (int) tmp % 100;
ltime->second_part=0;
+ ltime->time_type= TIMESTAMP_TIME;
return 0;
}
diff --git a/sql/field.h b/sql/field.h
index a72ccfa8354..5df7d554c35 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -66,6 +66,7 @@ public:
uint32 field_length; // Length of field
uint16 flags;
uchar null_bit; // Bit used to test null bit
+ uint abs_offset; // use only in group_concat
Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg,
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index ec2488f520a..144e6d7e74a 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -489,6 +489,8 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
if (!to->eq_def(from))
return do_field_string;
}
+ else if (to->charset() != from->charset())
+ return do_field_string;
else if (to->real_type() == FIELD_TYPE_VAR_STRING && to_length !=
from_length)
return do_varstring;
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 3f660abea80..70322cef6fd 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -689,6 +689,72 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
/*
+ Preload pages of the index file for a table into the key cache.
+*/
+
+int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt)
+{
+ int error;
+ const char *errmsg;
+ ulonglong map= ~(ulonglong) 0;
+ TABLE_LIST *table_list= table->pos_in_table_list;
+ my_bool ignore_leaves= table_list->ignore_leaves;
+
+ DBUG_ENTER("ha_myisam::preload_keys");
+
+ /* Check validity of the index references */
+ if (table_list->use_index)
+ {
+ key_map kmap= get_key_map_from_key_list(table, table_list->use_index);
+ if (kmap == ~(key_map) 0)
+ {
+ errmsg= thd->net.last_error;
+ error= HA_ADMIN_FAILED;
+ goto err;
+ }
+ if (kmap)
+ map= kmap;
+ }
+
+ mi_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE,
+ (void *) &thd->variables.preload_buff_size);
+
+ if ((error= mi_preload(file, map, ignore_leaves)))
+ {
+ switch (error) {
+ case HA_ERR_NON_UNIQUE_BLOCK_SIZE:
+ errmsg= "Indexes use different block sizes";
+ break;
+ case HA_ERR_OUT_OF_MEM:
+ errmsg= "Failed to allocate buffer";
+ break;
+ default:
+ char buf[ERRMSGSIZE+20];
+ my_snprintf(buf, ERRMSGSIZE,
+ "Failed to read from index file (errno: %d)", my_errno);
+ errmsg= buf;
+ }
+ error= HA_ADMIN_FAILED;
+ goto err;
+ }
+
+ DBUG_RETURN(HA_ADMIN_OK);
+
+ err:
+ {
+ MI_CHECK param;
+ myisamchk_init(&param);
+ param.thd= thd;
+ param.op_name= (char*)"preload_keys";
+ param.db_name= table->table_cache_key;
+ param.table_name= table->table_name;
+ param.testflag= 0;
+ mi_check_print_error(&param, errmsg);
+ DBUG_RETURN(error);
+ }
+}
+
+/*
Deactive all not unique index that can be recreated fast
SYNOPSIS
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index 154429ecc0d..8486e25556b 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -127,6 +127,7 @@ class ha_myisam: public handler
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int restore(THD* thd, HA_CHECK_OPT* check_opt);
int backup(THD* thd, HA_CHECK_OPT* check_opt);
+ int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
#ifdef HAVE_REPLICATION
int dump(THD* thd, int fd);
int net_read_dump(NET* net);
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 5f07bbc4140..a0449e83222 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -303,14 +303,40 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
return to;
}
+
+/* Find out database name and table name from a filename */
+
+static void split_file_name(const char *file_name,
+ LEX_STRING *db, LEX_STRING *name)
+{
+ uint name_length, dir_length, prefix_length;
+ char buff[FN_REFLEN];
+
+ db->length= 0;
+ name_length= (uint) (strmake(buff, file_name, sizeof(buff)-1) - buff);
+ dir_length= dirname_length(buff);
+ if (dir_length > 1)
+ {
+ /* Get database */
+ buff[dir_length-1]= 0; // Remove end '/'
+ prefix_length= dirname_length(buff);
+ db->str= (char*) file_name+ prefix_length;
+ db->length= dir_length - prefix_length -1;
+ }
+ name->str= (char*) file_name+ dir_length;
+ name->length= (uint) (fn_ext(name->str) - name->str);
+}
+
+
void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
{
- // [phi] auto_increment stuff is missing (but currently not needed)
DBUG_ENTER("ha_myisammrg::update_create_info");
+
if (!(create_info->used_fields & HA_CREATE_USED_UNION))
{
MYRG_TABLE *open_table;
THD *thd=current_thd;
+
create_info->merge_list.next= &create_info->merge_list.first;
create_info->merge_list.elements=0;
@@ -318,14 +344,17 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
open_table != file->end_table ;
open_table++)
{
- char *name=open_table->table->filename;
- char buff[FN_REFLEN];
TABLE_LIST *ptr;
+ LEX_STRING db, name;
+
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
goto err;
- fn_format(buff,name,"","",3);
- if (!(ptr->real_name=thd->strdup(buff)))
+ split_file_name(open_table->table->filename, &db, &name);
+ if (!(ptr->real_name= thd->strmake(name.str, name.length)))
+ goto err;
+ if (db.length && !(ptr->db= thd->strmake(db.str, db.length)))
goto err;
+
create_info->merge_list.elements++;
(*create_info->merge_list.next) = (byte*) ptr;
create_info->merge_list.next= (byte**) &ptr->next;
@@ -344,37 +373,34 @@ err:
DBUG_VOID_RETURN;
}
+
int ha_myisammrg::create(const char *name, register TABLE *form,
HA_CREATE_INFO *create_info)
{
char buff[FN_REFLEN],**table_names,**pos;
TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first;
+ THD *thd= current_thd;
DBUG_ENTER("ha_myisammrg::create");
- if (!(table_names= (char**) sql_alloc((create_info->merge_list.elements+1)*
- sizeof(char*))))
+ if (!(table_names= (char**) thd->alloc((create_info->merge_list.elements+1)*
+ sizeof(char*))))
DBUG_RETURN(1);
for (pos=table_names ; tables ; tables=tables->next)
{
char *table_name;
+ TABLE **tbl= 0;
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ tbl= find_temporary_table(thd, tables->db, tables->real_name);
+ if (!tbl)
{
- TABLE **tbl=find_temporary_table(current_thd,
- tables->db, tables->real_name);
- if (!tbl)
- {
- table_name=sql_alloc(1+
- my_snprintf(buff,FN_REFLEN,"%s/%s/%s",mysql_real_data_home,
- tables->db, tables->real_name));
- if (!table_name)
- DBUG_RETURN(1);
- strcpy(table_name, buff);
- }
- else
- table_name=(*tbl)->path;
+ uint length= my_snprintf(buff,FN_REFLEN,"%s%s/%s",
+ mysql_real_data_home,
+ tables->db, tables->real_name);
+ if (!(table_name= thd->strmake(buff, length)))
+ DBUG_RETURN(1);
}
else
- table_name=tables->real_name;
+ table_name=(*tbl)->path;
*pos++= table_name;
}
*pos=0;
@@ -384,9 +410,13 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
(my_bool) 0));
}
+
void ha_myisammrg::append_create_info(String *packet)
{
- char buff[FN_REFLEN];
+ const char *current_db;
+ uint db_length;
+ THD *thd= current_thd;
+
if (file->merge_insert_method != MERGE_INSERT_DISABLED)
{
packet->append(" INSERT_METHOD=",15);
@@ -395,15 +425,26 @@ void ha_myisammrg::append_create_info(String *packet)
packet->append(" UNION=(",8);
MYRG_TABLE *open_table,*first;
+ current_db= table->table_cache_key;
+ db_length= strlen(current_db);
+
for (first=open_table=file->open_tables ;
open_table != file->end_table ;
open_table++)
{
- char *name= open_table->table->filename;
- fn_format(buff,name,"","",3);
+ LEX_STRING db, name;
+ split_file_name(open_table->table->filename, &db, &name);
if (open_table != first)
packet->append(',');
- packet->append(buff,(uint) strlen(buff));
+ /* Report database for mapped table if it isn't in current database */
+ if (db.length &&
+ (db_length != db.length ||
+ strncmp(current_db, db.str, db.length)))
+ {
+ append_identifier(thd, packet, db.str, db.length);
+ packet->append('.');
+ }
+ append_identifier(thd, packet, name.str, name.length);
}
packet->append(')');
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 493959f0473..150a0d5329e 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -620,6 +620,11 @@ int handler::analyze(THD* thd, HA_CHECK_OPT* check_opt)
return HA_ADMIN_NOT_IMPLEMENTED;
}
+int handler::preload_keys(THD* thd, HA_CHECK_OPT* check_opt)
+{
+ return HA_ADMIN_NOT_IMPLEMENTED;
+}
+
/*
Read first row (only) from a table
This is never called for InnoDB or BDB tables, as these table types
@@ -704,6 +709,8 @@ void handler::update_auto_increment()
nr=get_auto_increment();
if (!table->next_number_field->store(nr))
thd->insert_id((ulonglong) nr);
+ else
+ thd->insert_id(table->next_number_field->val_int());
auto_increment_column_changed=1;
DBUG_VOID_RETURN;
}
diff --git a/sql/handler.h b/sql/handler.h
index 97ce295d520..08a7c83d328 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -305,6 +305,7 @@ public:
virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt);
virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt);
virtual int backup(THD* thd, HA_CHECK_OPT* check_opt);
+ virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
/*
restore assumes .frm file must exist, and that generate_table() has been
called; It will just copy the data file and run repair.
diff --git a/sql/item.cc b/sql/item.cc
index cdd78572a0a..072dec4e6a6 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -23,6 +23,10 @@
#include <m_ctype.h>
#include "my_dir.h"
+static void mark_as_dependent(bool outer_resolving,
+ SELECT_LEX *last, SELECT_LEX_NODE *current,
+ Item_ident *item);
+
/*****************************************************************************
** Item functions
*****************************************************************************/
@@ -39,13 +43,21 @@ Item::Item():
{
marker= 0;
maybe_null=null_value=with_sum_func=unsigned_flag=0;
- coercibility=COER_IMPLICIT;
+ set_charset(default_charset(), DERIVATION_COERCIBLE);
name= 0;
decimals= 0; max_length= 0;
THD *thd= current_thd;
next= thd->free_list; // Put in free list
thd->free_list= this;
loop_id= 0;
+ /*
+ Item constructor can be called during execution other tnen SQL_COM
+ command => we should check thd->lex.current_select on zero (thd->lex
+ can be uninitialised)
+ */
+ if (thd->lex.current_select &&
+ thd->lex.current_select->parsing_place == SELECT_LEX_NODE::SELECT_LIST)
+ thd->lex.current_select->select_items++;
}
/*
@@ -65,7 +77,7 @@ Item::Item(THD *thd, Item &item):
unsigned_flag(item.unsigned_flag),
with_sum_func(item.with_sum_func),
fixed(item.fixed),
- coercibility(item.coercibility)
+ collation(item.collation)
{
next=thd->free_list; // Put in free list
thd->free_list= this;
@@ -181,44 +193,61 @@ CHARSET_INFO * Item::default_charset() const
return current_thd->variables.collation_connection;
}
-bool Item::set_charset(CHARSET_INFO *cs1, enum coercion co1,
- CHARSET_INFO *cs2, enum coercion co2)
+bool DTCollation::aggregate(DTCollation &dt)
{
- if (cs1 == &my_charset_bin || cs2 == &my_charset_bin)
+ if (!my_charset_same(collation, dt.collation))
{
- set_charset(&my_charset_bin, COER_NOCOLL);
- return 0;
+ /*
+ We do allow to use binary strings (like BLOBS)
+ together with character strings.
+ Binaries have more precedance than a character
+ string of the same derivation.
+ */
+ if (collation == &my_charset_bin)
+ {
+ if (derivation <= dt.derivation)
+ ; // Do nothing
+ else
+ set(dt);
+ }
+ else if (dt.collation == &my_charset_bin)
+ {
+ if (dt.derivation <= derivation)
+ set(dt);
+ else
+ ; // Do nothing
+ }
+ else
+ {
+ set(0, DERIVATION_NONE);
+ return 1;
+ }
}
-
- if (!my_charset_same(cs1,cs2))
- return 1;
-
- if (co1 < co2)
+ else if (derivation < dt.derivation)
{
- set_charset(cs1, co1);
+ // Do nothing
}
- else if (co2 < co1)
+ else if (dt.derivation < derivation)
{
- set_charset(cs2, co2);
+ set(dt);
}
- else // co2 == co1
- {
- if (cs1 != cs2)
+ else
+ {
+ if (collation == dt.collation)
{
- if (co1 == COER_EXPLICIT)
- {
- return 1;
- }
- else
+ // Do nothing
+ }
+ else
+ {
+ if (derivation == DERIVATION_EXPLICIT)
{
- CHARSET_INFO *bin= get_charset_by_csname(cs1->csname, MY_CS_BINSORT,MYF(0));
- if (!bin)
- return 1;
- set_charset(bin, COER_NOCOLL);
+ set(0, DERIVATION_NONE);
+ return 1;
}
+ CHARSET_INFO *bin= get_charset_by_csname(collation->csname,
+ MY_CS_BINSORT,MYF(0));
+ set(bin, DERIVATION_NONE);
}
- else
- set_charset(cs2, co2);
}
return 0;
}
@@ -226,7 +255,7 @@ bool Item::set_charset(CHARSET_INFO *cs1, enum coercion co1,
Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
{
set_field(f);
- coercibility= COER_IMPLICIT;
+ set_charset(DERIVATION_IMPLICIT);
fixed= 1; // This item is not needed in fix_fields
}
@@ -235,7 +264,7 @@ Item_field::Item_field(THD *thd, Item_field &item):
Item_ident(thd, item),
field(item.field),
result_field(item.result_field)
-{ coercibility= COER_IMPLICIT; }
+{ set_charset(DERIVATION_IMPLICIT); }
void Item_field::set_field(Field *field_par)
{
@@ -247,7 +276,7 @@ void Item_field::set_field(Field *field_par)
field_name=field_par->field_name;
db_name=field_par->table->table_cache_key;
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
- set_charset(field_par->charset(), COER_IMPLICIT);
+ set_charset(field_par->charset(), DERIVATION_IMPLICIT);
}
const char *Item_ident::full_name() const
@@ -767,6 +796,37 @@ bool Item_ref_null_helper::get_date(TIME *ltime, bool fuzzydate)
return (owner->was_null|= null_value= (*ref)->get_date(ltime, fuzzydate));
}
+
+/*
+ Mark item and SELECT_LEXs as dependent if it is not outer resolving
+
+ SYNOPSIS
+ mark_as_dependent()
+ outer_resolving - flag of outer resolving
+ last - select from which current item depend
+ current - current select
+ item - item which should be marked
+*/
+
+static void mark_as_dependent(bool outer_resolving,
+ SELECT_LEX *last, SELECT_LEX_NODE *current,
+ Item_ident *item)
+{
+ /*
+ only last check is need, i.e.
+ "last != current"
+ first check added for speed up (check boolean should be faster
+ then comparing pointers and this condition usually true)
+ */
+ if (!outer_resolving || ((SELECT_LEX_NODE *)last) != current)
+ {
+ // store pointer on SELECT_LEX from wich item is dependent
+ item->depended_from= last;
+ current->mark_as_dependent(last);
+ }
+}
+
+
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (!field) // If field is not checked
@@ -790,6 +850,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
#ifdef EMBEDDED_LIBRARY
thd->net.last_errno= 0;
#endif
+ TABLE_LIST *table_list;
Item **refer= (Item **)not_found_item;
uint counter;
// Prevent using outer fields in subselects, that is not supported now
@@ -800,8 +861,14 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
sl;
sl= sl->outer_select())
{
+ table_list= (last= sl)->get_table_list();
+ if (sl->insert_select && table_list)
+ {
+ // it is primary INSERT st_select_lex => skip first table resolving
+ table_list= table_list->next;
+ }
if ((tmp= find_field_in_tables(thd, this,
- (last= sl)->get_table_list(), &where,
+ table_list, &where,
0)) != not_found_field)
break;
if ((refer= find_item_in_list(this, sl->item_list, &counter,
@@ -831,29 +898,22 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return -1;
}
- Item_ref *r;
- *ref= r= new Item_ref(last->ref_pointer_array + counter
- , (char *)table_name,
- (char *)field_name);
- if (!r)
+ Item_ref *rf;
+ *ref= rf= new Item_ref(last->ref_pointer_array + counter,
+ (char *)table_name,
+ (char *)field_name);
+ if (!rf)
return 1;
- if (r->fix_fields(thd, tables, ref) || r->check_cols(1))
+ if (rf->fix_fields(thd, tables, ref) || rf->check_cols(1))
return 1;
- // store pointer on SELECT_LEX from which item is dependent
- r->depended_from= last;
- cursel->mark_as_dependent(last);
+
+ mark_as_dependent(outer_resolving, last, cursel, rf);
return 0;
}
else
{
- // store pointer on SELECT_LEX from wich item is dependent
- depended_from= last;
- /*
- Mark all selects from resolved to 1 before select where was
- found table as depended (of select where was found table)
- */
- thd->lex.current_select->mark_as_dependent(last);
- if (depended_from->having_fix_field)
+ mark_as_dependent(outer_resolving, last, cursel, this);
+ if (last->having_fix_field)
{
Item_ref *rf;
*ref= rf= new Item_ref((where->db[0]?where->db:0),
@@ -1098,7 +1158,7 @@ Item_varbinary::Item_varbinary(const char *str, uint str_length)
str+=2;
}
*ptr=0; // Keep purify happy
- coercibility= COER_COERCIBLE;
+ set_charset(&my_charset_bin, DERIVATION_COERCIBLE);
}
longlong Item_varbinary::val_int()
@@ -1254,7 +1314,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
uint counter;
if (!ref)
{
- TABLE_LIST *where= 0;
+ TABLE_LIST *where= 0, *table_list;
SELECT_LEX *sl= (outer_resolving?
thd->lex.current_select->select_lex():
thd->lex.current_select->outer_select());
@@ -1293,8 +1353,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item)
break;
+ table_list= sl->get_table_list();
+ if (sl->insert_select && table_list)
+ {
+ // it is primary INSERT st_select_lex => skip first table resolving
+ table_list= table_list->next;
+ }
if ((tmp= find_field_in_tables(thd, this,
- sl->get_table_list(), &where,
+ table_list, &where,
0)) != not_found_field)
break;
if (sl->master_unit()->first_select()->linkage ==
@@ -1319,12 +1385,10 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
else if (tmp != not_found_field)
{
ref= 0; // To prevent "delete *ref;" on ~Item_erf() of this item
- Item_field* f;
- if (!((*reference)= f= new Item_field(tmp)))
+ Item_field* fld;
+ if (!((*reference)= fld= new Item_field(tmp)))
return 1;
- // store pointer on SELECT_LEX from wich item is dependent
- f->depended_from= last;
- thd->lex.current_select->mark_as_dependent(last);
+ mark_as_dependent(outer_resolving, last, thd->lex.current_select, fld);
return 0;
}
else
@@ -1335,11 +1399,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
"forward reference in item list");
return -1;
}
- /*
- depended_from: pointer on SELECT_LEX from wich item is dependent
- */
- ref= (depended_from= last)->ref_pointer_array + counter;
- thd->lex.current_select->mark_as_dependent(last);
+ mark_as_dependent(outer_resolving, last, thd->lex.current_select,
+ this);
+ ref= last->ref_pointer_array + counter;
}
}
else if (!ref)
diff --git a/sql/item.h b/sql/item.h
index 5cfe8eb3907..57061221878 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -23,6 +23,65 @@ class Protocol;
struct st_table_list;
void item_init(void); /* Init item functions */
+
+/*
+ "Declared Type Collation"
+ A combination of collation and its deriviation.
+*/
+
+enum Derivation
+{
+ DERIVATION_COERCIBLE= 3,
+ DERIVATION_IMPLICIT= 2,
+ DERIVATION_NONE= 1,
+ DERIVATION_EXPLICIT= 0
+};
+
+class DTCollation {
+public:
+ CHARSET_INFO *collation;
+ enum Derivation derivation;
+
+ DTCollation()
+ {
+ collation= &my_charset_bin;
+ derivation= DERIVATION_NONE;
+ }
+ DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg)
+ {
+ collation= collation_arg;
+ derivation= derivation_arg;
+ }
+ void set(DTCollation &dt)
+ {
+ collation= dt.collation;
+ derivation= dt.derivation;
+ }
+ void set(CHARSET_INFO *collation_arg, Derivation derivation_arg)
+ {
+ collation= collation_arg;
+ derivation= derivation_arg;
+ }
+ void set(CHARSET_INFO *collation_arg)
+ { collation= collation_arg; }
+ void set(Derivation derivation_arg)
+ { derivation= derivation_arg; }
+ bool aggregate(DTCollation &dt);
+ bool set(DTCollation &dt1, DTCollation &dt2)
+ { set(dt1); return aggregate(dt2); }
+ const char *derivation_name() const
+ {
+ switch(derivation)
+ {
+ case DERIVATION_COERCIBLE: return "COERCIBLE";
+ case DERIVATION_IMPLICIT: return "IMPLICIT";
+ case DERIVATION_EXPLICIT: return "EXPLICIT";
+ case DERIVATION_NONE: return "NONE";
+ default: return "UNKNOWN";
+ }
+ }
+};
+
class Item {
uint loop_id; /* Used to find selfrefering loops */
Item(const Item &); /* Prevent use of these */
@@ -41,19 +100,6 @@ public:
SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
- enum coercion { COER_COERCIBLE=3, COER_IMPLICIT=2,
- COER_NOCOLL=1, COER_EXPLICIT=0 };
- const char *coercion_name(enum coercion coer) const
- {
- switch(coer)
- {
- case COER_COERCIBLE: return "COERCIBLE";
- case COER_IMPLICIT: return "IMPLICIT";
- case COER_EXPLICIT: return "EXPLICIT";
- case COER_NOCOLL: return "NO COLLATION";
- default: return "UNKNOWN";
- }
- }
String str_value; /* used to store value */
my_string name; /* Name from select */
@@ -65,8 +111,8 @@ public:
my_bool unsigned_flag;
my_bool with_sum_func;
my_bool fixed; /* If item fixed with fix_fields */
- enum coercion coercibility; /* Precedence order of collation */
-
+ DTCollation collation;
+
// alloc & destruct is done as start of select using sql_alloc
Item();
/*
@@ -123,18 +169,22 @@ public:
virtual Item *real_item() { return this; }
virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
- virtual bool binary() const
- { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
CHARSET_INFO *default_charset() const;
- CHARSET_INFO *charset() const { return str_value.charset(); };
- void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); }
- void set_charset(CHARSET_INFO *cs, enum coercion coer)
- {
- str_value.set_charset(cs);
- coercibility= coer;
+ Derivation derivation() const { return collation.derivation; }
+ CHARSET_INFO *charset() const { return collation.collation; }
+ void set_charset(CHARSET_INFO *cs)
+ { collation.collation= cs; }
+ void set_charset(Derivation dv)
+ { collation.derivation= dv; }
+ void set_charset(CHARSET_INFO *cs, Derivation dv)
+ { collation.collation= cs; collation.derivation= dv; }
+ void set_charset(Item &item)
+ { collation= item.collation; }
+ void set_charset(DTCollation *collation_arg)
+ {
+ collation.collation= collation_arg->collation;
+ collation.derivation= collation_arg->derivation;
}
- bool set_charset(CHARSET_INFO *cs1, enum coercion co1,
- CHARSET_INFO *cs2, enum coercion co2);
virtual void set_outer_resolving() {}
// Row emulation
@@ -180,7 +230,7 @@ public:
Item_field(const char *db_par,const char *table_name_par,
const char *field_name_par)
:Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0)
- { coercibility= COER_IMPLICIT; }
+ { set_charset(DERIVATION_IMPLICIT); }
// Constructor need to process subselect with temporary tables (see Item)
Item_field(THD *thd, Item_field &item);
Item_field(Field *field);
@@ -381,19 +431,19 @@ class Item_string :public Item
{
public:
Item_string(const char *str,uint length,
- CHARSET_INFO *cs, enum coercion coer= COER_COERCIBLE)
+ CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
{
+ set_charset(cs, dv);
str_value.set(str,length,cs);
- coercibility= coer;
max_length=length;
set_name(str, length, cs);
decimals=NOT_FIXED_DEC;
}
Item_string(const char *name_par, const char *str, uint length,
- CHARSET_INFO *cs, enum coercion coer= COER_COERCIBLE)
+ CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
{
+ set_charset(cs, dv);
str_value.set(str,length,cs);
- coercibility= coer;
max_length=length;
set_name(name_par,0,cs);
decimals=NOT_FIXED_DEC;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index d4997f78a9e..f89b68d3879 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -23,6 +23,41 @@
#include "mysql_priv.h"
#include <m_ctype.h>
+
+static Item_result item_store_type(Item_result a,Item_result b)
+{
+ if (a == STRING_RESULT || b == STRING_RESULT)
+ return STRING_RESULT;
+ else if (a == REAL_RESULT || b == REAL_RESULT)
+ return REAL_RESULT;
+ else
+ return INT_RESULT;
+}
+
+static void agg_result_type(Item_result *type, Item **items, uint nitems)
+{
+ uint i;
+ type[0]= items[0]->result_type();
+ for (i=1 ; i < nitems ; i++)
+ type[0]= item_store_type(type[0], items[i]->result_type());
+}
+
+static void agg_cmp_type(Item_result *type, Item **items, uint nitems)
+{
+ uint i;
+ type[0]= items[0]->result_type();
+ for (i=1 ; i < nitems ; i++)
+ type[0]= item_cmp_type(type[0], items[i]->result_type());
+}
+
+static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname)
+{
+ my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
+ c1.collation->name,c1.derivation_name(),
+ c2.collation->name,c2.derivation_name(),
+ fname);
+}
+
Item_bool_func2* Item_bool_func2::eq_creator(Item *a, Item *b)
{
return new Item_func_eq(a, b);
@@ -87,52 +122,17 @@ static bool convert_constant_item(Field *field, Item **item)
return 0;
}
-bool Item_bool_func2::set_cmp_charset(CHARSET_INFO *cs1, enum coercion co1,
- CHARSET_INFO *cs2, enum coercion co2)
-{
- if ((cs1 == &my_charset_bin) || (cs2 == &my_charset_bin))
- {
- cmp_charset= &my_charset_bin;
- return 0;
- }
-
- if ((co1 == COER_NOCOLL) || (co2 == COER_NOCOLL))
- return 1;
-
- if (!my_charset_same(cs1,cs2))
- return 1;
-
- if (co1 < co2)
- cmp_charset= cs1;
- else if (co2 < co1)
- cmp_charset= cs2;
- else // co1==co2
- {
- if (cs1 == cs2)
- cmp_charset= cs1;
- else
- {
- if (co1 == COER_COERCIBLE)
- {
- CHARSET_INFO *c;
- if ((c= get_charset_by_csname(cs1->csname, MY_CS_PRIMARY, MYF(0))))
- {
- cmp_charset= c;
- return 0;
- }
- }
- return 1;
- }
- }
- return 0;
-}
-
-bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables,
- Item ** ref)
+void Item_bool_func2::fix_length_and_dec()
{
- if (Item_int_func::fix_fields(thd, tables, ref))
- return 1;
+ max_length= 1; // Function returns 0 or 1
+
+ /*
+ As some compare functions are generated after sql_yacc,
+ we have to check for out of memory conditions here
+ */
+ if (!args[0] || !args[1])
+ return;
/*
We allow to convert to Unicode character sets in some cases.
@@ -151,13 +151,13 @@ bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables,
uint strong= 0;
uint weak= 0;
- if ((args[0]->coercibility < args[1]->coercibility) &&
+ if ((args[0]->derivation() < args[1]->derivation()) &&
!my_charset_same(args[0]->charset(), args[1]->charset()) &&
(args[0]->charset()->state & MY_CS_UNICODE))
{
weak= 1;
}
- else if ((args[1]->coercibility < args[0]->coercibility) &&
+ else if ((args[1]->derivation() < args[0]->derivation()) &&
!my_charset_same(args[0]->charset(), args[1]->charset()) &&
(args[1]->charset()->state & MY_CS_UNICODE))
{
@@ -174,44 +174,18 @@ bool Item_bool_func2::fix_fields(THD *thd, struct st_table_list *tables,
cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(),
args[strong]->charset());
conv= new Item_string(cstr.ptr(),cstr.length(),cstr.charset(),
- args[weak]->coercibility);
+ args[weak]->derivation());
((Item_string*)conv)->str_value.copy();
}
else
{
conv= new Item_func_conv_charset(args[weak],args[strong]->charset());
- conv->coercibility= args[weak]->coercibility;
+ conv->collation.set(args[weak]->derivation());
}
args[weak]= conv ? conv : args[weak];
- set_cmp_charset(args[0]->charset(), args[0]->coercibility,
- args[1]->charset(), args[1]->coercibility);
}
}
- if (!cmp_charset)
- {
- /* set_cmp_charset() failed */
- my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0),
- args[0]->charset()->name,coercion_name(args[0]->coercibility),
- args[1]->charset()->name,coercion_name(args[1]->coercibility),
- func_name());
- return 1;
- }
- return 0;
-}
-
-
-void Item_bool_func2::fix_length_and_dec()
-{
- max_length= 1; // Function returns 0 or 1
-
- /*
- As some compare functions are generated after sql_yacc,
- we have to check for out of memory conditions here
- */
- if (!args[0] || !args[1])
- return;
-
-
+
// Make a special case of compare with fields to get nicer DATE comparisons
if (args[0]->type() == FIELD_ITEM)
{
@@ -222,7 +196,6 @@ void Item_bool_func2::fix_length_and_dec()
{
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
INT_RESULT); // Works for all types.
- cmp_charset= &my_charset_bin; // For test in fix_fields
return;
}
}
@@ -236,18 +209,11 @@ void Item_bool_func2::fix_length_and_dec()
{
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
INT_RESULT); // Works for all types.
- cmp_charset= &my_charset_bin; // For test in fix_fields
return;
}
}
}
set_cmp_func();
- /*
- We must set cmp_charset here as we may be called from for an automatic
- generated item, like in natural join
- */
- set_cmp_charset(args[0]->charset(), args[0]->coercibility,
- args[1]->charset(), args[1]->coercibility);
}
@@ -277,6 +243,18 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
}
}
+ else if (type == STRING_RESULT)
+ {
+ /*
+ We must set cmp_charset here as we may be called from for an automatic
+ generated item, like in natural join
+ */
+ if (cmp_collation.set((*a)->collation, (*b)->collation))
+ {
+ my_coll_agg_error((*a)->collation, (*b)->collation, owner->func_name());
+ return 1;
+ }
+ }
return 0;
}
@@ -289,7 +267,7 @@ int Arg_comparator::compare_string()
if ((res2= (*b)->val_str(&owner->tmp_value2)))
{
owner->null_value= 0;
- return sortcmp(res1,res2,owner->cmp_charset);
+ return sortcmp(res1,res2,cmp_collation.collation);
}
}
owner->null_value= 1;
@@ -303,7 +281,7 @@ int Arg_comparator::compare_e_string()
res2= (*b)->val_str(&owner->tmp_value2);
if (!res1 || !res2)
return test(res1 == res2);
- return test(sortcmp(res1, res2, owner->cmp_charset) == 0);
+ return test(sortcmp(res1, res2, cmp_collation.collation) == 0);
}
@@ -405,12 +383,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
return 1;
if (args[0]->maybe_null)
maybe_null=1;
- /*
- TODO: Check if following is right
- (set_charset set type of result, not how compare should be used)
- */
- if (args[0]->binary())
- set_charset(&my_charset_bin);
+
with_sum_func= args[0]->with_sum_func;
used_tables_cache= args[0]->used_tables();
const_item_cache= args[0]->const_item();
@@ -532,7 +505,7 @@ longlong Item_func_strcmp::val_int()
null_value=1;
return 0;
}
- int value= sortcmp(a,b,cmp_charset);
+ int value= sortcmp(a,b,cmp.cmp_collation.collation);
null_value=0;
return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
}
@@ -609,14 +582,10 @@ void Item_func_between::fix_length_and_dec()
*/
if (!args[0] || !args[1] || !args[2])
return;
- cmp_type=item_cmp_type(args[0]->result_type(),
- item_cmp_type(args[1]->result_type(),
- args[2]->result_type()));
- /* QQ: COERCIBILITY */
- if (args[0]->binary() | args[1]->binary() | args[2]->binary())
- cmp_charset= &my_charset_bin;
- else
- cmp_charset= args[0]->charset();
+ agg_cmp_type(&cmp_type, args, 3);
+ if (cmp_type == STRING_RESULT &&
+ agg_arg_collations_for_comparison(cmp_collation, args, 3))
+ return;
/*
Make a special case of compare with date/time and longlong fields.
@@ -648,17 +617,17 @@ longlong Item_func_between::val_int()
a=args[1]->val_str(&value1);
b=args[2]->val_str(&value2);
if (!args[1]->null_value && !args[2]->null_value)
- return (sortcmp(value,a,cmp_charset) >= 0 &&
- sortcmp(value,b,cmp_charset) <= 0) ? 1 : 0;
+ return (sortcmp(value,a,cmp_collation.collation) >= 0 &&
+ sortcmp(value,b,cmp_collation.collation) <= 0) ? 1 : 0;
if (args[1]->null_value && args[2]->null_value)
null_value=1;
else if (args[1]->null_value)
{
- null_value= sortcmp(value,b,cmp_charset) <= 0; // not null if false range.
+ null_value= sortcmp(value,b,cmp_collation.collation) <= 0; // not null if false range.
}
else
{
- null_value= sortcmp(value,a,cmp_charset) >= 0; // not null if false range.
+ null_value= sortcmp(value,a,cmp_collation.collation) >= 0; // not null if false range.
}
}
else if (cmp_type == INT_RESULT)
@@ -704,32 +673,17 @@ longlong Item_func_between::val_int()
return 0;
}
-static Item_result item_store_type(Item_result a,Item_result b)
-{
- if (a == STRING_RESULT || b == STRING_RESULT)
- return STRING_RESULT;
- else if (a == REAL_RESULT || b == REAL_RESULT)
- return REAL_RESULT;
- else
- return INT_RESULT;
-}
-
void
Item_func_ifnull::fix_length_and_dec()
{
maybe_null=args[1]->maybe_null;
max_length=max(args[0]->max_length,args[1]->max_length);
decimals=max(args[0]->decimals,args[1]->decimals);
- if ((cached_result_type=item_store_type(args[0]->result_type(),
- args[1]->result_type())) !=
- REAL_RESULT)
+ agg_result_type(&cached_result_type, args, 2);
+ if (cached_result_type == STRING_RESULT)
+ agg_arg_collations(collation, args, arg_count);
+ else if (cached_result_type != REAL_RESULT)
decimals= 0;
- if (set_charset(args[0]->charset(),args[0]->coercibility,
- args[1]->charset(),args[1]->coercibility))
- my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0),
- args[0]->charset()->name,coercion_name(args[0]->coercibility),
- args[1]->charset()->name,coercion_name(args[1]->coercibility),
- func_name());
}
@@ -802,26 +756,18 @@ Item_func_if::fix_length_and_dec()
cached_result_type= arg1_type;
set_charset(args[1]->charset());
}
- else if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT)
+ else
{
- cached_result_type = STRING_RESULT;
- if (set_charset(args[1]->charset(), args[1]->coercibility,
- args[2]->charset(), args[2]->coercibility))
+ agg_result_type(&cached_result_type, args+1, 2);
+ if (cached_result_type == STRING_RESULT)
{
- my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0),
- args[0]->charset()->name,coercion_name(args[0]->coercibility),
- args[1]->charset()->name,coercion_name(args[1]->coercibility),
- func_name());
+ if (agg_arg_collations(collation, args+1, 2))
return;
}
- }
- else
- {
- set_charset(&my_charset_bin); // Number
- if (arg1_type == REAL_RESULT || arg2_type == REAL_RESULT)
- cached_result_type = REAL_RESULT;
else
- cached_result_type=arg1_type; // Should be INT_RESULT
+ {
+ set_charset(&my_charset_bin); // Number
+ }
}
}
@@ -865,7 +811,7 @@ Item_func_nullif::fix_length_and_dec()
{
max_length=args[0]->max_length;
decimals=args[0]->decimals;
- cached_result_type=args[0]->result_type();
+ agg_result_type(&cached_result_type, args, 2);
}
}
@@ -928,64 +874,60 @@ Item *Item_func_case::find_item(String *str)
String *first_expr_str,*tmp;
longlong first_expr_int;
double first_expr_real;
- bool int_used, real_used,str_used;
- int_used=real_used=str_used=0;
-
+
/* These will be initialized later */
LINT_INIT(first_expr_str);
LINT_INIT(first_expr_int);
LINT_INIT(first_expr_real);
+ if (first_expr_num != -1)
+ {
+ switch (cmp_type)
+ {
+ case STRING_RESULT:
+ // We can't use 'str' here as this may be overwritten
+ if (!(first_expr_str= args[first_expr_num]->val_str(&str_value)))
+ return else_expr_num != -1 ? args[else_expr_num] : 0; // Impossible
+ break;
+ case INT_RESULT:
+ first_expr_int= args[first_expr_num]->val_int();
+ if (args[first_expr_num]->null_value)
+ return else_expr_num != -1 ? args[else_expr_num] : 0;
+ break;
+ case REAL_RESULT:
+ first_expr_real= args[first_expr_num]->val();
+ if (args[first_expr_num]->null_value)
+ return else_expr_num != -1 ? args[else_expr_num] : 0;
+ break;
+ case ROW_RESULT:
+ default:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ break;
+ }
+ }
+
// Compare every WHEN argument with it and return the first match
- for (uint i=0 ; i < arg_count ; i+=2)
+ for (uint i=0 ; i < ncases ; i+=2)
{
- if (!first_expr)
+ if (first_expr_num == -1)
{
- // No expression between CASE and first WHEN
+ // No expression between CASE and the first WHEN
if (args[i]->val_int())
return args[i+1];
continue;
}
- switch (args[i]->result_type()) {
+ switch (cmp_type) {
case STRING_RESULT:
- if (!str_used)
- {
- str_used=1;
- // We can't use 'str' here as this may be overwritten
- if (!(first_expr_str= first_expr->val_str(&str_value)))
- return else_expr; // Impossible
- }
if ((tmp=args[i]->val_str(str))) // If not null
- {
- /* QQ: COERCIBILITY */
- if (first_expr_is_binary || args[i]->binary())
- {
- if (sortcmp(tmp,first_expr_str,&my_charset_bin)==0)
- return args[i+1];
- }
- else if (sortcmp(tmp,first_expr_str,tmp->charset())==0)
+ if (sortcmp(tmp,first_expr_str,cmp_collation.collation)==0)
return args[i+1];
- }
break;
case INT_RESULT:
- if (!int_used)
- {
- int_used=1;
- first_expr_int= first_expr->val_int();
- if (first_expr->null_value)
- return else_expr;
- }
if (args[i]->val_int()==first_expr_int && !args[i]->null_value)
return args[i+1];
break;
case REAL_RESULT:
- if (!real_used)
- {
- real_used=1;
- first_expr_real= first_expr->val();
- if (first_expr->null_value)
- return else_expr;
- }
if (args[i]->val()==first_expr_real && !args[i]->null_value)
return args[i+1];
break;
@@ -997,7 +939,7 @@ Item *Item_func_case::find_item(String *str)
}
}
// No, WHEN clauses all missed, return ELSE expression
- return else_expr;
+ return else_expr_num != -1 ? args[else_expr_num] : 0;
}
@@ -1053,104 +995,57 @@ double Item_func_case::val()
return res;
}
-
-bool
-Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
-{
- if (first_expr && (first_expr->fix_fields(thd, tables, &first_expr) ||
- first_expr->check_cols(1)) ||
- else_expr && (else_expr->fix_fields(thd, tables, &else_expr) ||
- else_expr->check_cols(1)))
- return 1;
- if (Item_func::fix_fields(thd, tables, ref))
- return 1;
- if (first_expr)
- {
- used_tables_cache|=(first_expr)->used_tables();
- const_item_cache&= (first_expr)->const_item();
- with_sum_func= with_sum_func || (first_expr)->with_sum_func;
- first_expr_is_binary= first_expr->binary();
- }
- if (else_expr)
- {
- used_tables_cache|=(else_expr)->used_tables();
- const_item_cache&= (else_expr)->const_item();
- with_sum_func= with_sum_func || (else_expr)->with_sum_func;
- }
- if (!else_expr || else_expr->maybe_null)
- maybe_null=1; // The result may be NULL
- return 0;
-}
-
-
-void Item_func_case::split_sum_func(Item **ref_pointer_array,
- List<Item> &fields)
-{
- if (first_expr)
- {
- if (first_expr->with_sum_func && first_expr->type() != SUM_FUNC_ITEM)
- first_expr->split_sum_func(ref_pointer_array, fields);
- else if (first_expr->used_tables() || first_expr->type() == SUM_FUNC_ITEM)
- {
- uint el= fields.elements;
- fields.push_front(first_expr);
- ref_pointer_array[el]= first_expr;
- first_expr= new Item_ref(ref_pointer_array + el, 0, first_expr->name);
- }
- }
- if (else_expr)
- {
- if (else_expr->with_sum_func && else_expr->type() != SUM_FUNC_ITEM)
- else_expr->split_sum_func(ref_pointer_array, fields);
- else if (else_expr->used_tables() || else_expr->type() == SUM_FUNC_ITEM)
- {
- uint el= fields.elements;
- fields.push_front(else_expr);
- ref_pointer_array[el]= else_expr;
- else_expr= new Item_ref(ref_pointer_array + el, 0, else_expr->name);
- }
- }
- Item_func::split_sum_func(ref_pointer_array, fields);
-}
-
-
-void Item_func_case::set_outer_resolving()
-{
- first_expr->set_outer_resolving();
- else_expr->set_outer_resolving();
- Item_func::set_outer_resolving();
-}
-
-void Item_func_case::update_used_tables()
-{
- Item_func::update_used_tables();
- if (first_expr)
- {
- used_tables_cache|=(first_expr)->used_tables();
- const_item_cache&= (first_expr)->const_item();
- }
- if (else_expr)
- {
- used_tables_cache|=(else_expr)->used_tables();
- const_item_cache&= (else_expr)->const_item();
- }
-}
-
-
void Item_func_case::fix_length_and_dec()
{
+ Item **agg;
+ uint nagg;
+
+ if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1))))
+ return;
+
+ // Aggregate all THEN and ELSE expression types
+ // and collations when string result
+
+ for (nagg= 0 ; nagg < ncases/2 ; nagg++)
+ agg[nagg]= args[nagg*2+1];
+
+ if (else_expr_num != -1)
+ agg[nagg++]= args[else_expr_num];
+
+ agg_result_type(&cached_result_type, agg, nagg);
+ if ((cached_result_type == STRING_RESULT) &&
+ agg_arg_collations(collation, agg, nagg))
+ return;
+
+
+ // Aggregate first expression and all THEN expression types
+ // and collations when string comparison
+ if (first_expr_num != -1)
+ {
+ agg[0]= args[first_expr_num];
+ for (nagg= 0; nagg < ncases/2 ; nagg++)
+ agg[nagg+1]= args[nagg*2];
+ nagg++;
+ agg_cmp_type(&cmp_type, agg, nagg);
+ if ((cmp_type == STRING_RESULT) &&
+ agg_arg_collations_for_comparison(cmp_collation, agg, nagg))
+ return;
+ }
+
+ if (!else_expr_num != -1 || args[else_expr_num]->maybe_null)
+ maybe_null=1;
+
max_length=0;
decimals=0;
- cached_result_type = args[1]->result_type();
- for (uint i=0 ; i < arg_count ; i+=2)
+ for (uint i=0 ; i < ncases ; i+=2)
{
set_if_bigger(max_length,args[i+1]->max_length);
set_if_bigger(decimals,args[i+1]->decimals);
}
- if (else_expr != NULL)
+ if (else_expr_num != -1)
{
- set_if_bigger(max_length,else_expr->max_length);
- set_if_bigger(decimals,else_expr->decimals);
+ set_if_bigger(max_length,args[else_expr_num]->max_length);
+ set_if_bigger(decimals,args[else_expr_num]->decimals);
}
}
@@ -1209,29 +1104,33 @@ void Item_func_coalesce::fix_length_and_dec()
{
max_length= 0;
decimals= 0;
- cached_result_type = args[0]->result_type();
+ agg_result_type(&cached_result_type, args, arg_count);
for (uint i=0 ; i < arg_count ; i++)
{
set_if_bigger(max_length,args[i]->max_length);
set_if_bigger(decimals,args[i]->decimals);
}
+ if (cached_result_type == STRING_RESULT)
+ agg_arg_collations(collation, args, arg_count);
+ else if (cached_result_type != REAL_RESULT)
+ decimals= 0;
}
/****************************************************************************
Classes and function for the IN operator
****************************************************************************/
-static int cmp_longlong(longlong *a,longlong *b)
+static int cmp_longlong(void *cmp_arg, longlong *a,longlong *b)
{
return *a < *b ? -1 : *a == *b ? 0 : 1;
}
-static int cmp_double(double *a,double *b)
+static int cmp_double(void *cmp_arg, double *a,double *b)
{
return *a < *b ? -1 : *a == *b ? 0 : 1;
}
-static int cmp_row(cmp_item_row* a, cmp_item_row* b)
+static int cmp_row(void *cmp_arg, cmp_item_row* a, cmp_item_row* b)
{
return a->compare(b);
}
@@ -1248,18 +1147,18 @@ int in_vector::find(Item *item)
{
uint mid=(start+end+1)/2;
int res;
- if ((res=(*compare)(base+mid*size,result)) == 0)
+ if ((res=(*compare)(collation, base+mid*size, result)) == 0)
return 1;
if (res < 0)
start=mid;
else
end=mid-1;
}
- return (int) ((*compare)(base+start*size,result) == 0);
+ return (int) ((*compare)(collation, base+start*size, result) == 0);
}
-in_string::in_string(uint elements,qsort_cmp cmp_func)
- :in_vector(elements, sizeof(String), cmp_func),
+in_string::in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs)
+ :in_vector(elements, sizeof(String), cmp_func, cs),
tmp(buff, sizeof(buff), &my_charset_bin)
{}
@@ -1298,7 +1197,7 @@ in_row::in_row(uint elements, Item * item)
{
base= (char*) new cmp_item_row[count= elements];
size= sizeof(cmp_item_row);
- compare= (qsort_cmp) cmp_row;
+ compare= (qsort2_cmp) cmp_row;
tmp.store_value(item);
}
@@ -1323,7 +1222,7 @@ void in_row::set(uint pos, Item *item)
}
in_longlong::in_longlong(uint elements)
- :in_vector(elements,sizeof(longlong),(qsort_cmp) cmp_longlong)
+ :in_vector(elements,sizeof(longlong),(qsort2_cmp) cmp_longlong, 0)
{}
void in_longlong::set(uint pos,Item *item)
@@ -1340,7 +1239,7 @@ byte *in_longlong::get_value(Item *item)
}
in_double::in_double(uint elements)
- :in_vector(elements,sizeof(double),(qsort_cmp) cmp_double)
+ :in_vector(elements,sizeof(double),(qsort2_cmp) cmp_double, 0)
{}
void in_double::set(uint pos,Item *item)
@@ -1479,7 +1378,7 @@ int cmp_item_row::compare(cmp_item *c)
bool Item_func_in::nulls_in_row()
{
Item **arg,**arg_end;
- for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
+ for (arg= args+1, arg_end= args+arg_count; arg != arg_end ; arg++)
{
if ((*arg)->null_inside())
return 1;
@@ -1487,17 +1386,8 @@ bool Item_func_in::nulls_in_row()
return 0;
}
-static int srtcmp_in(const String *x,const String *y)
+static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
{
- CHARSET_INFO *cs= x->charset();
- return cs->coll->strnncollsp(cs,
- (unsigned char *) x->ptr(),x->length(),
- (unsigned char *) y->ptr(),y->length());
-}
-
-static int bincmp_in(const String *x,const String *y)
-{
- CHARSET_INFO *cs= &my_charset_bin;
return cs->coll->strnncollsp(cs,
(unsigned char *) x->ptr(),x->length(),
(unsigned char *) y->ptr(),y->length());
@@ -1505,34 +1395,44 @@ static int bincmp_in(const String *x,const String *y)
void Item_func_in::fix_length_and_dec()
{
+ Item **arg, **arg_end;
+ uint const_itm= 1;
+
+ agg_cmp_type(&cmp_type, args, arg_count);
+ if ((cmp_type == STRING_RESULT) &&
+ (agg_arg_collations_for_comparison(cmp_collation, args, arg_count)))
+ return;
+
+ for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
+ const_itm&= arg[0]->const_item();
+
/*
Row item with NULLs inside can return NULL or FALSE =>
they can't be processed as static
*/
- if (const_item() && !nulls_in_row())
+ if (const_itm && !nulls_in_row())
{
- switch (item->result_type()) {
+ switch (cmp_type) {
case STRING_RESULT:
- if (item->binary())
- array=new in_string(arg_count,(qsort_cmp) srtcmp_in);
- else
- array=new in_string(arg_count,(qsort_cmp) bincmp_in);
+ uint i;
+ array=new in_string(arg_count-1,(qsort2_cmp) srtcmp_in,
+ cmp_collation.collation);
break;
case INT_RESULT:
- array= new in_longlong(arg_count);
+ array= new in_longlong(arg_count-1);
break;
case REAL_RESULT:
- array= new in_double(arg_count);
+ array= new in_double(arg_count-1);
break;
case ROW_RESULT:
- array= new in_row(arg_count, item);
+ array= new in_row(arg_count-1, args[0]);
break;
default:
DBUG_ASSERT(0);
return;
}
uint j=0;
- for (uint i=0 ; i < arg_count ; i++)
+ for (uint i=1 ; i < arg_count ; i++)
{
array->set(j,args[i]);
if (!args[i]->null_value) // Skip NULL values
@@ -1545,19 +1445,19 @@ void Item_func_in::fix_length_and_dec()
}
else
{
- in_item= cmp_item::get_comparator(item);
+ in_item= cmp_item::get_comparator(args[0]);
+ if (cmp_type == STRING_RESULT)
+ in_item->cmp_charset= cmp_collation.collation;
}
- maybe_null= item->maybe_null;
+ maybe_null= args[0]->maybe_null;
max_length= 1;
- used_tables_cache|=item->used_tables();
- const_item_cache&=item->const_item();
+ const_item_cache&=args[0]->const_item();
}
void Item_func_in::print(String *str)
{
str->append('(');
- item->print(str);
Item_func::print(str);
str->append(')');
}
@@ -1567,15 +1467,15 @@ longlong Item_func_in::val_int()
{
if (array)
{
- int tmp=array->find(item);
- null_value=item->null_value || (!tmp && have_null);
+ int tmp=array->find(args[0]);
+ null_value=args[0]->null_value || (!tmp && have_null);
return tmp;
}
- in_item->store_value(item);
- if ((null_value=item->null_value))
+ in_item->store_value(args[0]);
+ if ((null_value=args[0]->null_value))
return 0;
have_null= 0;
- for (uint i=0 ; i < arg_count ; i++)
+ for (uint i=1 ; i < arg_count ; i++)
{
if (!in_item->cmp(args[i]) && !args[i]->null_value)
return 1; // Would maybe be nice with i ?
@@ -1586,29 +1486,6 @@ longlong Item_func_in::val_int()
}
-void Item_func_in::update_used_tables()
-{
- Item_func::update_used_tables();
- item->update_used_tables();
- used_tables_cache|=item->used_tables();
- const_item_cache&=item->const_item();
-}
-
-void Item_func_in::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
-{
- if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
- item->split_sum_func(ref_pointer_array, fields);
- else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
- {
- uint el= fields.elements;
- fields.push_front(item);
- ref_pointer_array[el]= item;
- item= new Item_ref(ref_pointer_array + el, 0, item->name);
- }
- Item_func::split_sum_func(ref_pointer_array, fields);
-}
-
-
longlong Item_func_bit_or::val_int()
{
ulonglong arg1= (ulonglong) args[0]->val_int();
@@ -1683,7 +1560,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
maybe_null=1;
}
if (thd)
- thd->cond_count+=list.elements;
+ thd->lex.current_select->cond_count+=list.elements;
fix_length_and_dec();
fixed= 1;
return 0;
@@ -1924,7 +1801,7 @@ longlong Item_func_like::val_int()
null_value=0;
if (canDoTurboBM)
return turboBM_matches(res->ptr(), res->length()) ? 1 : 0;
- return my_wildcmp(cmp_charset,
+ return my_wildcmp(cmp.cmp_collation.collation,
res->ptr(),res->ptr()+res->length(),
res2->ptr(),res2->ptr()+res2->length(),
escape,wild_one,wild_many) ? 0 : 1;
@@ -2013,7 +1890,9 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
max_length= 1;
decimals= 0;
- binary_cmp= (args[0]->binary() || args[1]->binary());
+
+ if (agg_arg_collations(cmp_collation, args, 2))
+ return 1;
used_tables_cache=args[0]->used_tables() | args[1]->used_tables();
const_item_cache=args[0]->const_item() && args[1]->const_item();
@@ -2029,9 +1908,10 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
int error;
if ((error=regcomp(&preg,res->c_ptr(),
- binary_cmp ? REG_EXTENDED | REG_NOSUB :
+ (cmp_collation.collation->state & MY_CS_BINSORT) ?
+ REG_EXTENDED | REG_NOSUB :
REG_EXTENDED | REG_NOSUB | REG_ICASE,
- res->charset())))
+ cmp_collation.collation)))
{
(void) regerror(error,&preg,buff,sizeof(buff));
my_printf_error(ER_REGEXP_ERROR,ER(ER_REGEXP_ERROR),MYF(0),buff);
@@ -2078,10 +1958,10 @@ longlong Item_func_regex::val_int()
regex_compiled=0;
}
if (regcomp(&preg,res2->c_ptr(),
- binary_cmp ? REG_EXTENDED | REG_NOSUB :
+ (cmp_collation.collation->state & MY_CS_BINSORT) ?
+ REG_EXTENDED | REG_NOSUB :
REG_EXTENDED | REG_NOSUB | REG_ICASE,
- res->charset()))
-
+ cmp_collation.collation))
{
null_value=1;
return 0;
@@ -2128,7 +2008,7 @@ void Item_func_like::turboBM_compute_suffixes(int *suff)
*splm1 = pattern_len;
- if (cmp_charset == &my_charset_bin)
+ if (cmp.cmp_collation.collation == &my_charset_bin)
{
int i;
for (i = pattern_len - 2; i >= 0; i--)
@@ -2231,7 +2111,7 @@ void Item_func_like::turboBM_compute_bad_character_shifts()
for (i = bmBc; i < end; i++)
*i = pattern_len;
- if (cmp_charset == &my_charset_bin)
+ if (cmp.cmp_collation.collation == &my_charset_bin)
{
for (j = 0; j < plm1; j++)
bmBc[(uint) (uchar) pattern[j]] = plm1 - j;
@@ -2262,7 +2142,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
const int tlmpl= text_len - pattern_len;
/* Searching */
- if (cmp_charset == &my_charset_bin)
+ if (cmp.cmp_collation.collation == &my_charset_bin)
{
while (j <= tlmpl)
{
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 549839b4f96..25cc97d60bf 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -35,6 +35,8 @@ class Arg_comparator: public Sql_alloc
Arg_comparator *comparators; // used only for compare_row()
public:
+ DTCollation cmp_collation;
+
Arg_comparator() {};
Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {};
@@ -112,25 +114,20 @@ class Item_bool_func2 :public Item_int_func
protected:
Arg_comparator cmp;
String tmp_value1,tmp_value2;
- CHARSET_INFO *cmp_charset;
public:
Item_bool_func2(Item *a,Item *b):
- Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1), cmp_charset(0) {}
- bool fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref);
+ Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
void fix_length_and_dec();
void set_cmp_func()
{
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1);
}
- bool set_cmp_charset(CHARSET_INFO *cs1, enum coercion co1,
- CHARSET_INFO *cs2, enum coercion co2);
optimize_type select_optimize() const { return OPTIMIZE_OP; }
virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; }
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
void print(String *str) { Item_func::print_op(str); }
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
- virtual bool binary() const { return test(cmp_charset->state & MY_CS_BINSORT); }
static Item_bool_func2* eq_creator(Item *a, Item *b);
static Item_bool_func2* ne_creator(Item *a, Item *b);
@@ -245,7 +242,7 @@ public:
class Item_func_between :public Item_int_func
{
- CHARSET_INFO *cmp_charset;
+ DTCollation cmp_collation;
public:
Item_result cmp_type;
String value0,value1,value2;
@@ -351,27 +348,38 @@ public:
class Item_func_case :public Item_func
{
- Item * first_expr, *else_expr;
+ int first_expr_num, else_expr_num;
enum Item_result cached_result_type;
String tmp_value;
- bool first_expr_is_binary;
+ uint ncases;
+ Item_result cmp_type;
+ DTCollation cmp_collation;
public:
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
- :Item_func(list), first_expr(first_expr_arg), else_expr(else_expr_arg),
+ :Item_func(), first_expr_num(-1), else_expr_num(-1),
cached_result_type(INT_RESULT)
- {}
+ {
+ ncases= list.elements;
+ if (first_expr_arg)
+ {
+ first_expr_num= list.elements;
+ list.push_back(first_expr_arg);
+ }
+ if (else_expr_arg)
+ {
+ else_expr_num= list.elements;
+ list.push_back(else_expr_arg);
+ }
+ set_arguments(list);
+ }
double val();
longlong val_int();
String *val_str(String *);
void fix_length_and_dec();
- void update_used_tables();
enum Item_result result_type () const { return cached_result_type; }
const char *func_name() const { return "case"; }
void print(String *str);
- bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
- void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
Item *find_item(String *str);
- void set_outer_resolving();
};
@@ -382,21 +390,23 @@ class in_vector :public Sql_alloc
protected:
char *base;
uint size;
- qsort_cmp compare;
+ qsort2_cmp compare;
+ CHARSET_INFO *collation;
uint count;
public:
uint used_count;
in_vector() {}
- in_vector(uint elements,uint element_length,qsort_cmp cmp_func)
+ in_vector(uint elements,uint element_length,qsort2_cmp cmp_func,
+ CHARSET_INFO *cmp_coll)
:base((char*) sql_calloc(elements*element_length)),
- size(element_length), compare(cmp_func), count(elements),
- used_count(elements) {}
+ size(element_length), compare(cmp_func), collation(cmp_coll),
+ count(elements), used_count(elements) {}
virtual ~in_vector() {}
virtual void set(uint pos,Item *item)=0;
virtual byte *get_value(Item *item)=0;
void sort()
{
- qsort(base,used_count,size,compare);
+ qsort2(base,used_count,size,compare,collation);
}
int find(Item *item);
};
@@ -406,7 +416,7 @@ class in_string :public in_vector
char buff[80];
String tmp;
public:
- in_string(uint elements,qsort_cmp cmp_func);
+ in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs);
~in_string();
void set(uint pos,Item *item);
byte *get_value(Item *item);
@@ -601,41 +611,27 @@ public:
class Item_func_in :public Item_int_func
{
- Item *item;
+ Item_result cmp_type;
in_vector *array;
cmp_item *in_item;
bool have_null;
+ DTCollation cmp_collation;
public:
- Item_func_in(Item *a,List<Item> &list)
- :Item_int_func(list), item(a), array(0), in_item(0), have_null(0)
+ Item_func_in(List<Item> &list)
+ :Item_int_func(list), array(0), in_item(0), have_null(0)
{
- allowed_arg_cols= item->cols();
+ allowed_arg_cols= args[0]->cols();
}
longlong val_int();
- bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
- {
- // We do not check item->cols(), because allowed_arg_cols assigned from it
- bool res=(item->fix_fields(thd, tlist, &item) ||
- Item_func::fix_fields(thd, tlist, ref));
- with_sum_func= with_sum_func || item->with_sum_func;
- return res;
- }
void fix_length_and_dec();
- ~Item_func_in() { delete item; delete array; delete in_item; }
+ ~Item_func_in() { delete array; delete in_item; }
optimize_type select_optimize() const
{ return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; }
- Item *key_item() const { return item; }
+ Item *key_item() const { return args[0]; }
void print(String *str);
enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return " IN "; }
- void update_used_tables();
- void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
bool nulls_in_row();
- void set_outer_resolving()
- {
- item->set_outer_resolving();
- Item_int_func::set_outer_resolving();
- }
};
/* Functions used by where clause */
@@ -747,7 +743,7 @@ class Item_func_regex :public Item_bool_func
bool regex_compiled;
bool regex_is_const;
String prev_regexp;
- bool binary_cmp;
+ DTCollation cmp_collation;
public:
Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
regex_compiled(0),regex_is_const(0) {}
diff --git a/sql/item_create.cc b/sql/item_create.cc
index eb442424ca8..eaa27c1009d 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -450,7 +450,7 @@ Item *create_func_version(void)
{
return new Item_string(NullS,server_version,
(uint) strlen(server_version),
- system_charset_info, Item::COER_IMPLICIT);
+ system_charset_info, DERIVATION_IMPLICIT);
}
Item *create_func_weekday(Item* a)
@@ -506,9 +506,9 @@ Item *create_func_quote(Item* a)
return new Item_func_quote(a);
}
-Item *create_func_as_text(Item *a)
+Item *create_func_as_wkt(Item *a)
{
- return new Item_func_as_text(a);
+ return new Item_func_as_wkt(a);
}
Item *create_func_as_wkb(Item *a)
@@ -691,3 +691,38 @@ Item *create_func_uncompressed_length(Item* a)
#endif
+Item *create_func_datediff(Item *a, Item *b)
+{
+ return new Item_func_minus(new Item_func_to_days(a),
+ new Item_func_to_days(b));
+}
+
+Item *create_func_weekofyear(Item *a)
+{
+ return new Item_func_week(a, new Item_int((char*) "0", 3, 1));
+}
+
+Item *create_func_makedate(Item* a,Item* b)
+{
+ return new Item_func_makedate(a, b);
+}
+
+Item *create_func_addtime(Item* a,Item* b)
+{
+ return new Item_func_add_time(a, b, 0, 0);
+}
+
+Item *create_func_subtime(Item* a,Item* b)
+{
+ return new Item_func_add_time(a, b, 0, 1);
+}
+
+Item *create_func_timediff(Item* a,Item* b)
+{
+ return new Item_func_timediff(a, b);
+}
+
+Item *create_func_maketime(Item* a,Item* b,Item* c)
+{
+ return new Item_func_maketime(a, b, c);
+}
diff --git a/sql/item_create.h b/sql/item_create.h
index b679c639244..32e452c15dd 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -104,7 +104,7 @@ Item *create_func_is_used_lock(Item* a);
Item *create_func_quote(Item* a);
Item *create_func_geometry_from_text(Item *a);
-Item *create_func_as_text(Item *a);
+Item *create_func_as_wkt(Item *a);
Item *create_func_as_wkb(Item *a);
Item *create_func_srid(Item *a);
Item *create_func_startpoint(Item *a);
@@ -146,3 +146,10 @@ Item *create_func_compress(Item *a);
Item *create_func_uncompress(Item *a);
Item *create_func_uncompressed_length(Item *a);
+Item *create_func_datediff(Item *a, Item *b);
+Item *create_func_weekofyear(Item *a);
+Item *create_func_makedate(Item* a,Item* b);
+Item *create_func_addtime(Item* a,Item* b);
+Item *create_func_subtime(Item* a,Item* b);
+Item *create_func_timediff(Item* a,Item* b);
+Item *create_func_maketime(Item* a,Item* b,Item* c);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 6482d81f484..ea3c3980a50 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -31,6 +31,69 @@
#include <zlib.h>
#endif
+static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname)
+{
+ my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
+ c1.collation->name,c1.derivation_name(),
+ c2.collation->name,c2.derivation_name(),
+ fname);
+}
+
+static void my_coll_agg_error(DTCollation &c1,
+ DTCollation &c2,
+ DTCollation &c3,
+ const char *fname)
+{
+ my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0),
+ c1.collation->name,c1.derivation_name(),
+ c2.collation->name,c2.derivation_name(),
+ c3.collation->name,c3.derivation_name(),
+ fname);
+}
+
+static void my_coll_agg_error(Item** args, uint ac, const char *fname)
+{
+ if (2 == ac)
+ my_coll_agg_error(args[0]->collation, args[1]->collation, fname);
+ else if (3 == ac)
+ my_coll_agg_error(args[0]->collation,
+ args[1]->collation,
+ args[2]->collation,
+ fname);
+ else
+ my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),fname);
+}
+
+bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint ac)
+{
+ uint i;
+ c.set(av[0]->collation);
+ for (i= 1; i < ac; i++)
+ {
+ if (c.aggregate(av[i]->collation))
+ {
+ my_coll_agg_error(av, ac, func_name());
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
+ Item **av, uint ac)
+{
+ if (agg_arg_collations(c, av, ac))
+ return TRUE;
+
+ if (c.derivation == DERIVATION_NONE)
+ {
+ my_coll_agg_error(av, ac, func_name());
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
/* return TRUE if item is a constant */
bool
@@ -39,10 +102,9 @@ eval_const_cond(COND *cond)
return ((Item_func*) cond)->val_int() ? TRUE : FALSE;
}
-
-Item_func::Item_func(List<Item> &list)
- :allowed_arg_cols(1)
+void Item_func::set_arguments(List<Item> &list)
{
+ allowed_arg_cols= 1;
arg_count=list.elements;
if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
{
@@ -59,6 +121,12 @@ Item_func::Item_func(List<Item> &list)
list.empty(); // Fields are used
}
+Item_func::Item_func(List<Item> &list)
+ :allowed_arg_cols(1)
+{
+ set_arguments(list);
+}
+
/*
Resolve references to table column for a function and it's argument
@@ -858,18 +926,9 @@ void Item_func_min_max::fix_length_and_dec()
if (!args[i]->maybe_null)
maybe_null=0;
cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
- if (i==0)
- set_charset(args[i]->charset(), args[i]->coercibility);
- else if (set_charset(charset(), coercibility,
- args[i]->charset(), args[i]->coercibility))
- {
- my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0),
- charset()->name,coercion_name(coercibility),
- args[i]->charset()->name,coercion_name(args[i]->coercibility),
- func_name());
- break;
- }
}
+ if (cmp_type == STRING_RESULT)
+ agg_arg_collations_for_comparison(collation, args, arg_count);
}
@@ -1038,13 +1097,20 @@ longlong Item_func_coercibility::val_int()
return 0;
}
null_value= 0;
- return (longlong) args[0]->coercibility;
+ return (longlong) args[0]->derivation();
+}
+
+void Item_func_locate::fix_length_and_dec()
+{
+ maybe_null=0; max_length=11;
+ agg_arg_collations_for_comparison(cmp_collation, args, 2);
}
longlong Item_func_locate::val_int()
{
String *a=args[0]->val_str(&value1);
String *b=args[1]->val_str(&value2);
+ bool binary_cmp= (cmp_collation.collation->state & MY_CS_BINSORT) ? 1 : 0;
if (!a || !b)
{
null_value=1;
@@ -1059,7 +1125,7 @@ longlong Item_func_locate::val_int()
{
start=(uint) args[2]->val_int()-1;
#ifdef USE_MB
- if (use_mb(a->charset()))
+ if (use_mb(cmp_collation.collation))
{
start0=start;
if (!binary_cmp)
@@ -1072,7 +1138,7 @@ longlong Item_func_locate::val_int()
if (!b->length()) // Found empty string at start
return (longlong) (start+1);
#ifdef USE_MB
- if (use_mb(a->charset()) && !binary_cmp)
+ if (use_mb(cmp_collation.collation) && !binary_cmp)
{
const char *ptr=a->ptr()+start;
const char *search=b->ptr();
@@ -1091,7 +1157,7 @@ longlong Item_func_locate::val_int()
return (longlong) start0+1;
}
skipp:
- if ((l=my_ismbchar(a->charset(),ptr,strend)))
+ if ((l=my_ismbchar(cmp_collation.collation,ptr,strend)))
ptr+=l;
else ++ptr;
++start0;
@@ -1106,33 +1172,48 @@ longlong Item_func_locate::val_int()
longlong Item_func_field::val_int()
{
- String *field;
- if (!(field=item->val_str(&value)))
- return 0; // -1 if null ?
- for (uint i=0 ; i < arg_count ; i++)
+ if (cmp_type == STRING_RESULT)
{
- String *tmp_value=args[i]->val_str(&tmp);
- if (tmp_value && field->length() == tmp_value->length() &&
- !memcmp(field->ptr(),tmp_value->ptr(),tmp_value->length()))
- return (longlong) (i+1);
+ String *field;
+ if (!(field=args[0]->val_str(&value)))
+ return 0; // -1 if null ?
+ for (uint i=1 ; i < arg_count ; i++)
+ {
+ String *tmp_value=args[i]->val_str(&tmp);
+ if (tmp_value && field->length() == tmp_value->length() &&
+ !sortcmp(field,tmp_value,cmp_collation.collation))
+ return (longlong) (i);
+ }
+ }
+ else if (cmp_type == INT_RESULT)
+ {
+ longlong val= args[0]->val_int();
+ for (uint i=1; i < arg_count ; i++)
+ {
+ if (val == args[i]->val_int())
+ return (longlong) (i);
+ }
+ }
+ else
+ {
+ double val= args[0]->val();
+ for (uint i=1; i < arg_count ; i++)
+ {
+ if (val == args[i]->val())
+ return (longlong) (i);
+ }
}
return 0;
}
-
-void Item_func_field::split_sum_func(Item **ref_pointer_array,
- List<Item> &fields)
+void Item_func_field::fix_length_and_dec()
{
- if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
- item->split_sum_func(ref_pointer_array, fields);
- else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
- {
- uint el= fields.elements;
- fields.push_front(item);
- ref_pointer_array[el]= item;
- item= new Item_ref(ref_pointer_array + el, 0, item->name);
- }
- Item_func::split_sum_func(ref_pointer_array, fields);
+ maybe_null=0; max_length=3;
+ cmp_type= args[0]->result_type();
+ for (uint i=1; i < arg_count ; i++)
+ cmp_type= item_cmp_type(cmp_type, args[i]->result_type());
+ if (cmp_type == STRING_RESULT)
+ agg_arg_collations_for_comparison(cmp_collation, args, arg_count);
}
@@ -1197,6 +1278,7 @@ void Item_func_find_in_set::fix_length_and_dec()
}
}
}
+ agg_arg_collations_for_comparison(cmp_collation, args, 2);
}
static const char separator=',';
@@ -1224,7 +1306,6 @@ longlong Item_func_find_in_set::val_int()
null_value=0;
int diff;
- CHARSET_INFO *charset= find->charset();
if ((diff=buffer->length() - find->length()) >= 0)
{
const char *f_pos=find->ptr();
@@ -1238,7 +1319,8 @@ longlong Item_func_find_in_set::val_int()
const char *pos= f_pos;
while (pos != f_end)
{
- if (my_toupper(charset,*str) != my_toupper(charset,*pos))
+ if (my_toupper(cmp_collation.collation,*str) !=
+ my_toupper(cmp_collation.collation,*pos))
goto not_found;
str++;
pos++;
@@ -1339,7 +1421,18 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
Item *item= *arg;
if (item->fix_fields(thd, tables, arg) || item->check_cols(1))
return 1;
- if (item->binary())
+ /*
+ TODO: We should think about this. It is not always
+ right way just to set an UDF result to return my_charset_bin
+ if one argument has binary sorting order.
+ The result collation should be calculated according to arguments
+ derivations in some cases and should not in other cases.
+ Moreover, some arguments can represent a numeric input
+ which doesn't effect the result character set and collation.
+ There is no a general rule for UDF. Everything depends on
+ the particular user definted function.
+ */
+ if (item->charset()->state & MY_CS_BINSORT)
func->set_charset(&my_charset_bin);
if (item->maybe_null)
func->maybe_null=1;
@@ -2000,7 +2093,7 @@ Item_func_set_user_var::fix_length_and_dec()
void Item_func_set_user_var::update_hash(void *ptr, uint length,
Item_result type,
CHARSET_INFO *cs,
- enum coercion coercibility)
+ Derivation dv)
{
if ((null_value=args[0]->null_value))
{
@@ -2009,8 +2102,7 @@ void Item_func_set_user_var::update_hash(void *ptr, uint length,
my_free(entry->value,MYF(0));
entry->value=0;
entry->length=0;
- entry->var_charset=cs;
- entry->var_coercibility= coercibility;
+ entry->collation.set(cs, dv);
}
else
{
@@ -2041,8 +2133,7 @@ void Item_func_set_user_var::update_hash(void *ptr, uint length,
memcpy(entry->value,ptr,length);
entry->length= length;
entry->type=type;
- entry->var_charset=cs;
- entry->var_coercibility= coercibility;
+ entry->collation.set(cs, dv);
}
return;
@@ -2085,7 +2176,7 @@ Item_func_set_user_var::val()
{
double value=args[0]->val();
update_hash((void*) &value,sizeof(value), REAL_RESULT,
- &my_charset_bin, COER_NOCOLL);
+ &my_charset_bin, DERIVATION_NONE);
return value;
}
@@ -2094,7 +2185,7 @@ Item_func_set_user_var::val_int()
{
longlong value=args[0]->val_int();
update_hash((void*) &value, sizeof(longlong), INT_RESULT,
- &my_charset_bin, COER_NOCOLL);
+ &my_charset_bin, DERIVATION_NONE);
return value;
}
@@ -2103,10 +2194,10 @@ Item_func_set_user_var::val_str(String *str)
{
String *res=args[0]->val_str(str);
if (!res) // Null value
- update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, COER_NOCOLL);
+ update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, DERIVATION_NONE);
else
update_hash((void*) res->ptr(), res->length(), STRING_RESULT,
- res->charset(), args[0]->coercibility);
+ res->charset(), args[0]->derivation());
return res;
}
@@ -2147,7 +2238,7 @@ Item_func_get_user_var::val_str(String *str)
str->set(*(longlong*) entry->value, &my_charset_bin);
break;
case STRING_RESULT:
- if (str->copy(entry->value, entry->length, entry->var_charset))
+ if (str->copy(entry->value, entry->length, entry->collation.collation))
{
null_value=1;
return NULL;
@@ -2236,7 +2327,7 @@ void Item_func_get_user_var::fix_length_and_dec()
ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
user_var_event->user_var_event= var_entry;
user_var_event->type= var_entry->type;
- user_var_event->charset_number= var_entry->var_charset->number;
+ user_var_event->charset_number= var_entry->collation.collation->number;
if (!var_entry->value)
{
/* NULL value*/
@@ -2577,21 +2668,61 @@ longlong Item_func_bit_xor::val_int()
System variables
****************************************************************************/
-Item *get_system_var(enum_var_type var_type, LEX_STRING name)
+/*
+ Return value of an system variable base[.name] as a constant item
+
+ SYNOPSIS
+ get_system_var()
+ thd Thread handler
+ var_type global / session
+ name Name of base or system variable
+ component Component.
+
+ NOTES
+ If component.str = 0 then the variable name is in 'name'
+
+ RETURN
+ 0 error
+ # constant item
+*/
+
+
+Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
+ LEX_STRING component)
{
- if (!my_strcasecmp(system_charset_info, name.str, "VERSION"))
+ if (component.str == 0 &&
+ !my_strcasecmp(system_charset_info, name.str, "VERSION"))
return new Item_string("@@VERSION", server_version,
(uint) strlen(server_version),
system_charset_info);
- THD *thd=current_thd;
Item *item;
sys_var *var;
- char buff[MAX_SYS_VAR_LENGTH+3+8], *pos;
+ char buff[MAX_SYS_VAR_LENGTH*2+4+8], *pos;
+ LEX_STRING *base_name, *component_name;
+
+ if (component.str)
+ {
+ base_name= &component;
+ component_name= &name;
+ }
+ else
+ {
+ base_name= &name;
+ component_name= &component; // Empty string
+ }
- if (!(var= find_sys_var(name.str, name.length)))
+ if (!(var= find_sys_var(base_name->str, base_name->length)))
return 0;
- if (!(item=var->item(thd, var_type)))
+ if (component.str)
+ {
+ if (!var->is_struct())
+ {
+ net_printf(thd, ER_VARIABLE_IS_NOT_STRUCT, base_name->str);
+ return 0;
+ }
+ }
+ if (!(item=var->item(thd, var_type, component_name)))
return 0; // Impossible
thd->lex.uncacheable();
buff[0]='@';
@@ -2601,23 +2732,37 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name)
pos=strmov(pos,"session.");
else if (var_type == OPT_GLOBAL)
pos=strmov(pos,"global.");
- memcpy(pos, var->name, var->name_length+1);
+
+ set_if_smaller(component_name->length, MAX_SYS_VAR_LENGTH);
+ set_if_smaller(base_name->length, MAX_SYS_VAR_LENGTH);
+
+ if (component_name->str)
+ {
+ memcpy(pos, component_name->str, component_name->length);
+ pos+= component_name->length;
+ *pos++= '.';
+ }
+ memcpy(pos, base_name->str, base_name->length);
+ pos+= base_name->length;
+
// set_name() will allocate the name
- item->set_name(buff,(uint) (pos-buff)+var->name_length, system_charset_info);
+ item->set_name(buff,(uint) (pos-buff), system_charset_info);
return item;
}
-Item *get_system_var(enum_var_type var_type, const char *var_name, uint length,
- const char *item_name)
+Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name,
+ uint length, const char *item_name)
{
- THD *thd=current_thd;
Item *item;
sys_var *var;
+ LEX_STRING null_lex_string;
+
+ null_lex_string.str= 0;
var= find_sys_var(var_name, length);
DBUG_ASSERT(var != 0);
- if (!(item=var->item(thd, var_type)))
+ if (!(item=var->item(thd, var_type, &null_lex_string)))
return 0; // Impossible
thd->lex.uncacheable();
item->set_name(item_name, 0, system_charset_info); // Will use original name
diff --git a/sql/item_func.h b/sql/item_func.h
index 8ef2b85de52..7002f885c50 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -115,6 +115,7 @@ public:
virtual const char *func_name() const { return "?"; }
virtual bool const_item() const { return const_item_cache; }
inline Item **arguments() const { return args; }
+ void set_arguments(List<Item> &list);
inline uint argument_count() const { return arg_count; }
inline void remove_arguments() { arg_count=0; }
virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
@@ -135,6 +136,9 @@ public:
Field *tmp_table_field(TABLE *t_arg);
void set_outer_resolving();
Item *get_tmp_table_item(THD *thd);
+
+ bool agg_arg_collations(DTCollation &c, Item **items, uint nitems);
+ bool agg_arg_collations_for_comparison(DTCollation &c, Item **items, uint nitems);
};
@@ -610,53 +614,26 @@ public:
class Item_func_locate :public Item_int_func
{
String value1,value2;
- bool binary_cmp;
+ DTCollation cmp_collation;
public:
Item_func_locate(Item *a,Item *b) :Item_int_func(a,b) {}
Item_func_locate(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
const char *func_name() const { return "locate"; }
longlong val_int();
- void fix_length_and_dec()
- {
- maybe_null=0; max_length=11;
- binary_cmp = args[0]->binary() || args[1]->binary();
- }
+ void fix_length_and_dec();
};
class Item_func_field :public Item_int_func
{
- Item *item;
String value,tmp;
+ Item_result cmp_type;
+ DTCollation cmp_collation;
public:
- Item_func_field(Item *a,List<Item> &list) :Item_int_func(list),item(a) {}
- ~Item_func_field() { delete item; }
+ Item_func_field(List<Item> &list) :Item_int_func(list) {}
longlong val_int();
- bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
- {
- return (item->fix_fields(thd, tlist, &item) || item->check_cols(1) ||
- Item_func::fix_fields(thd, tlist, ref));
- }
- void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
- void update_used_tables()
- {
- item->update_used_tables() ; Item_func::update_used_tables();
- used_tables_cache|= item->used_tables();
- const_item_cache&= item->const_item();
- }
const char *func_name() const { return "field"; }
- void fix_length_and_dec()
- {
- maybe_null=0; max_length=3;
- used_tables_cache|= item->used_tables();
- const_item_cache&= item->const_item();
- with_sum_func= with_sum_func || item->with_sum_func;
- }
- void set_outer_resolving()
- {
- item->set_outer_resolving();
- Item_int_func::set_outer_resolving();
- }
+ void fix_length_and_dec();
};
@@ -684,6 +661,7 @@ class Item_func_find_in_set :public Item_int_func
String value,value2;
uint enum_value;
ulonglong enum_bit;
+ DTCollation cmp_collation;
public:
Item_func_find_in_set(Item *a,Item *b) :Item_int_func(a,b),enum_value(0) {}
longlong val_int();
@@ -943,7 +921,7 @@ public:
longlong val_int();
String *val_str(String *str);
void update_hash(void *ptr, uint length, enum Item_result type,
- CHARSET_INFO *cs, enum coercion coercibility);
+ CHARSET_INFO *cs, Derivation dv);
bool update();
enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 6db139fdfa6..5ac87a25e67 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -85,7 +85,7 @@ void Item_func_geometry_from_wkb::fix_length_and_dec()
}
-String *Item_func_as_text::val_str(String *str)
+String *Item_func_as_wkt::val_str(String *str)
{
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
@@ -104,7 +104,7 @@ String *Item_func_as_text::val_str(String *str)
return str;
}
-void Item_func_as_text::fix_length_and_dec()
+void Item_func_as_wkt::fix_length_and_dec()
{
max_length=MAX_BLOB_WIDTH;
}
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index 21e94735f31..d86914eb6c5 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -43,10 +43,10 @@ public:
void fix_length_and_dec();
};
-class Item_func_as_text: public Item_str_func
+class Item_func_as_wkt: public Item_str_func
{
public:
- Item_func_as_text(Item *a): Item_str_func(a) {}
+ Item_func_as_wkt(Item *a): Item_str_func(a) {}
const char *func_name() const { return "astext"; }
String *val_str(String *);
void fix_length_and_dec();
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index d660f7c472c..4e35e90b429 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -36,6 +36,14 @@
String empty_string("",default_charset_info);
+static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname)
+{
+ my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
+ c1.collation->name,c1.derivation_name(),
+ c2.collation->name,c2.derivation_name(),
+ fname);
+}
+
uint nr_of_decimals(const char *str)
{
if ((str=strchr(str,'.')))
@@ -316,20 +324,11 @@ void Item_func_concat::fix_length_and_dec()
bool first_coll= 1;
max_length=0;
- set_charset(args[0]->charset(),args[0]->coercibility);
+ if (agg_arg_collations(collation, args, arg_count))
+ return;
+
for (uint i=0 ; i < arg_count ; i++)
- {
max_length+=args[i]->max_length;
- if (set_charset(charset(), coercibility,
- args[i]->charset(), args[i]->coercibility))
- {
- my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0),
- charset()->name,coercion_name(coercibility),
- args[i]->charset()->name,coercion_name(args[i]->coercibility),
- func_name());
- break;
- }
- }
if (max_length > MAX_BLOB_WIDTH)
{
@@ -622,18 +621,14 @@ void Item_func_concat_ws::split_sum_func(Item **ref_pointer_array,
void Item_func_concat_ws::fix_length_and_dec()
{
- set_charset(separator->charset(),separator->coercibility);
+ collation.set(separator->collation);
max_length=separator->max_length*(arg_count-1);
for (uint i=0 ; i < arg_count ; i++)
{
max_length+=args[i]->max_length;
- if (set_charset(charset(), coercibility,
- args[i]->charset(), args[i]->coercibility))
+ if (collation.aggregate(args[i]->collation))
{
- my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0),
- charset()->name,coercion_name(coercibility),
- args[i]->charset()->name,coercion_name(args[i]->coercibility),
- func_name());
+ my_coll_agg_error(collation, args[i]->collation, func_name());
break;
}
}
@@ -702,7 +697,7 @@ String *Item_func_reverse::val_str(String *str)
void Item_func_reverse::fix_length_and_dec()
{
- set_charset(args[0]->charset(),args[0]->coercibility);
+ set_charset(*args[0]);
max_length = args[0]->max_length;
}
@@ -733,8 +728,10 @@ String *Item_func_replace::val_str(String *str)
if (args[1]->null_value)
goto null;
+ res->set_charset(collation.collation);
+
#ifdef USE_MB
- binary_cmp = (args[0]->binary() || args[1]->binary() || !use_mb(res->charset()));
+ binary_cmp = ((res->charset()->state & MY_CS_BINSORT) || !use_mb(res->charset()));
#endif
if (res2->length() == 0)
@@ -825,6 +822,9 @@ void Item_func_replace::fix_length_and_dec()
max_length=MAX_BLOB_WIDTH;
maybe_null=1;
}
+
+ if (agg_arg_collations_for_comparison(collation, args, 3))
+ return;
}
@@ -861,13 +861,10 @@ null:
void Item_func_insert::fix_length_and_dec()
{
- if (set_charset(args[0]->charset(), args[0]->coercibility,
- args[3]->charset(), args[3]->coercibility))
+ if (collation.set(args[0]->collation, args[3]->collation))
{
- my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0),
- args[0]->charset()->name,coercion_name(args[0]->coercibility),
- args[3]->charset()->name,coercion_name(args[3]->coercibility),
- func_name());
+ my_coll_agg_error(args[0]->collation, args[3]->collation, func_name());
+ return;
}
max_length=args[0]->max_length+args[3]->max_length;
if (max_length > MAX_BLOB_WIDTH)
@@ -923,7 +920,6 @@ String *Item_func_left::val_str(String *str)
if (!res->alloced_length())
{ // Don't change const str
str_value= *res; // Not malloced string
- set_charset(res->charset());
res= &str_value;
}
res->length((uint) length);
@@ -948,7 +944,7 @@ void Item_str_func::left_right_max_length()
void Item_func_left::fix_length_and_dec()
{
- set_charset(args[0]->charset(), args[0]->coercibility);
+ set_charset(*args[0]);
left_right_max_length();
}
@@ -975,7 +971,7 @@ String *Item_func_right::val_str(String *str)
void Item_func_right::fix_length_and_dec()
{
- set_charset(args[0]->charset(), args[0]->coercibility);
+ set_charset(*args[0]);
left_right_max_length();
}
@@ -983,13 +979,14 @@ void Item_func_right::fix_length_and_dec()
String *Item_func_substr::val_str(String *str)
{
String *res = args[0]->val_str(str);
- int32 start = (int32) args[1]->val_int()-1;
+ int32 start = (int32) args[1]->val_int();
int32 length = arg_count == 3 ? (int32) args[2]->val_int() : INT_MAX32;
int32 tmp_length;
if ((null_value=(args[0]->null_value || args[1]->null_value ||
(arg_count == 3 && args[2]->null_value))))
return 0; /* purecov: inspected */
+ start= (int32)((start < 0) ? res->length() + start : start -1);
start=res->charpos(start);
length=res->charpos(length,start);
if (start < 0 || (uint) start+1 > res->length() || length <= 0)
@@ -1009,7 +1006,7 @@ void Item_func_substr::fix_length_and_dec()
{
max_length=args[0]->max_length;
- set_charset(args[0]->charset(), args[0]->coercibility);
+ set_charset(*args[0]);
if (args[1]->const_item())
{
int32 start=(int32) args[1]->val_int()-1;
@@ -1029,6 +1026,15 @@ void Item_func_substr::fix_length_and_dec()
}
+void Item_func_substr_index::fix_length_and_dec()
+{
+ max_length= args[0]->max_length;
+
+ if (agg_arg_collations_for_comparison(collation, args, 2))
+ return;
+}
+
+
String *Item_func_substr_index::val_str(String *str)
{
String *res =args[0]->val_str(str);
@@ -1046,6 +1052,8 @@ String *Item_func_substr_index::val_str(String *str)
if (!res->length() || !delimeter_length || !count)
return &empty_string; // Wrong parameters
+ res->set_charset(collation.collation);
+
#ifdef USE_MB
if (use_mb(res->charset()))
{
@@ -1305,18 +1313,15 @@ void Item_func_trim::fix_length_and_dec()
max_length= args[0]->max_length;
if (arg_count == 1)
{
- set_charset(args[0]->charset(), args[0]->coercibility);
+ collation.set(args[0]->collation);
remove.set_charset(charset());
remove.set_ascii(" ",1);
}
else
- if (set_charset(args[1]->charset(), args[1]->coercibility,
- args[0]->charset(), args[0]->coercibility))
+ if (collation.set(args[1]->collation, args[0]->collation) ||
+ collation.derivation == DERIVATION_NONE)
{
- my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0),
- args[1]->charset()->name,coercion_name(args[1]->coercibility),
- args[0]->charset()->name,coercion_name(args[0]->coercibility),
- func_name());
+ my_coll_agg_error(args[1]->collation, args[0]->collation, func_name());
}
}
@@ -1530,7 +1535,7 @@ String *Item_func_user::val_str(String *str)
void Item_func_soundex::fix_length_and_dec()
{
- set_charset(args[0]->charset(), args[0]->coercibility);
+ set_charset(*args[0]);
max_length=args[0]->max_length;
set_if_bigger(max_length,4);
}
@@ -1655,92 +1660,53 @@ void Item_func_elt::fix_length_and_dec()
max_length=0;
decimals=0;
- for (uint i=0 ; i < arg_count ; i++)
+ if (agg_arg_collations(collation, args+1, arg_count-1))
+ return;
+
+ for (uint i=1 ; i < arg_count ; i++)
{
set_if_bigger(max_length,args[i]->max_length);
set_if_bigger(decimals,args[i]->decimals);
- if (i == 0)
- set_charset(args[i]->charset(),args[i]->coercibility);
- else
- {
- if (set_charset(charset(), coercibility,
- args[i]->charset(), args[i]->coercibility))
- {
- my_error(ER_CANT_AGGREGATE_COLLATIONS,MYF(0),
- charset()->name,coercion_name(coercibility),
- args[i]->charset()->name,coercion_name(args[i]->coercibility),
- func_name());
- break;
- }
- }
}
maybe_null=1; // NULL if wrong first arg
- with_sum_func= with_sum_func || item->with_sum_func;
- used_tables_cache|=item->used_tables();
- const_item_cache&=item->const_item();
-}
-
-
-void Item_func_elt::split_sum_func(Item **ref_pointer_array,
- List<Item> &fields)
-{
- if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
- item->split_sum_func(ref_pointer_array, fields);
- else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
- {
- uint el= fields.elements;
- fields.push_front(item);
- ref_pointer_array[el]= item;
- item= new Item_ref(ref_pointer_array + el, 0, item->name);
- }
- Item_str_func::split_sum_func(ref_pointer_array, fields);
-}
-
-
-void Item_func_elt::update_used_tables()
-{
- Item_func::update_used_tables();
- item->update_used_tables();
- used_tables_cache|=item->used_tables();
- const_item_cache&=item->const_item();
}
double Item_func_elt::val()
{
uint tmp;
- if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count)
+ if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
{
null_value=1;
return 0.0;
}
null_value=0;
- return args[tmp-1]->val();
+ return args[tmp]->val();
}
longlong Item_func_elt::val_int()
{
uint tmp;
- if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count)
+ if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
{
null_value=1;
return 0;
}
null_value=0;
- return args[tmp-1]->val_int();
+ return args[tmp]->val_int();
}
String *Item_func_elt::val_str(String *str)
{
uint tmp;
String *res;
- if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count)
+ if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
{
null_value=1;
return NULL;
}
null_value=0;
- res= args[tmp-1]->val_str(str);
+ res= args[tmp]->val_str(str);
res->set_charset(charset());
return res;
}
@@ -1765,8 +1731,13 @@ void Item_func_make_set::split_sum_func(Item **ref_pointer_array,
void Item_func_make_set::fix_length_and_dec()
{
max_length=arg_count-1;
- for (uint i=1 ; i < arg_count ; i++)
+
+ if (agg_arg_collations(collation, args, arg_count))
+ return;
+
+ for (uint i=0 ; i < arg_count ; i++)
max_length+=args[i]->max_length;
+
used_tables_cache|=item->used_tables();
const_item_cache&=item->const_item();
with_sum_func= with_sum_func || item->with_sum_func;
@@ -1889,7 +1860,7 @@ inline String* alloc_buffer(String *res,String *str,String *tmp_value,
void Item_func_repeat::fix_length_and_dec()
{
- set_charset(args[0]->charset(), args[0]->coercibility);
+ set_charset(*args[0]);
if (args[1]->const_item())
{
max_length=(long) (args[0]->max_length * args[1]->val_int());
@@ -1949,6 +1920,12 @@ err:
void Item_func_rpad::fix_length_and_dec()
{
+ if (collation.set(args[0]->collation, args[2]->collation))
+ {
+ my_coll_agg_error(args[0]->collation, args[2]->collation, func_name());
+ return;
+ }
+
if (args[1]->const_item())
{
uint32 length= (uint32) args[1]->val_int();
@@ -2009,6 +1986,12 @@ String *Item_func_rpad::val_str(String *str)
void Item_func_lpad::fix_length_and_dec()
{
+ if (collation.set(args[0]->collation, args[2]->collation))
+ {
+ my_coll_agg_error(args[0]->collation, args[2]->collation, func_name());
+ return;
+ }
+
if (args[1]->const_item())
{
uint32 length= (uint32) args[1]->val_int();
@@ -2126,9 +2109,8 @@ String *Item_func_conv_charset::val_str(String *str)
void Item_func_conv_charset::fix_length_and_dec()
{
- set_charset(conv_charset);
+ set_charset(conv_charset, DERIVATION_IMPLICIT);
max_length = args[0]->max_length*conv_charset->mbmaxlen;
- set_charset(conv_charset, COER_IMPLICIT);
}
@@ -2232,7 +2214,7 @@ void Item_func_set_collation::fix_length_and_dec()
colname,args[0]->charset()->csname);
return;
}
- set_charset(set_collation, COER_EXPLICIT);
+ set_charset(set_collation, DERIVATION_EXPLICIT);
max_length= args[0]->max_length;
}
@@ -2421,6 +2403,9 @@ void Item_func_export_set::fix_length_and_dec()
uint length=max(args[1]->max_length,args[2]->max_length);
uint sep_length=(arg_count > 3 ? args[3]->max_length : 1);
max_length=length*64+sep_length*63;
+
+ if (agg_arg_collations(collation, args+1, min(4,arg_count)-1))
+ return;
}
String* Item_func_inet_ntoa::val_str(String* str)
@@ -2557,7 +2542,7 @@ null:
}
#ifdef HAVE_COMPRESS
-#include "../zlib/zlib.h"
+#include "zlib.h"
String *Item_func_compress::val_str(String *str)
{
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 26c69668b0a..7f8d7ade67b 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -153,7 +153,7 @@ public:
Item_str_conv(Item *item) :Item_str_func(item) {}
void fix_length_and_dec()
{
- set_charset(args[0]->charset(), args[0]->coercibility);
+ set_charset(*args[0]);
max_length = args[0]->max_length;
}
};
@@ -215,7 +215,7 @@ class Item_func_substr_index :public Item_str_func
public:
Item_func_substr_index(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
String *val_str(String *);
- void fix_length_and_dec() { max_length= args[0]->max_length; }
+ void fix_length_and_dec();
const char *func_name() const { return "substr_index"; }
};
@@ -335,7 +335,7 @@ public:
class Item_func_database :public Item_str_func
{
public:
- Item_func_database() { coercibility= COER_IMPLICIT; }
+ Item_func_database() { set_charset(DERIVATION_IMPLICIT); }
String *val_str(String *);
void fix_length_and_dec()
{
@@ -348,7 +348,7 @@ public:
class Item_func_user :public Item_str_func
{
public:
- Item_func_user() { coercibility= COER_IMPLICIT; }
+ Item_func_user() { set_charset(DERIVATION_IMPLICIT); }
String *val_str(String *);
void fix_length_and_dec()
{
@@ -372,29 +372,13 @@ public:
class Item_func_elt :public Item_str_func
{
- Item *item;
-
public:
- Item_func_elt(Item *a,List<Item> &list) :Item_str_func(list),item(a) {}
- ~Item_func_elt() { delete item; }
+ Item_func_elt(List<Item> &list) :Item_str_func(list) {}
double val();
longlong val_int();
String *val_str(String *str);
- bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
- {
- return (item->fix_fields(thd, tlist, &item) ||
- item->check_cols(1) ||
- Item_func::fix_fields(thd, tlist, ref));
- }
- void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
void fix_length_and_dec();
- void update_used_tables();
const char *func_name() const { return "elt"; }
- void set_outer_resolving()
- {
- item->set_outer_resolving();
- Item_str_func::set_outer_resolving();
- }
};
@@ -433,6 +417,7 @@ public:
String *val_str(String *);
void fix_length_and_dec()
{
+ set_charset(default_charset());
max_length=args[0]->max_length+(args[0]->max_length-args[0]->decimals)/3;
}
const char *func_name() const { return "format"; }
@@ -444,7 +429,11 @@ class Item_func_char :public Item_str_func
public:
Item_func_char(List<Item> &list) :Item_str_func(list) {}
String *val_str(String *);
- void fix_length_and_dec() { maybe_null=0; max_length=arg_count; }
+ void fix_length_and_dec()
+ {
+ set_charset(default_charset());
+ maybe_null=0; max_length=arg_count;
+ }
const char *func_name() const { return "char"; }
};
@@ -490,7 +479,11 @@ public:
Item_func_conv(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
const char *func_name() const { return "conv"; }
String *val_str(String *);
- void fix_length_and_dec() { decimals=0; max_length=64; }
+ void fix_length_and_dec()
+ {
+ set_charset(default_charset());
+ decimals=0; max_length=64;
+ }
};
@@ -501,7 +494,11 @@ public:
Item_func_hex(Item *a) :Item_str_func(a) {}
const char *func_name() const { return "hex"; }
String *val_str(String *);
- void fix_length_and_dec() { decimals=0; max_length=args[0]->max_length*2; }
+ void fix_length_and_dec()
+ {
+ set_charset(default_charset());
+ decimals=0; max_length=args[0]->max_length*2;
+ }
};
@@ -536,7 +533,7 @@ public:
const char *func_name() const { return "load_file"; }
void fix_length_and_dec()
{
- set_charset(&my_charset_bin, COER_COERCIBLE);
+ set_charset(&my_charset_bin, DERIVATION_COERCIBLE);
maybe_null=1;
max_length=MAX_BLOB_WIDTH;
}
@@ -573,7 +570,7 @@ public:
String *val_str(String *);
void fix_length_and_dec()
{
- set_charset(args[0]->charset(), args[0]->coercibility);
+ set_charset(*args[0]);
max_length= args[0]->max_length * 2 + 2;
}
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 8c9b3eeebde..cd78edfee7b 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -508,7 +508,7 @@ void Item_in_subselect::single_value_transformer(THD *thd,
{
sl->item_list.push_back(item);
setup_ref_array(thd, &sl->ref_pointer_array,
- 1 + sl->with_sum_func +
+ 1 + sl->select_items +
sl->order_list.elements + sl->group_list.elements);
// To prevent crash on Item_ref_null_helper destruction in case of error
sl->ref_pointer_array[0]= 0;
@@ -824,6 +824,8 @@ int subselect_single_select_engine::exec()
{
DBUG_ENTER("subselect_single_select_engine::exec");
char const *save_where= join->thd->where;
+ SELECT_LEX_NODE *save_select= join->thd->lex.current_select;
+ join->thd->lex.current_select= select_lex;
if (!optimized)
{
optimized=1;
@@ -831,6 +833,7 @@ int subselect_single_select_engine::exec()
{
join->thd->where= save_where;
executed= 1;
+ join->thd->lex.current_select= save_select;
DBUG_RETURN(join->error?join->error:1);
}
}
@@ -839,6 +842,7 @@ int subselect_single_select_engine::exec()
if (join->reinit())
{
join->thd->where= save_where;
+ join->thd->lex.current_select= save_select;
DBUG_RETURN(1);
}
item->reset();
@@ -846,15 +850,14 @@ int subselect_single_select_engine::exec()
}
if (!executed)
{
- SELECT_LEX_NODE *save_select= join->thd->lex.current_select;
- join->thd->lex.current_select= select_lex;
join->exec();
- join->thd->lex.current_select= save_select;
executed= 1;
join->thd->where= save_where;
+ join->thd->lex.current_select= save_select;
DBUG_RETURN(join->error||thd->is_fatal_error);
}
join->thd->where= save_where;
+ join->thd->lex.current_select= save_select;
DBUG_RETURN(0);
}
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index a57291702bc..8d3d0de466a 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -57,7 +57,7 @@ Item_sum::Item_sum(THD *thd, Item_sum &item):
void Item_sum::mark_as_sum_func()
{
- current_thd->lex.current_select->with_sum_func++;
+ current_thd->lex.current_select->with_sum_func= 1;
with_sum_func= 1;
}
@@ -1114,7 +1114,7 @@ void Item_sum_count_distinct::make_unique()
bool Item_sum_count_distinct::setup(THD *thd)
{
List<Item> list;
- SELECT_LEX *select_lex= current_lex->current_select->select_lex();
+ SELECT_LEX *select_lex= thd->lex.current_select->select_lex();
if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
return 1;
@@ -1453,27 +1453,28 @@ String *Item_sum_udf_str::val_str(String *str)
GROUP_CONCAT(DISTINCT expr,...)
*/
-static int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
- byte* key2)
+int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
+ byte* key2)
{
Item_func_group_concat* item= (Item_func_group_concat*)arg;
+
for (uint i= 0; i < item->arg_count_field; i++)
{
- Item *field_item= item->expr[i];
+ Item *field_item= item->args[i];
Field *field= field_item->tmp_table_field();
if (field)
{
- uint offset= field->offset();
+ uint offset= field->abs_offset;
int res= field->key_cmp(key1 + offset, key2 + offset);
/*
if key1 and key2 is not equal than field->key_cmp return offset. This
- function must return value 1 for this case.
+ function must return value 1 for this case.
*/
if (res)
return 1;
}
- }
+ }
return 0;
}
@@ -1483,9 +1484,10 @@ static int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
GROUP_CONCAT(expr,... ORDER BY col,... )
*/
-static int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
+int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
{
Item_func_group_concat* item= (Item_func_group_concat*)arg;
+
for (uint i=0; i < item->arg_count_order; i++)
{
ORDER *order_item= item->order[i];
@@ -1493,14 +1495,14 @@ static int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
Field *field= item->tmp_table_field();
if (field)
{
- uint offset= field->offset();
+ uint offset= field->abs_offset;
bool dir= order_item->asc;
int res= field->key_cmp(key1 + offset, key2 + offset);
if (res)
return dir ? res : -res;
}
- }
+ }
/*
We can't return 0 because tree class remove this item as double value.
*/
@@ -1513,9 +1515,8 @@ static int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... )
*/
-static int group_concat_key_cmp_with_distinct_and_order(void* arg,
- byte* key1,
- byte* key2)
+int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1,
+ byte* key2)
{
if (!group_concat_key_cmp_with_distinct(arg,key1,key2))
return 0;
@@ -1528,24 +1529,23 @@ static int group_concat_key_cmp_with_distinct_and_order(void* arg,
item is pointer to Item_func_group_concat
*/
-static int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
+int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
Item_func_group_concat *group_concat_item)
{
char buff[MAX_FIELD_WIDTH];
String tmp((char *)&buff,sizeof(buff),default_charset_info);
String tmp2((char *)&buff,sizeof(buff),default_charset_info);
-
+
tmp.length(0);
for (uint i= 0; i < group_concat_item->arg_show_fields; i++)
{
- Item *show_item= group_concat_item->expr[i];
+ Item *show_item= group_concat_item->args[i];
if (!show_item->const_item())
{
Field *f= show_item->tmp_table_field();
- uint offset= f->offset();
char *sv= f->ptr;
- f->ptr= (char *)key + offset;
+ f->ptr= (char *)key + f->abs_offset;
String *res= f->val_str(&tmp,&tmp2);
group_concat_item->result.append(*res);
f->ptr= sv;
@@ -1595,15 +1595,23 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
List<Item> *is_select,
SQL_LIST *is_order,
String *is_separator)
- :Item_sum(), tmp_table_param(0), warning_available(false),
- separator(is_separator), tree(&tree_base), table(0),
- count_cut_values(0), tree_mode(0), distinct(is_distinct)
+ :Item_sum(), tmp_table_param(0), max_elements_in_tree(0), warning(0),
+ warning_available(0), key_length(0), rec_offset(0),
+ tree_mode(0), distinct(is_distinct), warning_for_row(0),
+ separator(is_separator), tree(&tree_base), table(0),
+ order(0), tables_list(0),
+ show_elements(0), arg_count_order(0), arg_count_field(0),
+ arg_show_fields(0), count_cut_values(0)
+
{
original= 0;
quick_group= 0;
mark_as_sum_func();
- SELECT_LEX *select_lex= current_lex->current_select->select_lex();
+ item_thd= current_thd;
+ SELECT_LEX *select_lex= item_thd->lex.current_select->select_lex();
order= 0;
+ group_concat_max_len= item_thd->variables.group_concat_max_len;
+
arg_show_fields= arg_count_field= is_select->elements;
arg_count_order= is_order ? is_order->elements : 0;
@@ -1613,16 +1621,12 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
We need to allocate:
args - arg_count+arg_count_order (for possible order items in temporare
tables)
- expr - arg_count_field
order - arg_count_order
*/
- args= (Item**) sql_alloc(sizeof(Item*)*(arg_count+arg_count_order+
- arg_count_field)+
+ args= (Item**) sql_alloc(sizeof(Item*)*(arg_count+arg_count_order)+
sizeof(ORDER*)*arg_count_order);
if (!args)
- return; // thd->fatal is set
- expr= args;
- expr+= arg_count+arg_count_order;
+ return;
/* fill args items of show and sort */
int i= 0;
@@ -1630,12 +1634,12 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
Item *item_select;
for ( ; (item_select= li++) ; i++)
- args[i]= expr[i]= item_select;
+ args[i]= item_select;
if (arg_count_order)
{
i= 0;
- order= (ORDER**)(expr + arg_count_field);
+ order= (ORDER**)(args + arg_count + arg_count_order);
for (ORDER *order_item= (ORDER*) is_order->first;
order_item != NULL;
order_item= order_item->next)
@@ -1696,13 +1700,15 @@ bool Item_func_group_concat::reset()
bool Item_func_group_concat::add()
{
+ if (always_null)
+ return 0;
copy_fields(tmp_table_param);
copy_funcs(tmp_table_param->items_to_copy);
bool record_is_null= TRUE;
for (uint i= 0; i < arg_show_fields; i++)
{
- Item *show_item= expr[i];
+ Item *show_item= args[i];
if (!show_item->const_item())
{
Field *f= show_item->tmp_table_field();
@@ -1718,13 +1724,13 @@ bool Item_func_group_concat::add()
null_value= FALSE;
if (tree_mode)
{
- if (!tree_insert(tree, table->record[0], 0,tree->custom_arg))
+ if (!tree_insert(tree, table->record[0] + rec_offset, 0, tree->custom_arg))
return 1;
}
else
{
if (result.length() <= group_concat_max_len && !warning_for_row)
- dump_leaf_key(table->record[0],1,
+ dump_leaf_key(table->record[0] + rec_offset, 1,
(Item_func_group_concat*)this);
}
return 0;
@@ -1757,12 +1763,6 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 1;
maybe_null |= args[i]->maybe_null;
}
- for (i= 0 ; i < arg_count_field ; i++)
- {
- if (expr[i]->fix_fields(thd, tables, expr + i) || expr[i]->check_cols(1))
- return 1;
- maybe_null |= expr[i]->maybe_null;
- }
/*
Fix fields for order clause in function:
GROUP_CONCAT(expr,... ORDER BY col,... )
@@ -1776,7 +1776,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
result_field= 0;
null_value= 1;
- fix_length_and_dec();
+ max_length= group_concat_max_len;
thd->allow_sum_func= 1;
if (!(tmp_table_param= new TMP_TABLE_PARAM))
return 1;
@@ -1788,19 +1788,21 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
bool Item_func_group_concat::setup(THD *thd)
{
+ DBUG_ENTER("Item_func_group_concat::setup");
List<Item> list;
- SELECT_LEX *select_lex= current_lex->current_select->select_lex();
+ SELECT_LEX *select_lex= thd->lex.current_select->select_lex();
if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
- return 1;
+ DBUG_RETURN(1);
/*
all not constant fields are push to list and create temp table
*/
+ always_null= 0;
for (uint i= 0; i < arg_count; i++)
{
Item *item= args[i];
if (list.push_back(item))
- return 1;
+ DBUG_RETURN(1);
if (item->const_item())
{
(void) item->val_int();
@@ -1808,6 +1810,8 @@ bool Item_func_group_concat::setup(THD *thd)
always_null= 1;
}
}
+ if (always_null)
+ DBUG_RETURN(0);
List<Item> all_fields(list);
if (arg_count_order)
@@ -1818,21 +1822,39 @@ bool Item_func_group_concat::setup(THD *thd)
}
count_field_types(tmp_table_param,all_fields,0);
+ if (table)
+ {
+ free_tmp_table(thd, table);
+ tmp_table_param->cleanup();
+ }
/*
We have to create a temporary table for that we get descriptions of fields
(types, sizes and so on).
*/
if (!(table=create_tmp_table(thd, tmp_table_param, all_fields, 0,
- 0, 0, 0,select_lex->options | thd->options)))
- return 1;
+ 0, 0, 0,select_lex->options | thd->options)))
+ DBUG_RETURN(1);
table->file->extra(HA_EXTRA_NO_ROWS);
table->no_rows= 1;
- qsort_cmp2 compare_key;
-
- tree_mode= distinct || arg_count_order;
+
+
+ Field** field, **field_end;
+ field_end = (field = table->field) + table->fields;
+ uint offset = 0;
+ for (key_length = 0; field < field_end; ++field)
+ {
+ uint32 length= (*field)->pack_length();
+ (*field)->abs_offset= offset;
+ offset+= length;
+ key_length += length;
+ }
+ rec_offset = table->reclength - key_length;
+
/*
choise function of sort
*/
+ tree_mode= distinct || arg_count_order;
+ qsort_cmp2 compare_key;
if (tree_mode)
{
if (arg_count_order)
@@ -1856,13 +1878,10 @@ bool Item_func_group_concat::setup(THD *thd)
*/
init_tree(tree, min(thd->variables.max_heap_table_size,
thd->variables.sortbuff_size/16), 0,
- table->reclength, compare_key, 0, NULL, (void*) this);
- max_elements_in_tree= ((table->reclength) ?
- thd->variables.max_heap_table_size/table->reclength : 1);
+ key_length, compare_key, 0, NULL, (void*) this);
+ max_elements_in_tree= ((key_length) ?
+ thd->variables.max_heap_table_size/key_length : 1);
};
- item_thd= thd;
-
- group_concat_max_len= thd->variables.group_concat_max_len;
/*
Copy table and tree_mode if they belong to this item (if item have not
@@ -1873,7 +1892,7 @@ bool Item_func_group_concat::setup(THD *thd)
original->table= table;
original->tree_mode= tree_mode;
}
- return 0;
+ DBUG_RETURN(0);
}
/* This is used by rollup to create a separate usable copy of the function */
@@ -1909,3 +1928,6 @@ String* Item_func_group_concat::val_str(String* str)
}
return &result;
}
+
+
+
diff --git a/sql/item_sum.h b/sql/item_sum.h
index c8614dda679..6f0d7a028a7 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -644,13 +644,28 @@ class Item_func_group_concat : public Item_sum
uint max_elements_in_tree;
MYSQL_ERROR *warning;
bool warning_available;
+ uint key_length;
+ int rec_offset;
+ bool tree_mode;
+ bool distinct;
+ bool warning_for_row;
+ bool always_null;
+
+ friend int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
+ byte* key2);
+ friend int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2);
+ friend int group_concat_key_cmp_with_distinct_and_order(void* arg,
+ byte* key1,
+ byte* key2);
+ friend int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
+ Item_func_group_concat *group_concat_item);
+
public:
String result;
String *separator;
TREE tree_base;
TREE *tree;
TABLE *table;
- Item **expr;
ORDER **order;
TABLE_LIST *tables_list;
ulong group_concat_max_len;
@@ -659,9 +674,6 @@ class Item_func_group_concat : public Item_sum
uint arg_count_field;
uint arg_show_fields;
uint count_cut_values;
- bool tree_mode, distinct;
- bool warning_for_row;
- bool always_null;
/*
Following is 0 normal object and pointer to original one for copy
(to correctly free resources)
@@ -677,10 +689,14 @@ class Item_func_group_concat : public Item_sum
max_elements_in_tree(item.max_elements_in_tree),
warning(item.warning),
warning_available(item.warning_available),
+ key_length(item.key_length),
+ rec_offset(item.rec_offset),
+ tree_mode(0),
+ distinct(item.distinct),
+ warning_for_row(item.warning_for_row),
separator(item.separator),
tree(item.tree),
table(item.table),
- expr(item.expr),
order(item.order),
tables_list(item.tables_list),
group_concat_max_len(item.group_concat_max_len),
@@ -689,9 +705,6 @@ class Item_func_group_concat : public Item_sum
arg_count_field(item.arg_count_field),
arg_show_fields(item.arg_show_fields),
count_cut_values(item.count_cut_values),
- tree_mode(0),
- distinct(item.distinct),
- warning_for_row(item.warning_for_row),
original(&item)
{
quick_group = 0;
@@ -700,7 +713,6 @@ class Item_func_group_concat : public Item_sum
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
const char *func_name() const { return "group_concat"; }
enum Type type() const { return SUM_FUNC_ITEM; }
- void fix_length_and_dec() { max_length=group_concat_max_len; }
virtual Item_result result_type () const { return STRING_RESULT; }
bool reset();
bool add();
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 61c869cddba..c2d1504e94a 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -29,6 +29,8 @@
** Todo: Move month and days to language files
*/
+#define MAX_DAY_NUMBER 3652424L
+
static String month_names[] =
{
String("January", &my_charset_latin1),
@@ -55,6 +57,82 @@ static String day_names[] =
String("Sunday", &my_charset_latin1)
};
+enum date_time_format_types
+{
+ TIME_ONLY= 0, TIME_MICROSECOND,
+ DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
+};
+
+typedef struct date_time_format
+{
+ const char* format_str;
+ uint length;
+};
+
+static struct date_time_format date_time_formats[]=
+{
+ {"%s%02d:%02d:%02d", 10},
+ {"%s%02d:%02d:%02d.%06d", 17},
+ {"%04d-%02d-%02d", 10},
+ {"%04d-%02d-%02d %02d:%02d:%02d", 19},
+ {"%04d-%02d-%02d %02d:%02d:%02d.%06d", 26}
+};
+
+
+/*
+ OPTIMIZATION TODO:
+ - Replace the switch with a function that should be called for each
+ date type.
+ - Remove sprintf and opencode the conversion, like we do in
+ Field_datetime.
+*/
+
+String *make_datetime(String *str, TIME *ltime,
+ enum date_time_format_types format)
+{
+ char *buff;
+ CHARSET_INFO *cs= &my_charset_bin;
+ uint length= date_time_formats[format].length + 32;
+ const char* format_str= date_time_formats[format].format_str;
+
+ if (str->alloc(length))
+ return 0;
+
+ buff= (char*) str->ptr();
+ switch (format) {
+ case TIME_ONLY:
+ length= cs->cset->snprintf(cs, buff, length, format_str, ltime->neg ? "-" : "",
+ ltime->hour, ltime->minute, ltime->second);
+ break;
+ case TIME_MICROSECOND:
+ length= cs->cset->snprintf(cs, buff, length, format_str, ltime->neg ? "-" : "",
+ ltime->hour, ltime->minute, ltime->second,
+ ltime->second_part);
+ break;
+ case DATE_ONLY:
+ length= cs->cset->snprintf(cs, buff, length, format_str,
+ ltime->year, ltime->month, ltime->day);
+ break;
+ case DATE_TIME:
+ length= cs->cset->snprintf(cs, buff, length, format_str,
+ ltime->year, ltime->month, ltime->day,
+ ltime->hour, ltime->minute, ltime->second);
+ break;
+ case DATE_TIME_MICROSECOND:
+ length= cs->cset->snprintf(cs, buff, length, format_str,
+ ltime->year, ltime->month, ltime->day,
+ ltime->hour, ltime->minute, ltime->second,
+ ltime->second_part);
+ break;
+ default:
+ return 0;
+ }
+
+ str->length(length);
+ str->set_charset(cs);
+ return str;
+}
+
/*
** Get a array of positive numbers from a string object.
** Each number is separated by 1 non digit character
@@ -302,14 +380,14 @@ longlong Item_func_time_to_sec::val_int()
static bool get_interval_value(Item *args,interval_type int_type,
String *str_value, INTERVAL *t)
{
- long array[4],value;
+ long array[5],value;
const char *str;
uint32 length;
LINT_INIT(value); LINT_INIT(str); LINT_INIT(length);
CHARSET_INFO *cs=str_value->charset();
bzero((char*) t,sizeof(*t));
- if ((int) int_type <= INTERVAL_SECOND)
+ if ((int) int_type <= INTERVAL_MICROSECOND)
{
value=(long) args->val_int();
if (args->null_value)
@@ -352,6 +430,9 @@ static bool get_interval_value(Item *args,interval_type int_type,
case INTERVAL_HOUR:
t->hour=value;
break;
+ case INTERVAL_MICROSECOND:
+ t->second_part=value;
+ break;
case INTERVAL_MINUTE:
t->minute=value;
break;
@@ -370,6 +451,15 @@ static bool get_interval_value(Item *args,interval_type int_type,
t->day=array[0];
t->hour=array[1];
break;
+ case INTERVAL_DAY_MICROSECOND:
+ if (get_interval_info(str,length,cs,5,array))
+ return (1);
+ t->day=array[0];
+ t->hour=array[1];
+ t->minute=array[2];
+ t->second=array[3];
+ t->second_part=array[4];
+ break;
case INTERVAL_DAY_MINUTE:
if (get_interval_info(str,length,cs,3,array))
return (1);
@@ -385,6 +475,14 @@ static bool get_interval_value(Item *args,interval_type int_type,
t->minute=array[2];
t->second=array[3];
break;
+ case INTERVAL_HOUR_MICROSECOND:
+ if (get_interval_info(str,length,cs,4,array))
+ return (1);
+ t->hour=array[0];
+ t->minute=array[1];
+ t->second=array[2];
+ t->second_part=array[3];
+ break;
case INTERVAL_HOUR_MINUTE:
if (get_interval_info(str,length,cs,2,array))
return (1);
@@ -398,12 +496,25 @@ static bool get_interval_value(Item *args,interval_type int_type,
t->minute=array[1];
t->second=array[2];
break;
+ case INTERVAL_MINUTE_MICROSECOND:
+ if (get_interval_info(str,length,cs,3,array))
+ return (1);
+ t->minute=array[0];
+ t->second=array[1];
+ t->second_part=array[2];
+ break;
case INTERVAL_MINUTE_SECOND:
if (get_interval_info(str,length,cs,2,array))
return (1);
t->minute=array[0];
t->second=array[1];
break;
+ case INTERVAL_SECOND_MICROSECOND:
+ if (get_interval_info(str,length,cs,2,array))
+ return (1);
+ t->second=array[0];
+ t->second_part=array[1];
+ break;
}
return 0;
}
@@ -687,6 +798,9 @@ uint Item_func_date_format::format_length(const String *format)
case 'T': /* time, 24-hour (hh:mm:ss) */
size += 8;
break;
+ case 'f': /* microseconds */
+ size += 6;
+ break;
case 'w': /* day (of the week), numeric */
case '%':
default:
@@ -798,8 +912,8 @@ String *Item_func_date_format::val_str(String *str)
null_value=1;
return 0;
}
- length= my_sprintf(intbuff, (intbuff,"%d",l_time.day));
- str->append(intbuff, length);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
if (l_time.day >= 10 && l_time.day <= 19)
str->append("th");
else
@@ -821,41 +935,45 @@ String *Item_func_date_format::val_str(String *str)
}
break;
case 'Y':
- sprintf(intbuff,"%04d",l_time.year);
- str->append(intbuff,4);
+ length= int10_to_str(l_time.year, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 4, '0');
break;
case 'y':
- sprintf(intbuff,"%02d",l_time.year%100);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.year%100, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'm':
- sprintf(intbuff,"%02d",l_time.month);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.month, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'c':
- sprintf(intbuff,"%d",l_time.month);
- str->append(intbuff);
+ length= int10_to_str(l_time.month, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'd':
- sprintf(intbuff,"%02d",l_time.day);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'e':
- sprintf(intbuff,"%d",l_time.day);
- str->append(intbuff);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
+ break;
+ case 'f':
+ length= int10_to_str(l_time.second_part, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 6, '0');
break;
case 'H':
- sprintf(intbuff,"%02d",l_time.hour);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.hour, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'h':
case 'I':
- sprintf(intbuff,"%02d", (l_time.hour+11)%12+1);
- str->append(intbuff,2);
+ length= int10_to_str((l_time.hour+11)%12+1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'i': /* minutes */
- sprintf(intbuff,"%02d",l_time.minute);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.minute, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'j':
if (date_or_time)
@@ -863,52 +981,60 @@ String *Item_func_date_format::val_str(String *str)
null_value=1;
return 0;
}
- sprintf(intbuff,"%03d",
- (int) (calc_daynr(l_time.year,l_time.month,l_time.day) -
- calc_daynr(l_time.year,1,1)) + 1);
- str->append(intbuff,3);
+ length= int10_to_str(calc_daynr(l_time.year,l_time.month,l_time.day) -
+ calc_daynr(l_time.year,1,1) + 1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 3, '0');
break;
case 'k':
- sprintf(intbuff,"%d",l_time.hour);
- str->append(intbuff);
+ length= int10_to_str(l_time.hour, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'l':
- sprintf(intbuff,"%d", (l_time.hour+11)%12+1);
- str->append(intbuff);
+ length= int10_to_str((l_time.hour+11)%12+1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'p':
str->append(l_time.hour < 12 ? "AM" : "PM",2);
break;
case 'r':
- sprintf(intbuff,(l_time.hour < 12) ? "%02d:%02d:%02d AM" :
- "%02d:%02d:%02d PM",(l_time.hour+11)%12+1,l_time.minute,
- l_time.second);
- str->append(intbuff);
+ length= my_sprintf(intbuff,
+ (intbuff,
+ (l_time.hour < 12) ? "%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
+ (l_time.hour+11)%12+1,
+ l_time.minute,
+ l_time.second));
+ str->append(intbuff, length);
break;
case 'S':
case 's':
- sprintf(intbuff,"%02d",l_time.second);
- str->append(intbuff);
+ length= int10_to_str(l_time.second, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'T':
- sprintf(intbuff,"%02d:%02d:%02d", l_time.hour, l_time.minute,
- l_time.second);
- str->append(intbuff);
+ length= my_sprintf(intbuff,
+ (intbuff,
+ "%02d:%02d:%02d",
+ l_time.hour,
+ l_time.minute,
+ l_time.second));
+ str->append(intbuff, length);
break;
case 'U':
case 'u':
{
uint year;
- sprintf(intbuff,"%02d",calc_week(&l_time, 0, (*ptr) == 'U', &year));
- str->append(intbuff,2);
+ length= int10_to_str(calc_week(&l_time, 0, (*ptr) == 'U', &year),
+ intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
}
break;
case 'v':
case 'V':
{
uint year;
- sprintf(intbuff,"%02d",calc_week(&l_time, 1, (*ptr) == 'V', &year));
- str->append(intbuff,2);
+ length= int10_to_str(calc_week(&l_time, 1, (*ptr) == 'V', &year),
+ intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
}
break;
case 'x':
@@ -916,14 +1042,15 @@ String *Item_func_date_format::val_str(String *str)
{
uint year;
(void) calc_week(&l_time, 1, (*ptr) == 'X', &year);
- sprintf(intbuff,"%04d",year);
- str->append(intbuff,4);
+ length= int10_to_str(year, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 4, '0');
}
break;
case 'w':
weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),1);
- sprintf(intbuff,"%d",weekday);
- str->append(intbuff,1);
+ length= int10_to_str(weekday, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
+
break;
default:
str->append(*ptr);
@@ -1005,7 +1132,7 @@ void Item_date_add_interval::fix_length_and_dec()
enum_field_types arg0_field_type;
set_charset(default_charset());
maybe_null=1;
- max_length=19*default_charset()->mbmaxlen;
+ max_length=26*MY_CHARSET_BIN_MB_MAXLEN;
value.alloc(32);
/*
@@ -1051,39 +1178,55 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
null_value=0;
switch (int_type) {
case INTERVAL_SECOND:
+ case INTERVAL_SECOND_MICROSECOND:
+ case INTERVAL_MICROSECOND:
case INTERVAL_MINUTE:
case INTERVAL_HOUR:
+ case INTERVAL_MINUTE_MICROSECOND:
case INTERVAL_MINUTE_SECOND:
+ case INTERVAL_HOUR_MICROSECOND:
case INTERVAL_HOUR_SECOND:
case INTERVAL_HOUR_MINUTE:
+ case INTERVAL_DAY_MICROSECOND:
case INTERVAL_DAY_SECOND:
case INTERVAL_DAY_MINUTE:
case INTERVAL_DAY_HOUR:
- long sec,days,daynr;
+ long sec,days,daynr,microseconds,extra_sec;
ltime->time_type=TIMESTAMP_FULL; // Return full date
+ microseconds= ltime->second_part + sign*interval.second_part;
+ extra_sec= microseconds/1000000L;
+ microseconds= microseconds%1000000L;
sec=((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
ltime->second +
sign*(interval.day*3600*24L +
- interval.hour*3600+interval.minute*60+interval.second));
+ interval.hour*3600+interval.minute*60+interval.second))+
+ extra_sec;
+
+ if (microseconds < 0)
+ {
+ microseconds+= 1000000L;
+ sec--;
+ }
days=sec/(3600*24L); sec=sec-days*3600*24L;
if (sec < 0)
{
days--;
sec+=3600*24L;
}
+ ltime->second_part= microseconds;
ltime->second=sec % 60;
ltime->minute=sec/60 % 60;
ltime->hour=sec/3600;
daynr= calc_daynr(ltime->year,ltime->month,1) + days;
get_date_from_daynr(daynr,&ltime->year,&ltime->month,&ltime->day);
- if (daynr < 0 || daynr >= 3652424) // Day number from year 0 to 9999-12-31
+ if (daynr < 0 || daynr >= MAX_DAY_NUMBER) // Day number from year 0 to 9999-12-31
goto null_date;
break;
case INTERVAL_DAY:
period= calc_daynr(ltime->year,ltime->month,ltime->day) +
sign*interval.day;
- if (period < 0 || period >= 3652424) // Daynumber from year 0 to 9999-12-31
+ if (period < 0 || period >= MAX_DAY_NUMBER) // Daynumber from year 0 to 9999-12-31
goto null_date;
get_date_from_daynr((long) period,&ltime->year,&ltime->month,&ltime->day);
break;
@@ -1124,34 +1267,21 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
String *Item_date_add_interval::val_str(String *str)
{
TIME ltime;
- CHARSET_INFO *cs=default_charset();
- uint32 l;
+ enum date_time_format_types format;
if (Item_date_add_interval::get_date(&ltime,0))
return 0;
+
if (ltime.time_type == TIMESTAMP_DATE)
- {
- l=11*cs->mbmaxlen+32;
- if (str->alloc(l))
- goto null_date;
- l=cs->cset->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d",
- ltime.year,ltime.month,ltime.day);
- str->length(l);
- }
+ format= DATE_ONLY;
+ else if (ltime.second_part)
+ format= DATE_TIME_MICROSECOND;
else
- {
- l=20*cs->mbmaxlen+32;
- if (str->alloc(l))
- goto null_date;
- l=cs->cset->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d",
- ltime.year,ltime.month,ltime.day,
- ltime.hour,ltime.minute,ltime.second);
- str->length(l);
- }
- str->set_charset(cs);
- return str;
+ format= DATE_TIME;
+
+ if (make_datetime(str, &ltime, format))
+ return str;
- null_date:
null_value=1;
return 0;
}
@@ -1188,6 +1318,11 @@ void Item_extract::fix_length_and_dec()
case INTERVAL_MINUTE: max_length=2; date_value=0; break;
case INTERVAL_MINUTE_SECOND: max_length=4; date_value=0; break;
case INTERVAL_SECOND: max_length=2; date_value=0; break;
+ case INTERVAL_MICROSECOND: max_length=2; date_value=0; break;
+ case INTERVAL_DAY_MICROSECOND: max_length=20; date_value=0; break;
+ case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break;
+ case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break;
+ case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break;
}
}
@@ -1234,6 +1369,21 @@ longlong Item_extract::val_int()
case INTERVAL_MINUTE: return (long) ltime.minute*neg;
case INTERVAL_MINUTE_SECOND: return (long) (ltime.minute*100+ltime.second)*neg;
case INTERVAL_SECOND: return (long) ltime.second*neg;
+ case INTERVAL_MICROSECOND: return (long) ltime.second_part*neg;
+ case INTERVAL_DAY_MICROSECOND: return (((longlong)ltime.day*1000000L +
+ (longlong)ltime.hour*10000L +
+ ltime.minute*100 +
+ ltime.second)*1000000L +
+ ltime.second_part)*neg;
+ case INTERVAL_HOUR_MICROSECOND: return (((longlong)ltime.hour*10000L +
+ ltime.minute*100 +
+ ltime.second)*1000000L +
+ ltime.second_part)*neg;
+ case INTERVAL_MINUTE_MICROSECOND: return (((longlong)(ltime.minute*100+
+ ltime.second))*1000000L+
+ ltime.second_part)*neg;
+ case INTERVAL_SECOND_MICROSECOND: return ((longlong)ltime.second*1000000L+
+ ltime.second_part)*neg;
}
return 0; // Impossible
}
@@ -1247,3 +1397,337 @@ void Item_typecast::print(String *str)
str->append(func_name());
str->append(')');
}
+
+String *Item_datetime_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_date(&ltime,1) &&
+ make_datetime(str, &ltime, ltime.second_part ?
+ DATE_TIME_MICROSECOND : DATE_TIME))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+
+bool Item_time_typecast::get_time(TIME *ltime)
+{
+ bool res= get_arg0_time(ltime);
+ ltime->time_type= TIMESTAMP_TIME;
+ return res;
+}
+
+
+String *Item_time_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_time(&ltime) &&
+ make_datetime(str, &ltime, ltime.second_part ? TIME_MICROSECOND : TIME_ONLY))
+ return str;
+
+ null_value=1;
+ return 0;
+}
+
+
+bool Item_date_typecast::get_date(TIME *ltime, bool fuzzy_date)
+{
+ bool res= get_arg0_date(ltime,1);
+ ltime->time_type= TIMESTAMP_DATE;
+ return res;
+}
+
+
+String *Item_date_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_date(&ltime,1) &&
+ make_datetime(str, &ltime, DATE_ONLY))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+/*
+ MAKEDATE(a,b) is a date function that creates a date value
+ from a year and day value.
+*/
+
+String *Item_func_makedate::val_str(String *str)
+{
+ TIME l_time;
+ long daynr= args[1]->val_int();
+ long yearnr= args[0]->val_int();
+ long days;
+
+ if (args[0]->null_value || args[1]->null_value ||
+ yearnr < 0 || daynr <= 0)
+ goto null_date;
+
+ days= calc_daynr(yearnr,1,1) + daynr - 1;
+ if (days > 0 || days < MAX_DAY_NUMBER) // Day number from year 0 to 9999-12-31
+ {
+ null_value=0;
+ get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
+ if (make_datetime(str, &l_time, DATE_ONLY))
+ return str;
+ }
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+
+void Item_func_add_time::fix_length_and_dec()
+{
+ enum_field_types arg0_field_type;
+ decimals=0;
+ max_length=26*MY_CHARSET_BIN_MB_MAXLEN;
+
+ /*
+ The field type for the result of an Item_func_add_time function is defined as
+ follows:
+
+ - If first arg is a MYSQL_TYPE_DATETIME or MYSQL_TYPE_TIMESTAMP
+ result is MYSQL_TYPE_DATETIME
+ - If first arg is a MYSQL_TYPE_TIME result is MYSQL_TYPE_TIME
+ - Otherwise the result is MYSQL_TYPE_STRING
+ */
+
+ cached_field_type= MYSQL_TYPE_STRING;
+ arg0_field_type= args[0]->field_type();
+ if (arg0_field_type == MYSQL_TYPE_DATE ||
+ arg0_field_type == MYSQL_TYPE_DATETIME ||
+ arg0_field_type == MYSQL_TYPE_TIMESTAMP)
+ cached_field_type= MYSQL_TYPE_DATETIME;
+ else if (arg0_field_type == MYSQL_TYPE_TIME)
+ cached_field_type= MYSQL_TYPE_TIME;
+}
+
+/*
+ ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a time/datetime value
+
+ t: time_or_datetime_expression
+ a: time_expression
+
+ Result: Time value or datetime value
+*/
+
+String *Item_func_add_time::val_str(String *str)
+{
+ TIME l_time1, l_time2, l_time3;
+ bool is_time= 0;
+ long microseconds, seconds, days= 0;
+ int l_sign= sign;
+
+ null_value=0;
+ l_time3.neg= 0;
+ if (is_date) // TIMESTAMP function
+ {
+ if (get_arg0_date(&l_time1,1) ||
+ args[1]->get_time(&l_time2) ||
+ l_time1.time_type == TIMESTAMP_TIME ||
+ l_time2.time_type != TIMESTAMP_TIME)
+ goto null_date;
+ }
+ else // ADDTIME function
+ {
+ if (args[0]->get_time(&l_time1) ||
+ args[1]->get_time(&l_time2) ||
+ l_time2.time_type == TIMESTAMP_FULL)
+ goto null_date;
+ is_time= (l_time1.time_type == TIMESTAMP_TIME);
+ if (is_time && (l_time2.neg == l_time1.neg && l_time1.neg))
+ l_time3.neg= 1;
+ }
+ if (l_time1.neg != l_time2.neg)
+ l_sign= -l_sign;
+
+ microseconds= l_time1.second_part + l_sign*l_time2.second_part;
+ seconds= (l_time1.hour*3600L + l_time1.minute*60L + l_time1.second +
+ (l_time2.day*86400L + l_time2.hour*3600L +
+ l_time2.minute*60L + l_time2.second)*l_sign);
+ if (is_time)
+ seconds+= l_time1.day*86400L;
+ else
+ days+= calc_daynr((uint) l_time1.year,(uint) l_time1.month, (uint) l_time1.day);
+ seconds= seconds + microseconds/1000000L;
+ microseconds= microseconds%1000000L;
+ days+= seconds/86400L;
+ seconds= seconds%86400L;
+
+ if (microseconds < 0)
+ {
+ microseconds+= 1000000L;
+ seconds--;
+ }
+ if (seconds < 0)
+ {
+ days+= seconds/86400L - 1;
+ seconds+= 86400L;
+ }
+ if (days < 0)
+ {
+ if (!is_time)
+ goto null_date;
+ if (microseconds)
+ {
+ microseconds= 1000000L - microseconds;
+ seconds++;
+ }
+ seconds= 86400L - seconds;
+ days= -(++days);
+ l_time3.neg= 1;
+ }
+
+ calc_time_from_sec(&l_time3, seconds, microseconds);
+ if (!is_time)
+ {
+ get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
+ if (l_time3.day &&
+ make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ DATE_TIME_MICROSECOND : DATE_TIME))
+ return str;
+ goto null_date;
+ }
+
+ l_time3.hour+= days*24;
+ if (make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+/*
+ TIMEDIFF(t,s) is a time function that calculates the
+ time value between a start and end time.
+
+ t and s: time_or_datetime_expression
+ Result: Time value
+*/
+
+String *Item_func_timediff::val_str(String *str)
+{
+ longlong seconds;
+ long microseconds;
+ long days;
+ int l_sign= 1;
+ TIME l_time1 ,l_time2, l_time3;
+
+ null_value= 0;
+ if (args[0]->get_time(&l_time1) ||
+ args[1]->get_time(&l_time2) ||
+ l_time1.time_type != l_time2.time_type)
+ goto null_date;
+
+ if (l_time1.neg != l_time2.neg)
+ l_sign= -l_sign;
+
+ if (l_time1.time_type == TIMESTAMP_TIME) // Time value
+ days= l_time1.day - l_sign*l_time2.day;
+ else // DateTime value
+ days= (calc_daynr((uint) l_time1.year,
+ (uint) l_time1.month,
+ (uint) l_time1.day) -
+ l_sign*calc_daynr((uint) l_time2.year,
+ (uint) l_time2.month,
+ (uint) l_time2.day));
+
+ microseconds= l_time1.second_part - l_sign*l_time2.second_part;
+ seconds= ((longlong) days*86400L + l_time1.hour*3600L +
+ l_time1.minute*60L + l_time1.second + microseconds/1000000L -
+ (longlong)l_sign*(l_time2.hour*3600L+l_time2.minute*60L+l_time2.second));
+
+ l_time3.neg= 0;
+ if (seconds < 0)
+ {
+ seconds= -seconds;
+ l_time3.neg= 1;
+ }
+ else if (seconds == 0 && microseconds < 0)
+ {
+ microseconds= -microseconds;
+ l_time3.neg= 1;
+ }
+ if (microseconds < 0)
+ {
+ microseconds+= 1000000L;
+ seconds--;
+ }
+ if ((l_time2.neg == l_time1.neg) && l_time1.neg)
+ l_time3.neg= l_time3.neg ? 0 : 1;
+
+ calc_time_from_sec(&l_time3, seconds, microseconds);
+ if (make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+/*
+ MAKETIME(h,m,s) is a time function that calculates a time value
+ from the total number of hours, minutes, and seconds.
+ Result: Time value
+*/
+
+String *Item_func_maketime::val_str(String *str)
+{
+ TIME ltime;
+
+ long hour= args[0]->val_int();
+ long minute= args[1]->val_int();
+ long second= args[2]->val_int();
+
+ if ((null_value=(args[0]->null_value ||
+ args[1]->null_value ||
+ args[2]->null_value ||
+ minute > 59 || minute < 0 ||
+ second > 59 || second < 0)))
+ goto null_date;
+
+ ltime.neg= 0;
+ if (hour < 0)
+ {
+ ltime.neg= 1;
+ hour= -hour;
+ }
+ ltime.hour= (ulong)hour;
+ ltime.minute= (ulong)minute;
+ ltime.second= (ulong)second;
+ if (make_datetime(str, &ltime, TIME_ONLY))
+ return str;
+
+null_date:
+ return 0;
+}
+
+/*
+ MICROSECOND(a) is a function ( extraction) that extracts the microseconds from a.
+
+ a: Datetime or time value
+ Result: int value
+*/
+longlong Item_func_microsecond::val_int()
+{
+ TIME ltime;
+ if (!get_arg0_time(&ltime))
+ return ltime.second_part;
+ return 0;
+}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 87563cf9f47..20b95f8e22d 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -478,9 +478,10 @@ public:
enum interval_type
{
INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE,
- INTERVAL_SECOND, INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE,
- INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
- INTERVAL_MINUTE_SECOND
+ INTERVAL_SECOND, INTERVAL_MICROSECOND ,INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR,
+ INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE,
+ INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND,
+ INTERVAL_HOUR_MICROSECOND, INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND
};
@@ -556,6 +557,8 @@ class Item_date_typecast :public Item_typecast
{
public:
Item_date_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
+ bool get_date(TIME *ltime, bool fuzzy_date);
const char *func_name() const { return "date"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
Field *tmp_table_field() { return result_field; }
@@ -570,6 +573,8 @@ class Item_time_typecast :public Item_typecast
{
public:
Item_time_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
+ bool get_time(TIME *ltime);
const char *func_name() const { return "time"; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
Field *tmp_table_field() { return result_field; }
@@ -584,6 +589,7 @@ class Item_datetime_typecast :public Item_typecast
{
public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
const char *func_name() const { return "datetime"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field() { return result_field; }
@@ -592,3 +598,106 @@ public:
return (new Field_datetime(maybe_null, name, t_arg, default_charset()));
}
};
+
+class Item_func_makedate :public Item_str_func
+{
+public:
+ Item_func_makedate(Item *a,Item *b) :Item_str_func(a,b) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "makedate"; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
+ }
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+
+class Item_func_add_time :public Item_str_func
+{
+ const bool is_date;
+ int sign;
+ enum_field_types cached_field_type;
+
+public:
+ Item_func_add_time(Item *a, Item *b, bool type_arg, bool neg_arg)
+ :Item_str_func(a, b), is_date(type_arg) { sign= neg_arg ? -1 : 1; }
+ String *val_str(String *str);
+ const char *func_name() const { return "addtime"; }
+ enum_field_types field_type() const { return cached_field_type; }
+ void fix_length_and_dec();
+
+/*
+ TODO:
+ Change this when we support
+ microseconds in TIME/DATETIME
+*/
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ if (cached_field_type == MYSQL_TYPE_TIME)
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
+ else if (cached_field_type == MYSQL_TYPE_DATETIME)
+ return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin));
+ return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+class Item_func_timediff :public Item_str_func
+{
+public:
+ Item_func_timediff(Item *a, Item *b)
+ :Item_str_func(a, b) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "timediff"; }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=17*MY_CHARSET_BIN_MB_MAXLEN;
+ }
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+class Item_func_maketime :public Item_str_func
+{
+public:
+ Item_func_maketime(Item *a, Item *b, Item *c)
+ :Item_str_func(a, b ,c) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "maketime"; }
+ enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
+ }
+ Field *tmp_table_field() { return result_field; }
+ Field *tmp_table_field(TABLE *t_arg)
+ {
+ return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
+ }
+};
+
+class Item_func_microsecond :public Item_int_func
+{
+public:
+ Item_func_microsecond(Item *a) :Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "microsecond"; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ maybe_null=1;
+ }
+};
diff --git a/sql/lex.h b/sql/lex.h
index 064bab8acbb..c2860f4551a 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -116,6 +116,7 @@ static SYMBOL symbols[] = {
{ "DATETIME", SYM(DATETIME),0,0},
{ "DAY", SYM(DAY_SYM),0,0},
{ "DAY_HOUR", SYM(DAY_HOUR_SYM),0,0},
+ { "DAY_MICROSECOND", SYM(DAY_MICROSECOND_SYM),0,0},
{ "DAY_MINUTE", SYM(DAY_MINUTE_SYM),0,0},
{ "DAY_SECOND", SYM(DAY_SECOND_SYM),0,0},
{ "DEC", SYM(DECIMAL_SYM),0,0},
@@ -186,6 +187,7 @@ static SYMBOL symbols[] = {
{ "HELP", SYM(HELP_SYM),0,0},
{ "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0},
{ "HOUR", SYM(HOUR_SYM),0,0},
+ { "HOUR_MICROSECOND", SYM(HOUR_MICROSECOND_SYM),0,0},
{ "HOUR_MINUTE", SYM(HOUR_MINUTE_SYM),0,0},
{ "HOUR_SECOND", SYM(HOUR_SECOND_SYM),0,0},
{ "HOSTS", SYM(HOSTS_SYM),0,0},
@@ -221,6 +223,7 @@ static SYMBOL symbols[] = {
{ "KILL", SYM(KILL_SYM),0,0},
{ "LAST", SYM(LAST_SYM),0,0},
{ "LEADING", SYM(LEADING),0,0},
+ { "LEAVES", SYM(LEAVES),0,0},
{ "LEFT", SYM(LEFT),0,0},
{ "LEVEL", SYM(LEVEL_SYM),0,0},
{ "LIKE", SYM(LIKE),0,0},
@@ -258,9 +261,11 @@ static SYMBOL symbols[] = {
{ "MERGE", SYM(MERGE_SYM),0,0},
{ "MEDIUM", SYM(MEDIUM_SYM),0,0},
{ "MEMORY", SYM(MEMORY_SYM),0,0},
+ { "MICROSECOND", SYM(MICROSECOND_SYM),0,0},
{ "MIDDLEINT", SYM(MEDIUMINT),0,0}, /* For powerbuilder */
{ "MIN_ROWS", SYM(MIN_ROWS),0,0},
{ "MINUTE", SYM(MINUTE_SYM),0,0},
+ { "MINUTE_MICROSECOND", SYM(MINUTE_MICROSECOND_SYM),0,0},
{ "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM),0,0},
{ "MOD", SYM(MOD_SYM),0,0},
{ "MODE", SYM(MODE_SYM),0,0},
@@ -336,6 +341,7 @@ static SYMBOL symbols[] = {
{ "ROWS", SYM(ROWS_SYM),0,0},
{ "RTREE", SYM(RTREE_SYM),0,0},
{ "SECOND", SYM(SECOND_SYM),0,0},
+ { "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM),0,0},
{ "SEPARATOR", SYM(SEPARATOR_SYM),0,0},
{ "SELECT", SYM(SELECT_SYM),0,0},
{ "SERIAL", SYM(SERIAL_SYM),0,0},
@@ -426,14 +432,16 @@ static SYMBOL symbols[] = {
static SYMBOL sql_functions[] = {
{ "ABS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_abs)},
{ "ACOS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_acos)},
- { "ADDDATE", SYM(DATE_ADD_INTERVAL),0,0},
+ { "ADDDATE", SYM(ADDDATE_SYM),0,0},
+ { "ADDTIME", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_addtime)},
{ "AES_ENCRYPT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_encrypt)},
{ "AES_DECRYPT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_decrypt)},
{ "AREA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_area)},
{ "ASIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_asin)},
{ "ASBINARY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkb)},
- { "ASTEXT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_text)},
+ { "ASTEXT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkt)},
{ "ASWKB", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkb)},
+ { "ASWKT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkt)},
{ "ATAN", SYM(ATAN),0,0},
{ "ATAN2", SYM(ATAN),0,0},
{ "BENCHMARK", SYM(BENCHMARK_SYM),0,0},
@@ -468,6 +476,7 @@ static SYMBOL sql_functions[] = {
{ "CURDATE", SYM(CURDATE),0,0},
{ "CURTIME", SYM(CURTIME),0,0},
{ "DATE_ADD", SYM(DATE_ADD_INTERVAL),0,0},
+ { "DATEDIFF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_datediff)},
{ "DATE_FORMAT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_date_format)},
{ "DATE_SUB", SYM(DATE_SUB_INTERVAL),0,0},
{ "DAYNAME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayname)},
@@ -543,6 +552,8 @@ static SYMBOL sql_functions[] = {
{ "LPAD", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)},
{ "LTRIM", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ltrim)},
{ "MAKE_SET", SYM(MAKE_SET_SYM),0,0},
+ { "MAKEDATE", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_makedate)},
+ { "MAKETIME", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_maketime)},
{ "MASTER_POS_WAIT", SYM(MASTER_POS_WAIT),0,0},
{ "MAX", SYM(MAX_SYM),0,0},
{ "MBRCONTAINS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_contains)},
@@ -603,7 +614,7 @@ static SYMBOL sql_functions[] = {
{ "RTRIM", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)},
{ "SEC_TO_TIME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)},
{ "SESSION_USER", SYM(USER),0,0},
- { "SUBDATE", SYM(DATE_SUB_INTERVAL),0,0},
+ { "SUBDATE", SYM(SUBDATE_SYM),0,0},
{ "SIGN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sign)},
{ "SIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sin)},
{ "SHA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
@@ -616,14 +627,17 @@ static SYMBOL sql_functions[] = {
{ "STD", SYM(STD_SYM),0,0},
{ "STDDEV", SYM(STD_SYM),0,0},
{ "STRCMP", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)},
+ { "SUBSTR", SYM(SUBSTRING),0,0},
{ "SUBSTRING", SYM(SUBSTRING),0,0},
{ "SUBSTRING_INDEX", SYM(SUBSTRING_INDEX),0,0},
+ { "SUBTIME", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)},
{ "SUM", SYM(SUM_SYM),0,0},
{ "SYSDATE", SYM(NOW_SYM),0,0},
{ "SYSTEM_USER", SYM(USER),0,0},
{ "TAN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_tan)},
{ "TIME_FORMAT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)},
{ "TIME_TO_SEC", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)},
+ { "TIMEDIFF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_timediff)},
{ "TO_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)},
{ "TOUCHES", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_touches)},
{ "TRIM", SYM(TRIM),0,0},
@@ -637,6 +651,7 @@ static SYMBOL sql_functions[] = {
{ "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM),0,0},
{ "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
+ { "WEEKOFYEAR", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)},
{ "WITHIN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_within)},
{ "X", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_x)},
{ "Y", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_y)},
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 98a877616e0..749732384c7 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -2230,7 +2230,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
}
Item_func_set_user_var e(user_var_name, it);
e.fix_fields(thd, 0, 0);
- e.update_hash(val, val_len, type, charset, Item::COER_NOCOLL);
+ e.update_hash(val, val_len, type, charset, DERIVATION_NONE);
free_root(&thd->mem_root,0);
rli->inc_event_relay_log_pos(get_event_len());
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 432ca533c6a..65451ca40b5 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -224,6 +224,8 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define RAID_BLOCK_SIZE 1024
+#define MY_CHARSET_BIN_MB_MAXLEN 1
+
#ifdef EXTRA_DEBUG
/*
Sync points allow us to force the server to reach a certain line of code
@@ -250,6 +252,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
/* Options to add_table_to_list() */
#define TL_OPTION_UPDATING 1
#define TL_OPTION_FORCE_INDEX 2
+#define TL_OPTION_IGNORE_LEAVES 4
/* Some portable defines */
@@ -402,6 +405,8 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
+int mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
+
bool check_simple_select();
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
@@ -529,6 +534,8 @@ int mysqld_show_fields(THD *thd,TABLE_LIST *table, const char *wild,
bool verbose);
int mysqld_show_keys(THD *thd, TABLE_LIST *table);
int mysqld_show_logs(THD *thd);
+void append_identifier(THD *thd, String *packet, const char *name,
+ uint length);
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1);
int mysqld_show_create(THD *thd, TABLE_LIST *table_list);
@@ -552,6 +559,7 @@ void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used);
bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
void mysql_stmt_execute(THD *thd, char *packet);
void mysql_stmt_free(THD *thd, char *packet);
+void mysql_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter);
@@ -593,6 +601,8 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
extern const Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
find_item_error_report_type report_error);
+key_map get_key_map_from_key_list(TABLE *table,
+ List<String> *index_list);
bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name,
List_iterator<Item> *it);
@@ -763,6 +773,7 @@ extern rw_lock_t LOCK_grant;
extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager;
extern pthread_attr_t connection_attrib;
extern I_List<THD> threads;
+extern I_List<NAMED_LIST> key_caches;
extern MY_BITMAP temp_pool;
extern DATE_FORMAT dayord;
extern String empty_string;
@@ -844,6 +855,7 @@ longlong str_to_datetime(const char *str,uint length,bool fuzzy_date);
timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
bool fuzzy_date);
void localtime_to_TIME(TIME *to, struct tm *from);
+void calc_time_from_sec(TIME *to, long seconds, long microseconds);
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char);
@@ -896,9 +908,10 @@ extern void sql_cache_free();
extern int sql_cache_hit(THD *thd, char *inBuf, uint length);
/* item.cc */
-Item *get_system_var(enum_var_type var_type, LEX_STRING name);
-Item *get_system_var(enum_var_type var_type, const char *var_name, uint length,
- const char *item_name);
+Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
+ LEX_STRING component);
+Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name,
+ uint length, const char *item_name);
/* log.cc */
bool flush_error_log(void);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 39fff130d10..ef2fb78ef80 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -225,6 +225,12 @@ const char *localhost= "localhost", *delayed_user= "DELAYED";
#endif
bool opt_large_files= sizeof(my_off_t) > 4;
+
+/*
+ Used with --help for detailed option
+*/
+bool opt_verbose= 0;
+
arg_cmp_func Arg_comparator::comparator_matrix[4][2] =
{{&Arg_comparator::compare_string, &Arg_comparator::compare_e_string},
{&Arg_comparator::compare_real, &Arg_comparator::compare_e_real},
@@ -312,11 +318,12 @@ const char *sql_mode_str="OFF";
FILE *bootstrap_file;
-I_List <i_string_pair> replicate_rewrite_db;
+I_List<i_string_pair> replicate_rewrite_db;
I_List<i_string> replicate_do_db, replicate_ignore_db;
// allow the user to tell us which db to replicate and which to ignore
I_List<i_string> binlog_do_db, binlog_ignore_db;
I_List<THD> threads,thread_cache;
+I_List<NAMED_LIST> key_caches;
struct system_variables global_system_variables;
struct system_variables max_system_variables;
@@ -875,6 +882,7 @@ void clean_up(bool print_message)
#endif
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
end_key_cache();
+ delete_elements(&key_caches, free_key_cache);
end_thr_alarm(1); /* Free allocated memory */
#ifdef USE_RAID
end_raid();
@@ -1818,15 +1826,28 @@ extern "C" int my_message_sql(uint error, const char *str,
{
THD *thd;
DBUG_ENTER("my_message_sql");
- DBUG_PRINT("error",("Message: '%s'",str));
- if ((thd=current_thd))
+ DBUG_PRINT("error", ("Message: '%s'", str));
+ if ((thd= current_thd))
{
- NET *net= &thd->net;
- net->report_error= 1;
- if (!net->last_error[0]) // Return only first message
+ /*
+ thd->lex.current_select equel to zero if lex structure is not inited
+ (not query command (COM_QUERY))
+ */
+ if (thd->lex.current_select &&
+ thd->lex.current_select->no_error && !thd->is_fatal_error)
+ {
+ DBUG_PRINT("error", ("above error converted to warning"));
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
+ }
+ else
{
- strmake(net->last_error,str,sizeof(net->last_error)-1);
- net->last_errno=error ? error : ER_UNKNOWN_ERROR;
+ NET *net= &thd->net;
+ net->report_error= 1;
+ if (!net->last_error[0]) // Return only first message
+ {
+ strmake(net->last_error, str, sizeof(net->last_error)-1);
+ net->last_errno= error ? error : ER_UNKNOWN_ERROR;
+ }
}
}
else
@@ -1988,22 +2009,6 @@ static int init_common_variables(const char *conf_file_name, int argc,
DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
server_version, SYSTEM_TYPE,MACHINE_TYPE));
-#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
- {
- /* Retrieve used stack size; Needed for checking stack overflows */
- size_t stack_size= 0;
- pthread_attr_getstacksize(&connection_attrib, &stack_size);
- /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
- if (stack_size && stack_size < thread_stack)
- {
- if (global_system_variables.log_warnings)
- sql_print_error("Warning: Asked for %ld thread stack, but got %ld",
- thread_stack, stack_size);
- thread_stack= stack_size;
- }
- }
-#endif
-
#if defined( SET_RLIMIT_NOFILE) || defined( OS2)
/* connections and databases needs lots of files */
{
@@ -2353,6 +2358,21 @@ int main(int argc, char **argv)
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
pthread_attr_setstacksize(&connection_attrib,thread_stack);
+#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
+ {
+ /* Retrieve used stack size; Needed for checking stack overflows */
+ size_t stack_size= 0;
+ pthread_attr_getstacksize(&connection_attrib, &stack_size);
+ /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
+ if (stack_size && stack_size < thread_stack)
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_error("Warning: Asked for %ld thread stack, but got %ld",
+ thread_stack, stack_size);
+ thread_stack= stack_size;
+ }
+ }
+#endif
(void) thr_setconcurrency(concurrency); // 10 by default
select_thread=pthread_self();
@@ -3426,6 +3446,7 @@ enum options
OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT,
OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT,
OPT_OPEN_FILES_LIMIT,
+ OPT_PRELOAD_BUFFER_SIZE,
OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE,
OPT_QUERY_CACHE_TYPE, OPT_RECORD_BUFFER,
OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE,
@@ -3623,6 +3644,9 @@ Disable with --skip-bdb (will save memory).",
#endif /* End HAVE_INNOBASE_DB */
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
+ {"verbose", 'v', "Used with --help option for detailed help",
+ (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+ 0, 0},
{"init-file", OPT_INIT_FILE, "Read SQL commands from this file at startup.",
(gptr*) &opt_init_file, (gptr*) &opt_init_file, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
@@ -3958,8 +3982,6 @@ replicating a LOAD DATA INFILE command.",
0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
- {"version", 'v', "Synonym for option -V.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
- 0, 0, 0, 0},
{"log-warnings", 'W', "Log some not critical warnings to the log file.",
(gptr*) &global_system_variables.log_warnings,
(gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0,
@@ -4090,8 +4112,9 @@ replicating a LOAD DATA INFILE command.",
REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD,
IO_SIZE, 0},
{"key_buffer_size", OPT_KEY_BUFFER_SIZE,
- "The size of the buffer used for index blocks. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.",
- (gptr*) &keybuff_size, (gptr*) &keybuff_size, 0, GET_ULL,
+ "The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.",
+ (gptr*) &keybuff_size, (gptr*) &keybuff_size, 0,
+ (enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR),
REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD,
IO_SIZE, 0},
{"long_query_time", OPT_LONG_QUERY_TIME,
@@ -4234,6 +4257,11 @@ replicating a LOAD DATA INFILE command.",
"If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.",
(gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, 65535, 0, 1, 0},
+ {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE,
+ "The size of the buffer that is allocated when preloading indexes",
+ (gptr*) &global_system_variables.preload_buff_size,
+ (gptr*) &max_system_variables.preload_buff_size, 0, GET_ULONG,
+ REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0},
#ifdef HAVE_QUERY_CACHE
{"query_cache_limit", OPT_QUERY_CACHE_LIMIT,
"Don't cache results that are bigger than this.",
@@ -4552,6 +4580,10 @@ and you are welcome to modify and redistribute it under the GPL license\n\
Starts the MySQL server\n");
printf("Usage: %s [OPTIONS]\n", my_progname);
+ if (!opt_verbose)
+ puts("\nFor more help options (several pages), use mysqld --verbose --help\n");
+ else
+ {
#ifdef __WIN__
puts("NT and Win32 specific options:\n\
--install Install the default service (NT)\n\
@@ -4575,7 +4607,8 @@ Starts the MySQL server\n");
puts("\n\
To see what values a running MySQL server is using, type\n\
-'mysqladmin variables' instead of 'mysqld --help'.");
+'mysqladmin variables' instead of 'mysqld --verbose --help'.\n");
+ }
}
@@ -4660,6 +4693,9 @@ static void mysql_init_variables(void)
my_bind_addr = htonl(INADDR_ANY);
threads.empty();
thread_cache.empty();
+ key_caches.empty();
+ if (!get_or_create_key_cache("default", 7))
+ exit(1);
/* Initialize structures that is used when processing options */
replicate_rewrite_db.empty();
@@ -4847,6 +4883,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
#endif
#include <sslopt-case.h>
case 'v':
+ usage();
+ exit(0);
case 'V':
print_version();
exit(0);
@@ -5290,12 +5328,35 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
return 0;
}
- /* Initiates DEBUG - but no debugging here ! */
+
+
+extern "C" gptr *
+mysql_getopt_value(const char *keyname, uint key_length,
+ const struct my_option *option)
+{
+ if (!key_length)
+ {
+ keyname= "default";
+ key_length= 7;
+ }
+ switch (option->id) {
+ case OPT_KEY_BUFFER_SIZE:
+ {
+ KEY_CACHE *key_cache;
+ if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
+ exit(1);
+ return (gptr*) &key_cache->size;
+ }
+ }
+ return option->value;
+}
+
static void get_options(int argc,char **argv)
{
int ho_error;
+ my_getopt_register_get_addr(mysql_getopt_value);
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(ho_error);
if (argc > 0)
@@ -5338,6 +5399,8 @@ static void get_options(int argc,char **argv)
table_alias_charset= (lower_case_table_names ?
files_charset_info :
&my_charset_bin);
+ /* QQ To be deleted when we have key cache variables in a struct */
+ keybuff_size= (((KEY_CACHE *) find_named(&key_caches, "default", 7))->size);
}
@@ -5552,6 +5615,6 @@ template class I_List<THD>;
template class I_List_iterator<THD>;
template class I_List<i_string>;
template class I_List<i_string_pair>;
-
+template class I_List<NAMED_LIST>;
FIX_GCC_LINKING_PROBLEM
#endif
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index eb4d76bbf6e..fd5e4f1d71a 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -959,5 +959,5 @@ my_net_read(NET *net)
return len;
}
-#endif /* EMBEDDED_LIBRARY */
+#endif /* #ifndef EMBEDDED_LIBRARY */
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc
index 93bae6f444d..25fc010d9a5 100644
--- a/sql/nt_servc.cc
+++ b/sql/nt_servc.cc
@@ -462,7 +462,7 @@ BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType)
{
/* a remove operation */
if (!(service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS )))
- printf("The service doesn't exists!\n");
+ printf("The service doesn't exist!\n");
else
{
SERVICE_STATUS ss;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 6c1c49e23fc..18c465ffde3 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -832,10 +832,10 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
Field *field=((Item_field*) (func->key_item()))->field;
Item_result cmp_type=field->cmp_type();
tree= get_mm_parts(param,field,Item_func::EQ_FUNC,
- func->arguments()[0],cmp_type);
+ func->arguments()[1],cmp_type);
if (!tree)
DBUG_RETURN(tree); // Not key field
- for (uint i=1 ; i < func->argument_count(); i++)
+ for (uint i=2 ; i < func->argument_count(); i++)
{
SEL_TREE *new_tree=get_mm_parts(param,field,Item_func::EQ_FUNC,
func->arguments()[i],cmp_type);
@@ -2637,7 +2637,7 @@ int QUICK_SELECT_DESC::get_next()
else
{
DBUG_ASSERT(range->flag & NEAR_MAX || range_reads_after_key(range));
-#ifdef NOT_IMPLEMENTED_YET
+#ifndef NOT_IMPLEMENTED_YET
result=file->index_read(record, (byte*) range->max_key,
range->max_length,
((range->flag & NEAR_MAX) ?
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 1d730836d6e..1b9256c7723 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -572,7 +572,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
#endif
}
- send_eof(thd);
+ send_eof(thd, 1);
DBUG_RETURN(prepare_for_send(list));
err:
@@ -823,6 +823,13 @@ bool Protocol_simple::store(Field *field)
}
+/*
+ TODO:
+ Second_part format ("%06") needs to change when
+ we support 0-6 decimals for time.
+*/
+
+
bool Protocol_simple::store(TIME *tm)
{
#ifndef DEBUG_OFF
@@ -840,6 +847,8 @@ bool Protocol_simple::store(TIME *tm)
(int) tm->hour,
(int) tm->minute,
(int) tm->second));
+ if (tm->second_part)
+ length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part));
return net_store_data((char*) buff, length);
}
@@ -861,6 +870,12 @@ bool Protocol_simple::store_date(TIME *tm)
}
+/*
+ TODO:
+ Second_part format ("%06") needs to change when
+ we support 0-6 decimals for time.
+*/
+
bool Protocol_simple::store_time(TIME *tm)
{
#ifndef DEBUG_OFF
@@ -876,6 +891,8 @@ bool Protocol_simple::store_time(TIME *tm)
(long) day*24L+(long) tm->hour,
(int) tm->minute,
(int) tm->second));
+ if (tm->second_part)
+ length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part));
return net_store_data((char*) buff, length);
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index f42517a5b0e..cb6c875d513 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -86,9 +86,9 @@ static void fix_net_retry_count(THD *thd, enum_var_type type);
static void fix_max_join_size(THD *thd, enum_var_type type);
static void fix_query_cache_size(THD *thd, enum_var_type type);
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
-static void fix_key_buffer_size(THD *thd, enum_var_type type);
static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type);
static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
+static KEY_CACHE *create_key_cache(const char *name, uint length);
void fix_sql_mode_var(THD *thd, enum_var_type type);
static byte *get_error_count(THD *thd);
static byte *get_warning_count(THD *thd);
@@ -136,9 +136,7 @@ sys_var_thd_ulong sys_interactive_timeout("interactive_timeout",
&SV::net_interactive_timeout);
sys_var_thd_ulong sys_join_buffer_size("join_buffer_size",
&SV::join_buff_size);
-sys_var_ulonglong_ptr sys_key_buffer_size("key_buffer_size",
- &keybuff_size,
- fix_key_buffer_size);
+sys_var_key_buffer_size sys_key_buffer_size("key_buffer_size");
sys_var_bool_ptr sys_local_infile("local_infile",
&opt_local_infile);
sys_var_thd_bool sys_log_warnings("log_warnings", &SV::log_warnings);
@@ -210,6 +208,8 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count",
&SV::net_retry_count,
fix_net_retry_count);
sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
+sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size",
+ &SV::preload_buff_size);
sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
&SV::read_buff_size);
sys_var_bool_ptr sys_readonly("read_only", &opt_readonly);
@@ -423,6 +423,7 @@ sys_var *sys_variables[]=
&sys_net_wait_timeout,
&sys_net_write_timeout,
&sys_new_mode,
+ &sys_preload_buff_size,
&sys_pseudo_thread_id,
&sys_query_cache_size,
#ifdef HAVE_QUERY_CACHE
@@ -602,6 +603,7 @@ struct show_var_st init_vars[]= {
{"log_error", (char*) log_error_file, SHOW_CHAR},
{"port", (char*) &mysqld_port, SHOW_INT},
{"protocol_version", (char*) &protocol_version, SHOW_INT},
+ {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
{sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS},
{sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS},
{sys_readonly.name, (char*) &sys_readonly, SHOW_SYS},
@@ -789,12 +791,6 @@ static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type)
#endif
-static void fix_key_buffer_size(THD *thd, enum_var_type type)
-{
- ha_resize_key_cache();
-}
-
-
void fix_delay_key_write(THD *thd, enum_var_type type)
{
switch ((enum_delay_key_write) delay_key_write_options) {
@@ -866,7 +862,7 @@ bool sys_var_enum::update(THD *thd, set_var *var)
}
-byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
{
return (byte*) enum_names->type_names[*value];
}
@@ -902,7 +898,8 @@ void sys_var_thd_ulong::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
if (type == OPT_GLOBAL)
return (byte*) &(global_system_variables.*offset);
@@ -947,7 +944,8 @@ void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
if (type == OPT_GLOBAL)
return (byte*) &(global_system_variables.*offset);
@@ -990,7 +988,8 @@ void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
if (type == OPT_GLOBAL)
return (byte*) &(global_system_variables.*offset);
@@ -1017,7 +1016,8 @@ void sys_var_thd_bool::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
if (type == OPT_GLOBAL)
return (byte*) &(global_system_variables.*offset);
@@ -1111,7 +1111,7 @@ err:
to create an item that gets the current value at fix_fields() stage.
*/
-Item *sys_var::item(THD *thd, enum_var_type var_type)
+Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
{
if (check_type(var_type))
{
@@ -1127,16 +1127,16 @@ Item *sys_var::item(THD *thd, enum_var_type var_type)
}
switch (type()) {
case SHOW_LONG:
- return new Item_uint((int32) *(ulong*) value_ptr(thd, var_type));
+ return new Item_uint((int32) *(ulong*) value_ptr(thd, var_type, base));
case SHOW_LONGLONG:
- return new Item_int(*(longlong*) value_ptr(thd, var_type));
+ return new Item_int(*(longlong*) value_ptr(thd, var_type, base));
case SHOW_HA_ROWS:
- return new Item_int((longlong) *(ha_rows*) value_ptr(thd, var_type));
+ return new Item_int((longlong) *(ha_rows*) value_ptr(thd, var_type, base));
case SHOW_MY_BOOL:
- return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type),1);
+ return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type, base),1);
case SHOW_CHAR:
{
- char *str= (char*) value_ptr(thd, var_type);
+ char *str= (char*) value_ptr(thd, var_type, base);
return new Item_string(str, strlen(str), system_charset_info);
}
default:
@@ -1165,7 +1165,8 @@ void sys_var_thd_enum::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
ulong tmp= ((type == OPT_GLOBAL) ?
global_system_variables.*offset :
@@ -1182,7 +1183,8 @@ bool sys_var_thd_bit::update(THD *thd, set_var *var)
}
-byte *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
/*
If reverse is 0 (default) return 1 if bit is set.
@@ -1245,6 +1247,7 @@ bool sys_var_collation::check(THD *thd, set_var *var)
return 0;
}
+
bool sys_var_character_set::check(THD *thd, set_var *var)
{
CHARSET_INFO *tmp;
@@ -1270,20 +1273,24 @@ bool sys_var_character_set::check(THD *thd, set_var *var)
return 0;
}
+
bool sys_var_character_set::update(THD *thd, set_var *var)
{
ci_ptr(thd,var->type)[0]= var->save_result.charset;
return 0;
}
-byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type)
+
+byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
CHARSET_INFO *cs= ci_ptr(thd,type)[0];
return cs ? (byte*) cs->csname : (byte*) "NULL";
}
-CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd, enum_var_type type)
+CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd,
+ enum_var_type type)
{
if (type == OPT_GLOBAL)
return &global_system_variables.collation_connection;
@@ -1291,7 +1298,9 @@ CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd, enum_var_type
return &thd->variables.collation_connection;
}
-void sys_var_character_set_connection::set_default(THD *thd, enum_var_type type)
+
+void sys_var_character_set_connection::set_default(THD *thd,
+ enum_var_type type)
{
if (type == OPT_GLOBAL)
global_system_variables.collation_connection= default_charset_info;
@@ -1300,7 +1309,8 @@ void sys_var_character_set_connection::set_default(THD *thd, enum_var_type type)
}
-CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd, enum_var_type type)
+CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd,
+ enum_var_type type)
{
if (type == OPT_GLOBAL)
return &global_system_variables.character_set_client;
@@ -1308,6 +1318,7 @@ CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd, enum_var_type typ
return &thd->variables.character_set_client;
}
+
void sys_var_character_set_client::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1316,6 +1327,7 @@ void sys_var_character_set_client::set_default(THD *thd, enum_var_type type)
thd->variables.character_set_client= global_system_variables.character_set_client;
}
+
CHARSET_INFO ** sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1324,6 +1336,7 @@ CHARSET_INFO ** sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type ty
return &thd->variables.character_set_results;
}
+
void sys_var_character_set_results::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1332,6 +1345,7 @@ void sys_var_character_set_results::set_default(THD *thd, enum_var_type type)
thd->variables.character_set_results= global_system_variables.character_set_results;
}
+
CHARSET_INFO ** sys_var_character_set_server::ci_ptr(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1340,6 +1354,7 @@ CHARSET_INFO ** sys_var_character_set_server::ci_ptr(THD *thd, enum_var_type typ
return &thd->variables.character_set_server;
}
+
void sys_var_character_set_server::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1348,7 +1363,9 @@ void sys_var_character_set_server::set_default(THD *thd, enum_var_type type)
thd->variables.character_set_server= global_system_variables.character_set_server;
}
-CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type type)
+
+CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd,
+ enum_var_type type)
{
if (type == OPT_GLOBAL)
return &global_system_variables.character_set_database;
@@ -1356,6 +1373,7 @@ CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type t
return &thd->variables.character_set_database;
}
+
void sys_var_character_set_database::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1364,6 +1382,7 @@ void sys_var_character_set_database::set_default(THD *thd, enum_var_type type)
thd->variables.character_set_database= thd->db_charset;
}
+
bool sys_var_collation_connection::update(THD *thd, set_var *var)
{
if (var->type == OPT_GLOBAL)
@@ -1373,7 +1392,9 @@ bool sys_var_collation_connection::update(THD *thd, set_var *var)
return 0;
}
-byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type)
+
+byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
CHARSET_INFO *cs= ((type == OPT_GLOBAL) ?
global_system_variables.collation_connection :
@@ -1381,6 +1402,7 @@ byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type)
return cs ? (byte*) cs->name : (byte*) "NULL";
}
+
void sys_var_collation_connection::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1390,6 +1412,71 @@ void sys_var_collation_connection::set_default(THD *thd, enum_var_type type)
}
+bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
+{
+ ulonglong tmp= var->value->val_int();
+ if (!base_name.length)
+ {
+ base_name.str= (char*) "default";
+ base_name.length= 7;
+ }
+ KEY_CACHE *key_cache= (KEY_CACHE*) find_named(&key_caches, base_name.str,
+ base_name.length);
+ if (!key_cache)
+ {
+ if (!tmp) // Tried to delete cache
+ return 0; // Ok, nothing to do
+ if (!(key_cache= create_key_cache(base_name.str,
+ base_name.length)))
+ return 1;
+ }
+ if (!tmp)
+ {
+ /* Delete not default key caches */
+ if (base_name.length != 7 || memcpy(base_name.str, "default", 7))
+ {
+ /*
+ QQ: Here we should move tables using this key cache to default
+ key cache
+ */
+ delete key_cache;
+ return 0;
+ }
+ }
+
+ key_cache->size= (ulonglong) getopt_ull_limit_value(tmp, option_limits);
+
+ /* QQ: Needs to be updated when we have multiple key caches */
+ keybuff_size= key_cache->size;
+ ha_resize_key_cache();
+ return 0;
+}
+
+static ulonglong zero=0;
+
+byte *sys_var_key_buffer_size::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
+{
+ const char *name;
+ uint length;
+
+ if (!base->str)
+ {
+ name= "default";
+ length= 7;
+ }
+ else
+ {
+ name= base->str;
+ length= base->length;
+ }
+ KEY_CACHE *key_cache= (KEY_CACHE*) find_named(&key_caches, name, length);
+ if (!key_cache)
+ return (byte*) &zero;
+ return (byte*) &key_cache->size;
+}
+
+
/*****************************************************************************
Functions to handle SET NAMES and SET CHARACTER SET
@@ -1425,7 +1512,8 @@ void sys_var_timestamp::set_default(THD *thd, enum_var_type type)
}
-byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
thd->sys_var_tmp.long_value= (long) thd->start_time;
return (byte*) &thd->sys_var_tmp.long_value;
@@ -1439,7 +1527,8 @@ bool sys_var_last_insert_id::update(THD *thd, set_var *var)
}
-byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
thd->sys_var_tmp.long_value= (long) thd->insert_id();
return (byte*) &thd->last_insert_id;
@@ -1453,7 +1542,8 @@ bool sys_var_insert_id::update(THD *thd, set_var *var)
}
-byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
return (byte*) &thd->current_insert_id;
}
@@ -1844,7 +1934,8 @@ int set_var_password::update(THD *thd)
Functions to handle sql_mode
****************************************************************************/
-byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
{
ulong val;
char buff[256];
@@ -1941,6 +2032,68 @@ ulong fix_sql_mode(ulong sql_mode)
}
+/****************************************************************************
+ Named list handling
+****************************************************************************/
+
+gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length)
+{
+ I_List_iterator<NAMED_LIST> it(*list);
+ NAMED_LIST *element;
+ while ((element= it++))
+ {
+ if (element->cmp(name, length))
+ return element->data;
+ }
+ return 0;
+}
+
+
+void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr))
+{
+ NAMED_LIST *element;
+ while ((element= list->get()))
+ {
+ (*free_element)(element->data);
+ delete element;
+ }
+}
+
+
+/* Key cache functions */
+
+static KEY_CACHE *create_key_cache(const char *name, uint length)
+{
+ KEY_CACHE *key_cache;
+ DBUG_PRINT("info",("Creating key cache: %s", name));
+ if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE),
+ MYF(MY_ZEROFILL | MY_WME))))
+ {
+ if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache))
+ {
+ my_free((char*) key_cache, MYF(0));
+ key_cache= 0;
+ }
+ }
+ return key_cache;
+}
+
+
+KEY_CACHE *get_or_create_key_cache(const char *name, uint length)
+{
+ KEY_CACHE *key_cache= (KEY_CACHE*) find_named(&key_caches, name,
+ length);
+ if (!key_cache)
+ key_cache= create_key_cache(name, length);
+ return key_cache;
+}
+
+
+void free_key_cache(gptr key_cache)
+{
+ my_free(key_cache, MYF(0));
+}
+
/****************************************************************************
Used templates
@@ -1949,4 +2102,5 @@ ulong fix_sql_mode(ulong sql_mode)
#ifdef __GNUC__
template class List<set_var_base>;
template class List_iterator_fast<set_var_base>;
+template class I_List_iterator<NAMED_LIST>;
#endif
diff --git a/sql/set_var.h b/sql/set_var.h
index 5a0fbd21809..978aba3384a 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -47,12 +47,18 @@ public:
struct my_option *option_limits; /* Updated by by set_var_init() */
uint name_length; /* Updated by by set_var_init() */
const char *name;
+ LEX_STRING base_name; /* for structs */
+
sys_after_update_func after_update;
sys_var(const char *name_arg) :name(name_arg),after_update(0)
- {}
+ {
+ base_name.length=0;
+ }
sys_var(const char *name_arg,sys_after_update_func func)
:name(name_arg),after_update(func)
- {}
+ {
+ base_name.length=0;
+ }
virtual ~sys_var() {}
virtual bool check(THD *thd, set_var *var) { return 0; }
bool check_enum(THD *thd, set_var *var, TYPELIB *enum_names);
@@ -60,14 +66,16 @@ public:
virtual bool update(THD *thd, set_var *var)=0;
virtual void set_default(THD *thd, enum_var_type type) {}
virtual SHOW_TYPE type() { return SHOW_UNDEF; }
- virtual byte *value_ptr(THD *thd, enum_var_type type) { return 0; }
+ virtual byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ { return 0; }
virtual bool check_type(enum_var_type type)
{ return type != OPT_GLOBAL; } /* Error if not GLOBAL */
virtual bool check_update_type(Item_result type)
{ return type != INT_RESULT; } /* Assume INT */
virtual bool check_default(enum_var_type type)
{ return option_limits == 0; }
- Item *item(THD *thd, enum_var_type type);
+ Item *item(THD *thd, enum_var_type type, LEX_STRING *base);
+ virtual bool is_struct() { return 0; }
};
@@ -83,7 +91,8 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_LONG; }
- byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ { return (byte*) value; }
};
@@ -99,7 +108,8 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_LONGLONG; }
- byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ { return (byte*) value; }
};
@@ -117,7 +127,8 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_MY_BOOL; }
- byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ { return (byte*) value; }
bool check_update_type(Item_result type) { return 0; }
};
@@ -149,7 +160,8 @@ public:
(*set_default_func)(thd, type);
}
SHOW_TYPE type() { return SHOW_CHAR; }
- byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
+ { return (byte*) value; }
bool check_update_type(Item_result type)
{
return type != STRING_RESULT; /* Only accept strings */
@@ -173,7 +185,7 @@ public:
}
bool update(THD *thd, set_var *var);
SHOW_TYPE type() { return SHOW_CHAR; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
bool check_update_type(Item_result type) { return 0; }
};
@@ -209,7 +221,7 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_LONG; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
class sys_var_pseudo_thread_id :public sys_var_thd_ulong
@@ -236,7 +248,7 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_HA_ROWS; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -256,7 +268,7 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_LONGLONG; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
bool check_default(enum_var_type type)
{
return type == OPT_GLOBAL && !option_limits;
@@ -282,7 +294,7 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_MY_BOOL; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
bool check(THD *thd, set_var *var)
{
return check_enum(thd, var, &bool_typelib);
@@ -313,7 +325,7 @@ public:
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_CHAR; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
bool check_update_type(Item_result type) { return 0; }
};
@@ -332,7 +344,7 @@ public:
return check_set(thd, var, enum_names);
}
void set_default(THD *thd, enum_var_type type);
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -355,7 +367,7 @@ public:
bool check_update_type(Item_result type) { return 0; }
bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
SHOW_TYPE type() { return SHOW_MY_BOOL; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -370,7 +382,7 @@ public:
bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
bool check_default(enum_var_type type) { return 0; }
SHOW_TYPE type() { return SHOW_LONG; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -381,7 +393,7 @@ public:
bool update(THD *thd, set_var *var);
bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
SHOW_TYPE type() { return SHOW_LONGLONG; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -392,7 +404,7 @@ public:
bool update(THD *thd, set_var *var);
bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
SHOW_TYPE type() { return SHOW_LONGLONG; }
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -456,7 +468,7 @@ SHOW_TYPE type() { return SHOW_CHAR; }
}
bool check_default(enum_var_type type) { return 0; }
bool update(THD *thd, set_var *var);
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
virtual void set_default(THD *thd, enum_var_type type)= 0;
virtual CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type)= 0;
};
@@ -513,9 +525,24 @@ public:
sys_var_collation_connection(const char *name_arg) :sys_var_collation(name_arg) {}
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
- byte *value_ptr(THD *thd, enum_var_type type);
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
+
+class sys_var_key_buffer_size :public sys_var
+{
+public:
+ sys_var_key_buffer_size(const char *name_arg)
+ :sys_var(name_arg)
+ {}
+ bool update(THD *thd, set_var *var);
+ SHOW_TYPE type() { return SHOW_LONGLONG; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+ bool check_default(enum_var_type type) { return 1; }
+ bool is_struct() { return 1; }
+};
+
+
/* Variable that you can only read from */
class sys_var_readonly: public sys_var
@@ -534,7 +561,7 @@ public:
bool check_default(enum_var_type type) { return 1; }
bool check_type(enum_var_type type) { return type != var_type; }
bool check_update_type(Item_result type) { return 1; }
- byte *value_ptr(THD *thd, enum_var_type type)
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
{
return (*value_ptr_func)(thd);
}
@@ -639,6 +666,33 @@ public:
};
+/* Named lists (used for keycaches) */
+
+class NAMED_LIST :public ilink
+{
+ const char *name;
+ uint name_length;
+public:
+ gptr data;
+
+ NAMED_LIST(I_List<NAMED_LIST> *links, const char *name_arg,
+ uint name_length_arg, gptr data_arg):
+ name_length(name_length_arg), data(data_arg)
+ {
+ name=my_strdup(name_arg,MYF(MY_WME));
+ links->push_back(this);
+ }
+ inline bool cmp(const char *name_cmp, uint length)
+ {
+ return length == name_length && !memcmp(name, name_cmp, length);
+ }
+ ~NAMED_LIST()
+ {
+ my_free((char*) name, MYF(0));
+ }
+};
+
+
/*
Prototypes for helper functions
*/
@@ -649,6 +703,11 @@ sys_var *find_sys_var(const char *str, uint length=0);
int sql_set_variables(THD *thd, List<set_var_base> *var_list);
void fix_delay_key_write(THD *thd, enum_var_type type);
ulong fix_sql_mode(ulong sql_mode);
-
extern sys_var_str sys_charset_system;
CHARSET_INFO *get_old_charset_by_name(const char *old_name);
+gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length);
+void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr));
+
+/* key_cache functions */
+KEY_CACHE *get_or_create_key_cache(const char *name, uint length);
+void free_key_cache(gptr key_cache);
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 273dfa0fcf5..6f42243ba2b 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -16,8 +16,8 @@ v/*
"ANO",
"Nemohu vytvo-Bøit soubor '%-.64s' (chybový kód: %d)",
"Nemohu vytvo-Bøit tabulku '%-.64s' (chybový kód: %d)",
-"Nemohu vytvo-Bøit databázi '%-.64s', chyba %d",
-"Nemohu vytvo-Bøit databázi '%-.64s', databáze ji¾ existuje",
+"Nemohu vytvo-Bøit databázi '%-.64s' (chybový kód: %d)",
+"Nemohu vytvo-Bøit databázi '%-.64s'; databáze ji¾ existuje",
"Nemohu zru-B¹it databázi '%-.64s', databáze neexistuje",
"Chyba p-Bøi ru¹ení databáze (nemohu vymazat '%-.64s', chyba %d)",
"Chyba p-Bøi ru¹ení databáze (nemohu vymazat adresáø '%-.64s', chyba %d)",
@@ -44,8 +44,8 @@ v/*
"Obsluha tabulky '%-.64s' nem-Bá tento parametr",
"Nemohu naj-Bít záznam v '%-.64s'",
"Nespr-Bávná informace v souboru '%-.64s'",
-"Nespr-Bávný klíè pro tabulku '%-.64s'. Pokuste se ho opravit",
-"Star-Bý klíèový soubor pro '%-.64s'. Opravte ho.",
+"Nespr-Bávný klíè pro tabulku '%-.64s'; pokuste se ho opravit",
+"Star-Bý klíèový soubor pro '%-.64s'; opravte ho.",
"'%-.64s' je jen pro -Bètení",
"M-Bálo pamìti. Pøestartujte daemona a zkuste znovu (je potøeba %d bytù)",
"M-Bálo pamìti pro tøídìní. Zvy¹te velikost tøídícího bufferu",
@@ -222,7 +222,7 @@ v/*
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -259,7 +259,7 @@ v/*
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -273,3 +273,6 @@ v/*
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 1d39a328154..25a5020a30f 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -10,22 +10,22 @@
"JA",
"Kan ikke oprette filen '%-.64s' (Fejlkode: %d)",
"Kan ikke oprette tabellen '%-.64s' (Fejlkode: %d)",
-"Kan ikke oprette databasen '%-.64s'. Fejl %d",
-"Kan ikke oprette databasen '%-.64s'. Databasen eksisterer",
-"Kan ikke slette (droppe) '%-.64s'. Databasen eksisterer ikke",
-"Fejl ved sletning (drop) af databasen (kan ikke slette '%-.64s', Fejl %d)",
-"Fejl ved sletting af database (kan ikke slette folderen '%-.64s', Fejl %d)",
+"Kan ikke oprette databasen '%-.64s' (Fejlkode: %d)",
+"Kan ikke oprette databasen '%-.64s'; databasen eksisterer",
+"Kan ikke slette (droppe) '%-.64s'; databasen eksisterer ikke",
+"Fejl ved sletning (drop) af databasen (kan ikke slette '%-.64s', Fejlkode %d)",
+"Fejl ved sletting af database (kan ikke slette folderen '%-.64s', Fejlkode %d)",
"Fejl ved sletning af '%-.64s' (Fejlkode: %d)",
"Kan ikke læse posten i systemfolderen",
"Kan ikke læse status af '%-.64s' (Fejlkode: %d)",
"Kan ikke læse aktive folder (Fejlkode: %d)",
"Kan ikke låse fil (Fejlkode: %d)",
-"Kan ikke åbne fil: '%-.64s'. (Fejlkode: %d)",
+"Kan ikke åbne fil: '%-.64s' (Fejlkode: %d)",
"Kan ikke finde fila: '%-.64s' (Fejlkode: %d)",
"Kan ikke læse folder '%-.64s' (Fejlkode: %d)",
"Kan ikke skifte folder til '%-.64s' (Fejlkode: %d)",
"Posten er ændret siden sidste læsning '%-.64s'",
-"Ikke mere diskplads (%s). Venter på at få frigjort plads....",
+"Ikke mere diskplads (%s). Venter på at få frigjort plads...",
"Kan ikke skrive, flere ens nøgler i tabellen '%-.64s'",
"Fejl ved lukning af '%-.64s' (Fejlkode: %d)",
"Fejl ved læsning af '%-.64s' (Fejlkode: %d)",
@@ -38,8 +38,8 @@
"Denne mulighed eksisterer ikke for tabeltypen '%-.64s'",
"Kan ikke finde posten i '%-.64s'",
"Forkert indhold i: '%-.64s'",
-"Fejl i indeksfilen til tabellen '%-.64s', prøv at reparere den",
-"Gammel indeksfil for tabellen '%-.64s'; Reparer den",
+"Fejl i indeksfilen til tabellen '%-.64s'; prøv at reparere den",
+"Gammel indeksfil for tabellen '%-.64s'; reparer den",
"'%-.64s' er skrivebeskyttet",
"Ikke mere hukommelse. Genstart serveren og prøv igen (mangler %d bytes)",
"Ikke mere sorteringshukommelse. Øg sorteringshukommelse (sort buffer size) for serveren",
@@ -216,7 +216,7 @@
"CREATE DATABASE er ikke tilladt mens en tråd holder på globalt read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -253,7 +253,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -267,3 +267,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 5b79f06b621..6aba93c246c 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -19,8 +19,8 @@
"Kan file '%-.64s' niet aanmaken (Errcode: %d)",
"Kan tabel '%-.64s' niet aanmaken (Errcode: %d)",
"Kan database '%-.64s' niet aanmaken (Errcode: %d)",
-"Kan database '%-.64s' niet aanmaken. Database bestaat reeds",
-"Kan database '%-.64s' niet verwijderen. Database bestaat niet",
+"Kan database '%-.64s' niet aanmaken; database bestaat reeds",
+"Kan database '%-.64s' niet verwijderen; database bestaat niet",
"Fout bij verwijderen database (kan '%-.64s' niet verwijderen, Errcode: %d)",
"Fout bij verwijderen database (kan rmdir '%-.64s' niet uitvoeren, Errcode: %d)",
"Fout bij het verwijderen van '%-.64s' (Errcode: %d)",
@@ -28,8 +28,8 @@
"Kan de status niet krijgen van '%-.64s' (Errcode: %d)",
"Kan de werkdirectory niet krijgen (Errcode: %d)",
"Kan de file niet blokeren (Errcode: %d)",
-"Kan de file '%-.64s' niet openen. (Errcode: %d)",
-"Kan de file: '%-.64s' niet vinden. (Errcode: %d)",
+"Kan de file '%-.64s' niet openen (Errcode: %d)",
+"Kan de file: '%-.64s' niet vinden (Errcode: %d)",
"Kan de directory niet lezen van '%-.64s' (Errcode: %d)",
"Kan de directory niet veranderen naar '%-.64s' (Errcode: %d)",
"Record is veranderd sinds de laatste lees activiteit in de tabel '%-.64s'",
@@ -46,8 +46,8 @@
"Tabel handler voor '%-.64s' heeft deze optie niet",
"Kan record niet vinden in '%-.64s'",
"Verkeerde info in file: '%-.64s'",
-"Verkeerde zoeksleutel file voor tabel: '%-.64s'. Probeer het te repareren",
-"Oude zoeksleutel file voor tabel '%-.64s'; Repareer het!",
+"Verkeerde zoeksleutel file voor tabel: '%-.64s'; probeer het te repareren",
+"Oude zoeksleutel file voor tabel '%-.64s'; repareer het!",
"'%-.64s' is alleen leesbaar",
"Geen geheugen meer. Herstart server en probeer opnieuw (%d bytes nodig)",
"Geen geheugen om te sorteren. Verhoog de server sort buffer size",
@@ -224,7 +224,7 @@
"CREATE DATABASE niet toegestaan terwijl thread een globale 'read lock' bezit",
"Foutieve parameters voor %s",
"%-.32s@%-.64s mag geen nieuwe gebruikers creeren",
-"Incorrecte tabel definitie; Alle MERGE tabellen moeten tot dezelfde database behoren",
+"Incorrecte tabel definitie; alle MERGE tabellen moeten tot dezelfde database behoren",
"Deadlock gevonden tijdens lock-aanvraag poging; Probeer herstart van de transactie",
"Het gebruikte tabel type ondersteund geen FULLTEXT indexen",
"Kan foreign key beperking niet toevoegen",
@@ -261,7 +261,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -275,3 +275,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index f15e063c487..57336647f2a 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -7,9 +7,9 @@
"YES",
"Can't create file '%-.64s' (errno: %d)",
"Can't create table '%-.64s' (errno: %d)",
-"Can't create database '%-.64s'. (errno: %d)",
-"Can't create database '%-.64s'. Database exists",
-"Can't drop database '%-.64s'. Database doesn't exist",
+"Can't create database '%-.64s' (errno: %d)",
+"Can't create database '%-.64s'; database exists",
+"Can't drop database '%-.64s'; database doesn't exist",
"Error dropping database (can't delete '%-.64s', errno: %d)",
"Error dropping database (can't rmdir '%-.64s', errno: %d)",
"Error on delete of '%-.64s' (errno: %d)",
@@ -17,12 +17,12 @@
"Can't get status of '%-.64s' (errno: %d)",
"Can't get working directory (errno: %d)",
"Can't lock file (errno: %d)",
-"Can't open file: '%-.64s'. (errno: %d)",
+"Can't open file: '%-.64s' (errno: %d)",
"Can't find file: '%-.64s' (errno: %d)",
"Can't read dir of '%-.64s' (errno: %d)",
"Can't change dir to '%-.64s' (errno: %d)",
"Record has changed since last read in table '%-.64s'",
-"Disk full (%s). Waiting for someone to free some space....",
+"Disk full (%s). Waiting for someone to free some space...",
"Can't write, duplicate key in table '%-.64s'",
"Error on close of '%-.64s' (errno: %d)",
"Error reading file '%-.64s' (errno: %d)",
@@ -35,8 +35,8 @@
"Table storage engine for '%-.64s' doesn't have this option",
"Can't find record in '%-.64s'",
"Incorrect information in file: '%-.64s'",
-"Incorrect key file for table: '%-.64s'. Try to repair it",
-"Old key file for table '%-.64s'; Repair it!",
+"Incorrect key file for table: '%-.64s'; try to repair it",
+"Old key file for table '%-.64s'; repair it!",
"Table '%-.64s' is read only",
"Out of memory. Restart daemon and try again (needed %d bytes)",
"Out of sort memory. Increase daemon sort buffer size",
@@ -85,12 +85,12 @@
"Can't create IP socket",
"Table '%-.64s' has no index like the one used in CREATE INDEX. Recreate the table",
"Field separator argument is not what is expected. Check the manual",
-"You can't use fixed rowlength with BLOBs. Please use 'fields terminated by'.",
+"You can't use fixed rowlength with BLOBs. Please use 'fields terminated by'",
"The file '%-.64s' must be in the database directory or be readable by all",
"File '%-.80s' already exists",
"Records: %ld Deleted: %ld Skipped: %ld Warnings: %ld",
"Records: %ld Duplicates: %ld",
-"Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the store engine doesn't support unique sub keys",
+"Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the storage engine doesn't support unique sub keys",
"You can't delete all columns with ALTER TABLE. Use DROP TABLE instead",
"Can't DROP '%-.64s'. Check that column/key exists",
"Records: %ld Duplicates: %ld Warnings: %ld",
@@ -145,7 +145,7 @@
"There is no such grant defined for user '%-.32s' on host '%-.64s'",
"%-.16s command denied to user: '%-.32s@%-.64s' for table '%-.64s'",
"%-.16s command denied to user: '%-.32s@%-.64s' for column '%-.64s' in table '%-.64s'",
-"Illegal GRANT/REVOKE command. Please consult the manual which privileges can be used.",
+"Illegal GRANT/REVOKE command. Please consult the manual which privileges can be used",
"The host or user argument to GRANT is too long",
"Table '%-.64s.%-.64s' doesn't exist",
"There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'",
@@ -186,7 +186,7 @@
"Got error %d during FLUSH_LOGS",
"Got error %d during CHECKPOINT",
"Aborted connection %ld to db: '%-.64s' user: '%-.32s' host: `%-.64s' (%-.64s)",
-"The store engine for the table does not support binary table dump",
+"The storage engine for the table does not support binary table dump",
"Binlog closed, cannot RESET MASTER",
"Failed rebuilding the index of dumped table '%-.64s'",
"Error from master: '%-.64s'",
@@ -213,7 +213,7 @@
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -250,7 +250,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client"
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client"
"All parts of a SPATIAL KEY must be NOT NULL"
"COLLATION '%s' is not valid for CHARACTER SET '%s'"
"The slave was already running"
@@ -269,3 +269,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 506b5fc0188..94e19fc6e9d 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -12,7 +12,7 @@
"JAH",
"Ei suuda luua faili '%-.64s' (veakood: %d)",
"Ei suuda luua tabelit '%-.64s' (veakood: %d)",
-"Ei suuda luua andmebaasi '%-.64s'. (veakood: %d)",
+"Ei suuda luua andmebaasi '%-.64s' (veakood: %d)",
"Ei suuda luua andmebaasi '%-.64s': andmebaas juba eksisteerib",
"Ei suuda kustutada andmebaasi '%-.64s': andmebaasi ei eksisteeri",
"Viga andmebaasi kustutamisel (ei suuda kustutada faili '%-.64s', veakood: %d)",
@@ -22,7 +22,7 @@
"Ei suuda lugeda '%-.64s' olekut (veakood: %d)",
"Ei suuda identifitseerida jooksvat kataloogi (veakood: %d)",
"Ei suuda lukustada faili (veakood: %d)",
-"Ei suuda avada faili '%-.64s'. (veakood: %d)",
+"Ei suuda avada faili '%-.64s' (veakood: %d)",
"Ei suuda leida faili '%-.64s' (veakood: %d)",
"Ei suuda lugeda kataloogi '%-.64s' (veakood: %d)",
"Ei suuda siseneda kataloogi '%-.64s' (veakood: %d)",
@@ -40,8 +40,8 @@
"Tabeli '%-.64s' handler ei toeta antud operatsiooni",
"Ei suuda leida kirjet '%-.64s'-s",
"Vigane informatsioon failis '%-.64s'",
-"Tabeli '%-.64s' võtmefail on vigane; Proovi seda parandada",
-"Tabeli '%-.64s' võtmefail on aegunud; Paranda see!",
+"Tabeli '%-.64s' võtmefail on vigane; proovi seda parandada",
+"Tabeli '%-.64s' võtmefail on aegunud; paranda see!",
"Tabel '%-.64s' on ainult lugemiseks",
"Mälu sai otsa. Proovi MySQL uuesti käivitada (puudu jäi %d baiti)",
"Mälu sai sorteerimisel otsa. Suurenda MySQL-i sorteerimispuhvrit",
@@ -255,7 +255,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -269,3 +269,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 8882e4dceda..dd062cc074a 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -7,9 +7,9 @@
"OUI",
"Ne peut créer le fichier '%-.64s' (Errcode: %d)",
"Ne peut créer la table '%-.64s' (Errcode: %d)",
-"Ne peut créer la base '%-.64s'. Erreur %d",
-"Ne peut créer la base '%-.64s'. Elle existe déjà",
-"Ne peut effacer la base '%-.64s'. Elle n'existe pas",
+"Ne peut créer la base '%-.64s' (Erreur %d)",
+"Ne peut créer la base '%-.64s'; elle existe déjà",
+"Ne peut effacer la base '%-.64s'; elle n'existe pas",
"Ne peut effacer la base '%-.64s' (erreur %d)",
"Erreur en effaçant la base (rmdir '%-.64s', erreur %d)",
"Erreur en effaçant '%-.64s' (Errcode: %d)",
@@ -17,7 +17,7 @@
"Ne peut obtenir le status de '%-.64s' (Errcode: %d)",
"Ne peut obtenir le répertoire de travail (Errcode: %d)",
"Ne peut verrouiller le fichier (Errcode: %d)",
-"Ne peut ouvrir le fichier: '%-.64s'. (Errcode: %d)",
+"Ne peut ouvrir le fichier: '%-.64s' (Errcode: %d)",
"Ne peut trouver le fichier: '%-.64s' (Errcode: %d)",
"Ne peut lire le répertoire de '%-.64s' (Errcode: %d)",
"Ne peut changer le répertoire pour '%-.64s' (Errcode: %d)",
@@ -35,8 +35,8 @@
"Le handler de la table '%-.64s' n'a pas cette option",
"Ne peut trouver l'enregistrement dans '%-.64s'",
"Information erronnée dans le fichier: '%-.64s'",
-"Index corrompu dans la table: '%-.64s'. Essayez de le réparer",
-"Vieux fichier d'index pour la table '%-.64s'; Réparez le!",
+"Index corrompu dans la table: '%-.64s'; essayez de le réparer",
+"Vieux fichier d'index pour la table '%-.64s'; réparez le!",
"'%-.64s' est en lecture seulement",
"Manque de mémoire. Redémarrez le démon et ré-essayez (%d octets nécessaires)",
"Manque de mémoire pour le tri. Augmentez-la.",
@@ -213,7 +213,7 @@
"CREATE DATABASE n'est pas autorisée pendant qu'une tâche possède un verrou global en lecture",
"Mauvais arguments à %s",
"%-.32s@%-.64s n'est pas autorisé à créer de nouveaux utilisateurs",
-"Définition de table incorrecte : toutes les tables MERGE doivent être dans la même base de donnée",
+"Définition de table incorrecte; toutes les tables MERGE doivent être dans la même base de donnée",
"Deadlock découvert en essayant d'obtenir les verrous : essayez de redémarrer la transaction",
"Le type de table utilisé ne supporte pas les index FULLTEXT",
"Impossible d'ajouter des contraintes d'index externe",
@@ -250,7 +250,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -264,3 +264,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 1e8f5bb2c05..e7cdf3f6f0d 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -14,11 +14,11 @@
"isamchk",
"Nein",
"Ja",
-"Kann Datei '%-.64s' nicht erzeugen. (Fehler: %d)",
-"Kann Tabelle '%-.64s' nicht erzeugen. (Fehler: %d)",
-"Kann Datenbank '%-.64s' nicht erzeugen. (Fehler: %d)",
-"Kann Datenbank '%-.64s' nicht erzeugen. Datenbank '%-.64s' existiert bereits.",
-"Kann Datenbank '%-.64s' nicht löschen. Keine Datenbank '%-.64s' vorhanden.",
+"Kann Datei '%-.64s' nicht erzeugen (Fehler: %d)",
+"Kann Tabelle '%-.64s' nicht erzeugen (Fehler: %d)",
+"Kann Datenbank '%-.64s' nicht erzeugen (Fehler: %d)",
+"Kann Datenbank '%-.64s' nicht erzeugen; datenbank '%-.64s' existiert bereits.",
+"Kann Datenbank '%-.64s' nicht löschen; keine Datenbank '%-.64s' vorhanden.",
"Fehler beim Löschen der Datenbank. ('%-.64s' kann nicht gelöscht werden, Fehlernuumer: %d)",
"Fehler beim Löschen der Datenbank. (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehlernummer: %d)",
"Fehler beim Löschen von '%-.64s'. (Fehler: %d)",
@@ -26,27 +26,27 @@
"Kann Status von '%-.64s' nicht ermitteln. (Fehler: %d)",
"Kann Arbeitsverzeichnis nicht ermitteln. (Fehler: %d)",
"Datei nicht sperrbar. (Fehler: %d)",
-"Kann Datei '%-.64s' nicht öffnen. (Fehler: %d)",
-"Kann Datei '%-.64s' nicht finden. (Fehler: %d)",
-"Verzeichnis von '%-.64s' nicht lesbar. (Fehler: %d)",
-"Kann nicht in das Verzeichnis '%-.64s' wechseln. (Fehler: %d)",
-"Datensatz hat sich seit dem letzten Zugriff auf Tabelle '%-.64s' geändert.",
+"Kann Datei '%-.64s' nicht öffnen (Fehler: %d)",
+"Kann Datei '%-.64s' nicht finden (Fehler: %d)",
+"Verzeichnis von '%-.64s' nicht lesbar (Fehler: %d)",
+"Kann nicht in das Verzeichnis '%-.64s' wechseln (Fehler: %d)",
+"Datensatz hat sich seit dem letzten Zugriff auf Tabelle '%-.64s' geändert",
"Festplatte voll (%-.64s). Warte bis jemand Platz schafft ...",
-"Kann nicht speichern, doppelter Schlüssel in Tabelle '%-.64s'.",
-"Fehler beim Schließen von '%-.64s'. (Fehler: %d)",
-"Fehler beim Lesen der Datei '%-.64s'. (Fehler: %d)",
-"Fehler beim Umbenennen von '%-.64s' nach '%-.64s'. (Fehler: %d)",
-"Fehler beim Speichern der Datei '%-.64s'. (Fehler: %d)",
-"'%-.64s' ist für Veränderungen gesperrt.",
-"Sortieren abgebrochen.",
-"View '%-.64s' existiert für '%-.64s' nicht.",
-"Fehler %d. (Tabellenhandler)",
-"Diese Option gibt es nicht. (Tabellenhandler)",
-"Kann Datensatz nicht finden.",
+"Kann nicht speichern, doppelter Schlüssel in Tabelle '%-.64s'",
+"Fehler beim Schließen von '%-.64s' (Fehler: %d)",
+"Fehler beim Lesen der Datei '%-.64s' (Fehler: %d)",
+"Fehler beim Umbenennen von '%-.64s' nach '%-.64s' (Fehler: %d)",
+"Fehler beim Speichern der Datei '%-.64s' (Fehler: %d)",
+"'%-.64s' ist für Veränderungen gesperrt",
+"Sortieren abgebrochen",
+"View '%-.64s' existiert für '%-.64s' nicht",
+"Fehler %d (Tabellenhandler)",
+"Diese Option gibt es nicht (Tabellenhandler)",
+"Kann Datensatz nicht finden",
"Falsche Information in Datei: '%-.64s'",
-"Falsche Schlüssel-Datei für Tabelle '%-.64s'. Versuche zu reparieren!",
-"Alte Schlüssel-Datei für Tabelle '%-.64s'. Repariere!",
-"'%-.64s' ist nur lesbar.",
+"Falsche Schlüssel-Datei für Tabelle '%-.64s'; versuche zu reparieren!",
+"Alte Schlüssel-Datei für Tabelle '%-.64s'; repariere!",
+"'%-.64s' ist nur lesbar",
"Kein Speicher vorhanden (benötigt %d bytes). Server neu starten.",
"Kein Speicher zum Sortieren. sort_buffer_size sollte erhöht werden.",
"Unerwartetes Ende beim Lesen der Datei '%-.64s'. (Fehler: %d)",
@@ -222,7 +222,7 @@
"Solange ein globaler Read LOCK gesetzt ist, ist CREATE DATABASE nicht zulässig.",
"Falsche Argumente für %s",
"%-.32s@%-.64s is nicht berechtigt neue Benutzer hinzuzufügen.",
-"Falsche Tabellendefinition: Sämtliche MERGE-Tabellen müssen in derselben Datenbank sein.",
+"Falsche Tabellendefinition; sämtliche MERGE-Tabellen müssen in derselben Datenbank sein.",
"Beim Versuch einen Lock anzufordern ist ein Deadlock aufgetreten. Es wird versucht die Transaktion erneut zu starten.",
"Der verwendete Tabellentyp unterstützt keinen FULLTEXT-Index.",
"Foreign_Key Beschränkung konnte nicht hinzugefügt werden.",
@@ -259,7 +259,7 @@
"Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden.",
"Select %u wurde während der Optimierung reduziert.",
"Tabelle '%-.64s', die in einem der SELECT-Befehle verwendet wurde kann nicht in %-.32s verwendet werden",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -273,3 +273,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index d322f3fbd6a..ef423ae2758 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -7,8 +7,8 @@
"ÍÁÉ",
"Áäýíáôç ç äçìéïõñãßá ôïõ áñ÷åßïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)",
"Áäýíáôç ç äçìéïõñãßá ôïõ ðßíáêá '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Áäýíáôç ç äçìéïõñãßá ôçò âÜóçò äåäïìÝíùí '%-.64s'. (êùäéêüò ëÜèïõò: %d)",
-"Áäýíáôç ç äçìéïõñãßá ôçò âÜóçò äåäïìÝíùí '%-.64s'. Ç âÜóç äåäïìÝíùí õðÜñ÷åé Þäç",
+"Áäýíáôç ç äçìéïõñãßá ôçò âÜóçò äåäïìÝíùí '%-.64s' (êùäéêüò ëÜèïõò: %d)",
+"Áäýíáôç ç äçìéïõñãßá ôçò âÜóçò äåäïìÝíùí '%-.64s'; Ç âÜóç äåäïìÝíùí õðÜñ÷åé Þäç",
"Áäýíáôç ç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí '%-.64s'. Ç âÜóç äåäïìÝíùí äåí õðÜñ÷åé",
"ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí (áäýíáôç ç äéáãñáöÞ '%-.64s', êùäéêüò ëÜèïõò: %d)",
"ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí (áäýíáôç ç äéáãñáöÞ ôïõ öáêÝëëïõ '%-.64s', êùäéêüò ëÜèïõò: %d)",
@@ -17,12 +17,12 @@
"Áäýíáôç ç ëÞøç ðëçñïöïñéþí ãéá ôçí êáôÜóôáóç ôïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)",
"Ï öÜêåëëïò åñãáóßáò äåí âñÝèçêå (êùäéêüò ëÜèïõò: %d)",
"Ôï áñ÷åßï äåí ìðïñåß íá êëåéäùèåß (êùäéêüò ëÜèïõò: %d)",
-"Äåí åßíáé äõíáôü íá áíïé÷ôåß ôï áñ÷åßï: '%-.64s'. (êùäéêüò ëÜèïõò: %d)",
+"Äåí åßíáé äõíáôü íá áíïé÷ôåß ôï áñ÷åßï: '%-.64s' (êùäéêüò ëÜèïõò: %d)",
"Äåí âñÝèçêå ôï áñ÷åßï: '%-.64s' (êùäéêüò ëÜèïõò: %d)",
"Äåí åßíáé äõíáôü íá äéáâáóôåß ï öÜêåëëïò ôïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)",
"Áäýíáôç ç áëëáãÞ ôïõ ôñÝ÷ïíôïò êáôáëüãïõ óå '%-.64s' (êùäéêüò ëÜèïõò: %d)",
"Ç åããñáöÞ Ý÷åé áëëÜîåé áðü ôçí ôåëåõôáßá öïñÜ ðïõ áíáóýñèçêå áðü ôïí ðßíáêá '%-.64s'",
-"Äåí õðÜñ÷åé ÷þñïò óôï äßóêï (%s). Ðáñáêáëþ, ðåñéìÝíåôå íá åëåõèåñùèåß ÷þñïò....",
+"Äåí õðÜñ÷åé ÷þñïò óôï äßóêï (%s). Ðáñáêáëþ, ðåñéìÝíåôå íá åëåõèåñùèåß ÷þñïò...",
"Äåí åßíáé äõíáôÞ ç êáôá÷þñçóç, ç ôéìÞ õðÜñ÷åé Þäç óôïí ðßíáêá '%-.64s'",
"ÐáñïõóéÜóôçêå ðñüâëçìá êëåßíïíôáò ôï '%-.64s' (êùäéêüò ëÜèïõò: %d)",
"Ðñüâëçìá êáôÜ ôçí áíÜãíùóç ôïõ áñ÷åßïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)",
@@ -35,7 +35,7 @@
"Ï ÷åéñéóôÞò ðßíáêá (table handler) ãéá '%-.64s' äåí äéáèÝôåé áõôÞ ôçí åðéëïãÞ",
"Áäýíáôç ç áíåýñåóç åããñáöÞò óôï '%-.64s'",
"ËÜèïò ðëçñïöïñßåò óôï áñ÷åßï: '%-.64s'",
-"ËÜèïò áñ÷åßï ôáîéíüìéóçò (key file) ãéá ôïí ðßíáêá: '%-.64s'. Ðáñáêáëþ, äéïñèþóôå ôï!",
+"ËÜèïò áñ÷åßï ôáîéíüìéóçò (key file) ãéá ôïí ðßíáêá: '%-.64s'; Ðáñáêáëþ, äéïñèþóôå ôï!",
"Ðáëáéü áñ÷åßï ôáîéíüìéóçò (key file) ãéá ôïí ðßíáêá '%-.64s'; Ðáñáêáëþ, äéïñèþóôå ôï!",
"'%-.64s' åðéôñÝðåôáé ìüíï ç áíÜãíùóç",
"Äåí õðÜñ÷åé äéáèÝóéìç ìíÞìç. ÐñïóðáèÞóôå ðÜëé, åðáíåêéíþíôáò ôç äéáäéêáóßá (demon) (÷ñåéÜæïíôáé %d bytes)",
@@ -213,7 +213,7 @@
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -250,7 +250,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -264,3 +264,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 162bfc5509c..6b27cdc2551 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -19,8 +19,8 @@
"A(z) '%-.64s' statusza nem allapithato meg (hibakod: %d)",
"A munkakonyvtar nem allapithato meg (hibakod: %d)",
"A file nem zarolhato. (hibakod: %d)",
-"A '%-.64s' file nem nyithato meg. (hibakod: %d)",
-"A(z) '%-.64s' file nem talalhato. (hibakod: %d)",
+"A '%-.64s' file nem nyithato meg (hibakod: %d)",
+"A(z) '%-.64s' file nem talalhato (hibakod: %d)",
"A(z) '%-.64s' konyvtar nem olvashato. (hibakod: %d)",
"Konyvtarvaltas nem lehetseges a(z) '%-.64s'-ba. (hibakod: %d)",
"A(z) '%-.64s' tablaban talalhato rekord megvaltozott az utolso olvasas ota",
@@ -37,8 +37,8 @@
"A(z) '%-.64s' tablakezelonek nincs ilyen opcioja",
"Nem talalhato a rekord '%-.64s'-ben",
"Ervenytelen info a file-ban: '%-.64s'",
-"Ervenytelen kulcsfile a tablahoz: '%-.64s'. Probalja kijavitani!",
-"Regi kulcsfile a '%-.64s'tablahoz; Probalja kijavitani!",
+"Ervenytelen kulcsfile a tablahoz: '%-.64s'; probalja kijavitani!",
+"Regi kulcsfile a '%-.64s'tablahoz; probalja kijavitani!",
"'%-.64s' irasvedett",
"Nincs eleg memoria. Inditsa ujra a demont, es probalja ismet. (%d byte szukseges.)",
"Nincs eleg memoria a rendezeshez. Novelje a rendezo demon puffermeretet",
@@ -215,7 +215,7 @@
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -252,7 +252,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -266,3 +266,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 26d916a968d..8b0598f64b5 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -7,9 +7,9 @@
"SI",
"Impossibile creare il file '%-.64s' (errno: %d)",
"Impossibile creare la tabella '%-.64s' (errno: %d)",
-"Impossibile creare il database '%-.64s'. (errno: %d)",
-"Impossibile creare il database '%-.64s'. Il database esiste",
-"Impossibile cancellare '%-.64s'. Il database non esiste",
+"Impossibile creare il database '%-.64s' (errno: %d)",
+"Impossibile creare il database '%-.64s'; il database esiste",
+"Impossibile cancellare '%-.64s'; il database non esiste",
"Errore durante la cancellazione del database (impossibile cancellare '%-.64s', errno: %d)",
"Errore durante la cancellazione del database (impossibile rmdir '%-.64s', errno: %d)",
"Errore durante la cancellazione di '%-.64s' (errno: %d)",
@@ -17,12 +17,12 @@
"Impossibile leggere lo stato di '%-.64s' (errno: %d)",
"Impossibile leggere la directory di lavoro (errno: %d)",
"Impossibile il locking il file (errno: %d)",
-"Impossibile aprire il file: '%-.64s'. (errno: %d)",
+"Impossibile aprire il file: '%-.64s' (errno: %d)",
"Impossibile trovare il file: '%-.64s' (errno: %d)",
"Impossibile leggere la directory di '%-.64s' (errno: %d)",
"Impossibile cambiare la directory in '%-.64s' (errno: %d)",
"Il record e` cambiato dall'ultima lettura della tabella '%-.64s'",
-"Disco pieno (%s). In attesa che qualcuno liberi un po' di spazio....",
+"Disco pieno (%s). In attesa che qualcuno liberi un po' di spazio...",
"Scrittura impossibile: chiave duplicata nella tabella '%-.64s'",
"Errore durante la chiusura di '%-.64s' (errno: %d)",
"Errore durante la lettura del file '%-.64s' (errno: %d)",
@@ -35,8 +35,8 @@
"Il gestore delle tabelle per '%-.64s' non ha questa opzione",
"Impossibile trovare il record in '%-.64s'",
"Informazione errata nel file: '%-.64s'",
-"File chiave errato per la tabella : '%-.64s'. Prova a riparalo",
-"File chiave vecchio per la tabella '%-.64s'; Riparalo!",
+"File chiave errato per la tabella : '%-.64s'; prova a riparalo",
+"File chiave vecchio per la tabella '%-.64s'; riparalo!",
"'%-.64s' e` di sola lettura",
"Memoria esaurita. Fai ripartire il demone e riprova (richiesti %d bytes)",
"Memoria per gli ordinamenti esaurita. Incrementare il 'sort_buffer' al demone",
@@ -250,7 +250,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -264,3 +264,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index a01a2b7ff6f..011d6a1faac 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -17,9 +17,9 @@
"'%-.64s' ¤Îºï½ü¤¬¥¨¥é¡¼ (errno: %d)",
"system table ¤Î¥ì¥³¡¼¥É¤òÆɤà»ö¤¬¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿",
"'%-.64s' ¤Î¥¹¥Æ¥¤¥¿¥¹¤¬ÆÀ¤é¤ì¤Þ¤»¤ó. (errno: %d)",
-"working directory ¤òÆÀ¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿. (errno: %d)",
-"¥Õ¥¡¥¤¥ë¤ò¥í¥Ã¥¯¤Ç¤­¤Þ¤»¤ó.(errno: %d)",
-"'%-.64s' ¥Õ¥¡¥¤¥ë¤ò³«¤¯»ö¤¬¤Ç¤­¤Þ¤»¤ó.(errno: %d)",
+"working directory ¤òÆÀ¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿ (errno: %d)",
+"¥Õ¥¡¥¤¥ë¤ò¥í¥Ã¥¯¤Ç¤­¤Þ¤»¤ó (errno: %d)",
+"'%-.64s' ¥Õ¥¡¥¤¥ë¤ò³«¤¯»ö¤¬¤Ç¤­¤Þ¤»¤ó (errno: %d)",
"'%-.64s' ¥Õ¥¡¥¤¥ë¤ò¸«ÉÕ¤±¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó.(errno: %d)",
"'%-.64s' ¥Ç¥£¥ì¥¯¥È¥ê¤¬Æɤá¤Þ¤»¤ó.(errno: %d)",
"'%-.64s' ¥Ç¥£¥ì¥¯¥È¥ê¤Ë chdir ¤Ç¤­¤Þ¤»¤ó.(errno: %d)",
@@ -215,7 +215,7 @@
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -252,7 +252,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -266,3 +266,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 5f5526be04b..be7fee7cb45 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -17,12 +17,12 @@
"'%-.64s'ÀÇ »óŸ¦ ¾òÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
"¼öÇà µð·ºÅ丮¸¦ ãÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
"È­ÀÏÀ» Àá±×Áö(lock) ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
-"È­ÀÏÀ» ¿­Áö ¸øÇß½À´Ï´Ù.: '%-.64s'. (¿¡·¯¹øÈ£: %d)",
+"È­ÀÏÀ» ¿­Áö ¸øÇß½À´Ï´Ù.: '%-.64s' (¿¡·¯¹øÈ£: %d)",
"È­ÀÏÀ» ãÁö ¸øÇß½À´Ï´Ù.: '%-.64s' (¿¡·¯¹øÈ£: %d)",
"'%-.64s'µð·ºÅ丮¸¦ ÀÐÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
"'%-.64s'µð·ºÅ丮·Î À̵¿ÇÒ ¼ö ¾ø¾ú½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
"Å×À̺í '%-.64s'¿¡¼­ ¸¶Áö¸·À¸·Î ÀÐÀº ÈÄ Record°¡ º¯°æµÇ¾ú½À´Ï´Ù.",
-"Disk full (%s). ´Ù¸¥ »ç¶÷ÀÌ Áö¿ï¶§±îÁö ±â´Ù¸³´Ï´Ù.....",
+"Disk full (%s). ´Ù¸¥ »ç¶÷ÀÌ Áö¿ï¶§±îÁö ±â´Ù¸³´Ï´Ù...",
"±â·ÏÇÒ ¼ö ¾øÀ¾´Ï´Ù., Å×À̺í '%-.64s'¿¡¼­ Áߺ¹ Å°",
"'%-.64s'´Ý´Â Áß ¿¡·¯ (¿¡·¯¹øÈ£: %d)",
"'%-.64s'È­ÀÏ Àб⠿¡·¯ (¿¡·¯¹øÈ£: %d)",
@@ -48,7 +48,7 @@
"'%-.32s@%-.64s' »ç¿ëÀÚ´Â '%-.64s' µ¥ÀÌŸº£À̽º¿¡ Á¢±ÙÀÌ °ÅºÎ µÇ¾ú½À´Ï´Ù.",
"'%-.32s@%-.64s' »ç¿ëÀÚ´Â Á¢±ÙÀÌ °ÅºÎ µÇ¾ú½À´Ï´Ù. (Using password: %s)",
"¼±ÅÃµÈ µ¥ÀÌŸº£À̽º°¡ ¾ø½À´Ï´Ù.",
-"¸í·É¾î°¡ ¹ºÁö ¸ð¸£°Ú¾î¿ä....",
+"¸í·É¾î°¡ ¹ºÁö ¸ð¸£°Ú¾î¿ä...",
"Ä®·³ '%-.64s'´Â ³Î(Null)ÀÌ µÇ¸é ¾ÈµË´Ï´Ù. ",
"µ¥ÀÌŸº£À̽º '%-.64s'´Â ¾Ë¼ö ¾øÀ½",
"Å×À̺í '%-.64s'´Â ÀÌ¹Ì Á¸ÀçÇÔ",
@@ -213,7 +213,7 @@
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -250,7 +250,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -264,3 +264,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index bf1019d3d87..96c11871502 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -9,9 +9,9 @@
"JA",
"Kan ikkje opprette fila '%-.64s' (Feilkode: %d)",
"Kan ikkje opprette tabellen '%-.64s' (Feilkode: %d)",
-"Kan ikkje opprette databasen '%-.64s'. Feil %d",
-"Kan ikkje opprette databasen '%-.64s'. Databasen eksisterer",
-"Kan ikkje fjerne (drop) '%-.64s'. Databasen eksisterer ikkje",
+"Kan ikkje opprette databasen '%-.64s' (Feilkode: %d)",
+"Kan ikkje opprette databasen '%-.64s'; databasen eksisterer",
+"Kan ikkje fjerne (drop) '%-.64s'; databasen eksisterer ikkje",
"Feil ved fjerning (drop) av databasen (kan ikkje slette '%-.64s', feil %d)",
"Feil ved sletting av database (kan ikkje slette katalogen '%-.64s', feil %d)",
"Feil ved sletting av '%-.64s' (Feilkode: %d)",
@@ -19,12 +19,12 @@
"Kan ikkje lese statusen til '%-.64s' (Feilkode: %d)",
"Kan ikkje lese aktiv katalog(Feilkode: %d)",
"Kan ikkje låse fila (Feilkode: %d)",
-"Kan ikkje åpne fila: '%-.64s'. (Feilkode: %d)",
+"Kan ikkje åpne fila: '%-.64s' (Feilkode: %d)",
"Kan ikkje finne fila: '%-.64s' (Feilkode: %d)",
"Kan ikkje lese katalogen '%-.64s' (Feilkode: %d)",
"Kan ikkje skifte katalog til '%-.64s' (Feilkode: %d)",
"Posten har vorte endra sidan den sist vart lesen '%-.64s'",
-"Ikkje meir diskplass (%s). Ventar på å få frigjort plass....",
+"Ikkje meir diskplass (%s). Ventar på å få frigjort plass...",
"Kan ikkje skrive, flere like nyklar i tabellen '%-.64s'",
"Feil ved lukking av '%-.64s' (Feilkode: %d)",
"Feil ved lesing av '%-.64s' (Feilkode: %d)",
@@ -37,8 +37,8 @@
"Tabell håndteraren for '%-.64s' har ikkje denne moglegheita",
"Kan ikkje finne posten i '%-.64s'",
"Feil informasjon i fila: '%-.64s'",
-"Tabellen '%-.64s' har feil i nykkelfila, Prøv å reparere den",
-"Gammel nykkelfil for tabellen '%-.64s'; Reparer den!",
+"Tabellen '%-.64s' har feil i nykkelfila; prøv å reparere den",
+"Gammel nykkelfil for tabellen '%-.64s'; reparer den!",
"'%-.64s' er skrivetryggja",
"Ikkje meir minne. Start på nytt tenesten og prøv igjen (trengte %d bytar)",
"Ikkje meir sorteringsminne. Auk sorteringsminnet (sorteringsbffer storleik) for tenesten",
@@ -215,7 +215,7 @@
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -252,7 +252,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -266,3 +266,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 68c95bbf22b..c505d512e9e 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -9,9 +9,9 @@
"JA",
"Kan ikke opprette fila '%-.64s' (Feilkode: %d)",
"Kan ikke opprette tabellen '%-.64s' (Feilkode: %d)",
-"Kan ikke opprette databasen '%-.64s'. Feil %d",
-"Kan ikke opprette databasen '%-.64s'. Databasen eksisterer",
-"Kan ikke fjerne (drop) '%-.64s'. Databasen eksisterer ikke",
+"Kan ikke opprette databasen '%-.64s' (Feilkode: %d)",
+"Kan ikke opprette databasen '%-.64s'; databasen eksisterer",
+"Kan ikke fjerne (drop) '%-.64s'; databasen eksisterer ikke",
"Feil ved fjerning (drop) av databasen (kan ikke slette '%-.64s', feil %d)",
"Feil ved sletting av database (kan ikke slette katalogen '%-.64s', feil %d)",
"Feil ved sletting av '%-.64s' (Feilkode: %d)",
@@ -19,12 +19,12 @@
"Kan ikke lese statusen til '%-.64s' (Feilkode: %d)",
"Kan ikke lese aktiv katalog(Feilkode: %d)",
"Kan ikke låse fila (Feilkode: %d)",
-"Kan ikke åpne fila: '%-.64s'. (Feilkode: %d)",
+"Kan ikke åpne fila: '%-.64s' (Feilkode: %d)",
"Kan ikke finne fila: '%-.64s' (Feilkode: %d)",
"Kan ikke lese katalogen '%-.64s' (Feilkode: %d)",
"Kan ikke skifte katalog til '%-.64s' (Feilkode: %d)",
"Posten har blitt endret siden den ble lest '%-.64s'",
-"Ikke mer diskplass (%s). Venter på å få frigjort plass....",
+"Ikke mer diskplass (%s). Venter på å få frigjort plass...",
"Kan ikke skrive, flere like nøkler i tabellen '%-.64s'",
"Feil ved lukking av '%-.64s' (Feilkode: %d)",
"Feil ved lesing av '%-.64s' (Feilkode: %d)",
@@ -37,8 +37,8 @@
"Tabell håndtereren for '%-.64s' har ikke denne muligheten",
"Kan ikke finne posten i '%-.64s'",
"Feil informasjon i filen: '%-.64s'",
-"Tabellen '%-.64s' har feil i nøkkelfilen, forsøk å reparer den",
-"Gammel nøkkelfil for tabellen '%-.64s'; Reparer den!",
+"Tabellen '%-.64s' har feil i nøkkelfilen; forsøk å reparer den",
+"Gammel nøkkelfil for tabellen '%-.64s'; reparer den!",
"'%-.64s' er skrivebeskyttet",
"Ikke mer minne. Star på nytt tjenesten og prøv igjen (trengte %d byter)",
"Ikke mer sorteringsminne. Øk sorteringsminnet (sort buffer size) for tjenesten",
@@ -215,7 +215,7 @@
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -252,7 +252,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -266,3 +266,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 5b93403c757..33b2fbdb8a8 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -11,9 +11,9 @@
"TAK",
"Nie mo¿na stworzyæ pliku '%-.64s' (Kod b³êdu: %d)",
"Nie mo¿na stworzyæ tabeli '%-.64s' (Kod b³êdu: %d)",
-"Nie mo¿na stworzyæ bazy danych '%-.64s'. B³?d %d",
-"Nie mo¿na stworzyæ bazy danych '%-.64s'. Baza danych ju¿ istnieje",
-"Nie mo¿na usun?æ bazy danych '%-.64s'. Baza danych nie istnieje",
+"Nie mo¿na stworzyæ bazy danych '%-.64s' (Kod b³êdu: %d)",
+"Nie mo¿na stworzyæ bazy danych '%-.64s'; baza danych ju¿ istnieje",
+"Nie mo¿na usun?æ bazy danych '%-.64s'; baza danych nie istnieje",
"B³?d podczas usuwania bazy danych (nie mo¿na usun?æ '%-.64s', b³?d %d)",
"B³?d podczas usuwania bazy danych (nie mo¿na wykonaæ rmdir '%-.64s', b³?d %d)",
"B³?d podczas usuwania '%-.64s' (Kod b³êdu: %d)",
@@ -21,12 +21,12 @@
"Nie mo¿na otrzymaæ statusu '%-.64s' (Kod b³êdu: %d)",
"Nie mo¿na rozpoznaæ aktualnego katalogu (Kod b³êdu: %d)",
"Nie mo¿na zablokowaæ pliku (Kod b³êdu: %d)",
-"Nie mo¿na otworzyæ pliku: '%-.64s'. (Kod b³êdu: %d)",
+"Nie mo¿na otworzyæ pliku: '%-.64s' (Kod b³êdu: %d)",
"Nie mo¿na znale¥æ pliku: '%-.64s' (Kod b³êdu: %d)",
"Nie mo¿na odczytaæ katalogu '%-.64s' (Kod b³êdu: %d)",
"Nie mo¿na zmieniæ katalogu na '%-.64s' (Kod b³êdu: %d)",
"Rekord zosta³ zmieniony od ostaniego odczytania z tabeli '%-.64s'",
-"Dysk pe³ny (%s). Oczekiwanie na zwolnienie miejsca....",
+"Dysk pe³ny (%s). Oczekiwanie na zwolnienie miejsca...",
"Nie mo¿na zapisaæ, powtórzone klucze w tabeli '%-.64s'",
"B³?d podczas zamykania '%-.64s' (Kod b³êdu: %d)",
"B³?d podczas odczytu pliku '%-.64s' (Kod b³êdu: %d)",
@@ -39,8 +39,8 @@
"Obs³uga tabeli '%-.64s' nie posiada tej opcji",
"Nie mo¿na znale¥æ rekordu w '%-.64s'",
"Niew³a?ciwa informacja w pliku: '%-.64s'",
-"Niew³a?ciwy plik kluczy dla tabeli: '%-.64s'. Spróbuj go naprawiæ",
-"Plik kluczy dla tabeli '%-.64s' jest starego typu; Napraw go!",
+"Niew³a?ciwy plik kluczy dla tabeli: '%-.64s'; spróbuj go naprawiæ",
+"Plik kluczy dla tabeli '%-.64s' jest starego typu; napraw go!",
"'%-.64s' jest tylko do odczytu",
"Zbyt ma³o pamiêci. Uruchom ponownie demona i spróbuj ponownie (potrzeba %d bajtów)",
"Zbyt ma³o pamiêci dla sortowania. Zwiêksz wielko?æ bufora demona dla sortowania",
@@ -217,7 +217,7 @@
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -254,7 +254,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -268,3 +268,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index edd3e3b813f..e8a3205ec5d 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -8,8 +8,8 @@
"Não pode criar o arquivo '%-.64s' (erro no. %d)",
"Não pode criar a tabela '%-.64s' (erro no. %d)",
"Não pode criar o banco de dados '%-.64s' (erro no. %d)",
-"Não pode criar o banco de dados '%-.64s'. Este banco de dados já existe",
-"Não pode eliminar o banco de dados '%-.64s'. Este banco de dados não existe",
+"Não pode criar o banco de dados '%-.64s'; este banco de dados já existe",
+"Não pode eliminar o banco de dados '%-.64s'; este banco de dados não existe",
"Erro ao eliminar banco de dados (não pode eliminar '%-.64s' - erro no. %d)",
"Erro ao eliminar banco de dados (não pode remover diretório '%-.64s' - erro no. %d)",
"Erro na remoção de '%-.64s' (erro no. %d)",
@@ -35,8 +35,8 @@
"Manipulador de tabela para '%-.64s' não tem esta opção",
"Não pode encontrar registro em '%-.64s'",
"Informação incorreta no arquivo '%-.64s'",
-"Arquivo de índice incorreto para tabela '%-.64s'. Tente repará-lo",
-"Arquivo de índice desatualizado para tabela '%-.64s'. Repare-o!",
+"Arquivo de índice incorreto para tabela '%-.64s'; tente repará-lo",
+"Arquivo de índice desatualizado para tabela '%-.64s'; repare-o!",
"Tabela '%-.64s' é somente para leitura",
"Sem memória. Reinicie o programa e tente novamente (necessita de %d bytes)",
"Sem memória para ordenação. Aumente tamanho do 'buffer' de ordenação",
@@ -250,7 +250,7 @@
"Cada tabela derivada deve ter seu próprio alias",
"Select %u foi reduzido durante otimização",
"Tabela '%-.64s' de um dos SELECT's não pode ser usada em %-.32s",
-"Cliente não suporta o protocolo de autenticação exigido pelo servidor. Considere a atualização deo cliente MySQL",
+"Cliente não suporta o protocolo de autenticação exigido pelo servidor; considere a atualização deo cliente MySQL",
"Todas as partes de uma SPATIAL KEY devem ser NOT NULL",
"COLLATION '%s' não é válida para CHARACTER SET '%s'",
"O slave já está rodando",
@@ -264,3 +264,6 @@
"Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 873a708fa7b..6602b5d430c 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -11,9 +11,9 @@
"DA",
"Nu pot sa creez fisierul '%-.64s' (Eroare: %d)",
"Nu pot sa creez tabla '%-.64s' (Eroare: %d)",
-"Nu pot sa creez baza de date '%-.64s'. (Eroare: %d)",
-"Nu pot sa creez baza de date '%-.64s'. Baza de date exista deja",
-"Nu pot sa drop baza de date '%-.64s'. Baza da date este inexistenta",
+"Nu pot sa creez baza de date '%-.64s' (Eroare: %d)",
+"Nu pot sa creez baza de date '%-.64s'; baza de date exista deja",
+"Nu pot sa drop baza de date '%-.64s'; baza da date este inexistenta",
"Eroare dropuind baza de date (nu pot sa sterg '%-.64s', Eroare: %d)",
"Eroare dropuind baza de date (nu pot sa rmdir '%-.64s', Eroare: %d)",
"Eroare incercind sa delete '%-.64s' (Eroare: %d)",
@@ -21,12 +21,12 @@
"Nu pot sa obtin statusul lui '%-.64s' (Eroare: %d)",
"Nu pot sa obtin directorul current (working directory) (Eroare: %d)",
"Nu pot sa lock fisierul (Eroare: %d)",
-"Nu pot sa deschid fisierul: '%-.64s'. (Eroare: %d)",
+"Nu pot sa deschid fisierul: '%-.64s' (Eroare: %d)",
"Nu pot sa gasesc fisierul: '%-.64s' (Eroare: %d)",
"Nu pot sa citesc directorul '%-.64s' (Eroare: %d)",
"Nu pot sa schimb directorul '%-.64s' (Eroare: %d)",
"Cimpul a fost schimbat de la ultima citire a tabelei '%-.64s'",
-"Hard-disk-ul este plin (%s). Astept sa se elibereze ceva spatiu....",
+"Hard-disk-ul este plin (%s). Astept sa se elibereze ceva spatiu...",
"Nu pot sa scriu (can't write), cheie duplicata in tabela '%-.64s'",
"Eroare inchizind '%-.64s' (errno: %d)",
"Eroare citind fisierul '%-.64s' (errno: %d)",
@@ -39,8 +39,8 @@
"Handlerul tabelei pentru '%-.64s' nu are aceasta optiune",
"Nu pot sa gasesc recordul in '%-.64s'",
"Informatie incorecta in fisierul: '%-.64s'",
-"Cheia fisierului incorecta pentru tabela: '%-.64s'. Incearca s-o repari",
-"Cheia fisierului e veche pentru tabela '%-.64s'; Repar-o!",
+"Cheia fisierului incorecta pentru tabela: '%-.64s'; incearca s-o repari",
+"Cheia fisierului e veche pentru tabela '%-.64s'; repar-o!",
"Tabela '%-.64s' e read-only",
"Out of memory. Porneste daemon-ul din nou si incearca inca o data (e nevoie de %d bytes)",
"Out of memory pentru sortare. Largeste marimea buffer-ului pentru sortare in daemon (sort buffer size)",
@@ -217,7 +217,7 @@
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -254,7 +254,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -268,3 +268,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index a05ecde6808..70ff979bfdf 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -9,7 +9,7 @@
"äá",
"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÆÁÊÌ '%-.64s' (ÏÛÉÂËÁ: %d)",
"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÔÁÂÌÉÃÕ '%-.64s' (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.64s'. (ÏÛÉÂËÁ: %d)",
+"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.64s' (ÏÛÉÂËÁ: %d)",
"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.64s'. âÁÚÁ ÄÁÎÎÙÈ ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ",
"îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.64s'. ôÁËÏÊ ÂÁÚÙ ÄÁÎÎÙÈ ÎÅÔ",
"ïÛÉÂËÁ ÐÒÉ ÕÄÁÌÅÎÉÉ ÂÁÚÙ ÄÁÎÎÙÈ (ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ '%-.64s', ÏÛÉÂËÁ: %d)",
@@ -19,12 +19,12 @@
"îÅ×ÏÚÍÏÖÎÏ ÐÏÌÕÞÉÔØ ÓÔÁÔÕÓÎÕÀ ÉÎÆÏÒÍÁÃÉÀ Ï '%-.64s' (ÏÛÉÂËÁ: %d)",
"îÅ×ÏÚÍÏÖÎÏ ÏÐÒÅÄÅÌÉÔØ ÒÁÂÏÞÉÊ ËÁÔÁÌÏÇ (ÏÛÉÂËÁ: %d)",
"îÅ×ÏÚÍÏÖÎÏ ÐÏÓÔÁ×ÉÔØ ÂÌÏËÉÒÏ×ËÕ ÎÁ ÆÁÊÌÅ (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ: '%-.64s'. (ÏÛÉÂËÁ: %d)",
+"îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ: '%-.64s' (ÏÛÉÂËÁ: %d)",
"îÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÆÁÊÌ: '%-.64s' (ÏÛÉÂËÁ: %d)",
"îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ËÁÔÁÌÏÇ '%-.64s' (ÏÛÉÂËÁ: %d)",
"îÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÊÔÉ × ËÁÔÁÌÏÇ '%-.64s' (ÏÛÉÂËÁ: %d)",
"úÁÐÉÓØ ÉÚÍÅÎÉÌÁÓØ Ó ÍÏÍÅÎÔÁ ÐÏÓÌÅÄÎÅÊ ×ÙÂÏÒËÉ × ÔÁÂÌÉÃÅ '%-.64s'",
-"äÉÓË ÚÁÐÏÌÎÅÎ. (%s). ïÖÉÄÁÅÍ, ÐÏËÁ ËÔÏ-ÔÏ ÎÅ ÕÂÅÒÅÔ ÐÏÓÌÅ ÓÅÂÑ ÍÕÓÏÒ....",
+"äÉÓË ÚÁÐÏÌÎÅÎ. (%s). ïÖÉÄÁÅÍ, ÐÏËÁ ËÔÏ-ÔÏ ÎÅ ÕÂÅÒÅÔ ÐÏÓÌÅ ÓÅÂÑ ÍÕÓÏÒ...",
"îÅ×ÏÚÍÏÖÎÏ ÐÒÏÉÚ×ÅÓÔÉ ÚÁÐÉÓØ, ÄÕÂÌÉÒÕÀÝÉÊÓÑ ËÌÀÞ × ÔÁÂÌÉÃÅ '%-.64s'",
"ïÛÉÂËÁ ÐÒÉ ÚÁËÒÙÔÉÉ '%-.64s' (ÏÛÉÂËÁ: %d)",
"ïÛÉÂËÁ ÞÔÅÎÉÑ ÆÁÊÌÁ '%-.64s' (ÏÛÉÂËÁ: %d)",
@@ -252,7 +252,7 @@
"Every derived table must have it's own alias",
"Select %u ÂÙÌ ÕÐÒÁÚÄÎÅÎ × ÐÒÏÃÅÓÓÅ ÏÐÔÉÍÉÚÁÃÉÉ",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -266,3 +266,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index c1c0de779c7..f4ea3ac3c82 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -13,9 +13,9 @@
"DA",
"Ne mogu da kreiram file '%-.64s' (errno: %d)",
"Ne mogu da kreiram tabelu '%-.64s' (errno: %d)",
-"Ne mogu da kreiram bazu '%-.64s'. (errno: %d)",
-"Ne mogu da kreiram bazu '%-.64s'. Baza veæ postoji.",
-"Ne mogu da izbrišem bazu '%-.64s'. Baza ne postoji.",
+"Ne mogu da kreiram bazu '%-.64s' (errno: %d)",
+"Ne mogu da kreiram bazu '%-.64s'; baza veæ postoji.",
+"Ne mogu da izbrišem bazu '%-.64s'; baza ne postoji.",
"Ne mogu da izbrišem bazu (ne mogu da izbrišem '%-.64s', errno: %d)",
"Ne mogu da izbrišem bazu (ne mogu da izbrišem direktorijum '%-.64s', errno: %d)",
"Greška pri brisanju '%-.64s' (errno: %d)",
@@ -23,12 +23,12 @@
"Ne mogu da dobijem stanje file-a '%-.64s' (errno: %d)",
"Ne mogu da dobijem trenutni direktorijum (errno: %d)",
"Ne mogu da zakljuèam file (errno: %d)",
-"Ne mogu da otvorim file: '%-.64s'. (errno: %d)",
+"Ne mogu da otvorim file: '%-.64s' (errno: %d)",
"Ne mogu da pronaðem file: '%-.64s' (errno: %d)",
"Ne mogu da proèitam direktorijum '%-.64s' (errno: %d)",
"Ne mogu da promenim direktorijum na '%-.64s' (errno: %d)",
"Slog je promenjen od zadnjeg èitanja tabele '%-.64s'",
-"Disk je pun (%s). Èekam nekoga da doðe i oslobodi nešto mesta....",
+"Disk je pun (%s). Èekam nekoga da doðe i oslobodi nešto mesta...",
"Ne mogu da pišem pošto postoji duplirani kljuè u tabeli '%-.64s'",
"Greška pri zatvaranju '%-.64s' (errno: %d)",
"Greška pri èitanju file-a '%-.64s' (errno: %d)",
@@ -41,8 +41,8 @@
"Handler tabela za '%-.64s' nema ovu opciju",
"Ne mogu da pronaðem slog u '%-.64s'",
"Pogrešna informacija u file-u: '%-.64s'",
-"Pogrešan key file za tabelu: '%-.64s'. Probajte da ga ispravite",
-"Zastareo key file za tabelu '%-.64s'; Ispravite ga",
+"Pogrešan key file za tabelu: '%-.64s'; probajte da ga ispravite",
+"Zastareo key file za tabelu '%-.64s'; ispravite ga",
"Tabelu '%-.64s' je dozvoljeno samo èitati",
"Nema memorije. Restartujte MySQL server i probajte ponovo (potrebno je %d byte-ova)",
"Nema memorije za sortiranje. Poveæajte velièinu sort buffer-a MySQL server-u",
@@ -219,7 +219,7 @@
"Komanda 'CREATE DATABASE' nije dozvoljena dok thread globalno zakljuèava èitanje podataka",
"Pogrešni argumenti prosleðeni na %s",
"Korisniku %-.32s@%-.64s nije dozvoljeno da kreira nove korisnike",
-"Pogrešna definicija tabele; Sve 'MERGE' tabele moraju biti u istoj bazi podataka",
+"Pogrešna definicija tabele; sve 'MERGE' tabele moraju biti u istoj bazi podataka",
"Unakrsno zakljuèavanje pronaðeno kada sam pokušao da dobijem pravo na zakljuèavanje; Probajte da restartujete transakciju",
"Upotrebljeni tip tabele ne podržava 'FULLTEXT' indekse",
"Ne mogu da dodam proveru spoljnog kljuèa",
@@ -246,7 +246,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -260,3 +260,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 26d673b847c..2ba4f2f0548 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -15,9 +15,9 @@
"Áno",
"Nemô¾em vytvori» súbor '%-.64s' (chybový kód: %d)",
"Nemô¾em vytvori» tabuµku '%-.64s' (chybový kód: %d)",
-"Nemô¾em vytvori» databázu '%-.64s'. (chybový kód: %d)",
-"Nemô¾em vytvori» databázu '%-.64s'. Databáza existuje",
-"Nemô¾em zmaza» databázu '%-.64s'. Databáza neexistuje",
+"Nemô¾em vytvori» databázu '%-.64s' (chybový kód: %d)",
+"Nemô¾em vytvori» databázu '%-.64s'; databáza existuje",
+"Nemô¾em zmaza» databázu '%-.64s'; databáza neexistuje",
"Chyba pri mazaní databázy (nemô¾em zmaza» '%-.64s', chybový kód: %d)",
"Chyba pri mazaní databázy (nemô¾em vymaza» adresár '%-.64s', chybový kód: %d)",
"Chyba pri mazaní '%-.64s' (chybový kód: %d)",
@@ -25,12 +25,12 @@
"Nemô¾em zisti» stav '%-.64s' (chybový kód: %d)",
"Nemô¾em zisti» pracovný adresár (chybový kód: %d)",
"Nemô¾em zamknú» súbor (chybový kód: %d)",
-"Nemô¾em otvori» súbor: '%-.64s'. (chybový kód: %d)",
+"Nemô¾em otvori» súbor: '%-.64s' (chybový kód: %d)",
"Nemô¾em nájs» súbor: '%-.64s' (chybový kód: %d)",
"Nemô¾em èíta» adresár '%-.64s' (chybový kód: %d)",
"Nemô¾em vojs» do adresára '%-.64s' (chybový kód: %d)",
"Záznam bol zmenený od posledného èítania v tabuµke '%-.64s'",
-"Disk je plný (%s), èakám na uvoµnenie miesta....",
+"Disk je plný (%s), èakám na uvoµnenie miesta...",
"Nemô¾em zapísa», duplikát kµúèa v tabuµke '%-.64s'",
"Chyba pri zatváraní '%-.64s' (chybový kód: %d)",
"Chyba pri èítaní súboru '%-.64s' (chybový kód: %d)",
@@ -43,8 +43,8 @@
"Obsluha tabuµky '%-.64s' nemá tento parameter",
"Nemô¾em nájs» záznam v '%-.64s'",
"Nesprávna informácia v súbore: '%-.64s'",
-"Nesprávny kµúè pre tabuµku '%-.64s'. Pokúste sa ho opravi»",
-"Starý kµúèový súbor pre '%-.64s'; Opravte ho!",
+"Nesprávny kµúè pre tabuµku '%-.64s'; pokúste sa ho opravi»",
+"Starý kµúèový súbor pre '%-.64s'; opravte ho!",
"'%-.64s' is èíta» only",
"Málo pamäti. Re¹tartujte daemona a skúste znova (je potrebných %d bytov)",
"Málo pamäti pre triedenie, zvý¹te veµkos» triediaceho bufferu",
@@ -221,7 +221,7 @@
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -258,7 +258,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -272,3 +272,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 99a92f63c4e..c7f8d51dee9 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -8,9 +8,9 @@
"SI",
"No puedo crear archivo '%-.64s' (Error: %d)",
"No puedo crear tabla '%-.64s' (Error: %d)",
-"No puedo crear base de datos '%-.64s'. Error %d",
-"No puedo crear base de datos '%-.64s'. La base de datos ya existe",
-"No puedo eliminar base de datos '%-.64s'. La base de datos no existe",
+"No puedo crear base de datos '%-.64s' (Error: %d)",
+"No puedo crear base de datos '%-.64s'; la base de datos ya existe",
+"No puedo eliminar base de datos '%-.64s'; la base de datos no existe",
"Error eliminando la base de datos(no puedo borrar '%-.64s', error %d)",
"Error eliminando la base de datos (No puedo borrar directorio '%-.64s', error %d)",
"Error en el borrado de '%-.64s' (Error: %d)",
@@ -18,12 +18,12 @@
"No puedo obtener el estado de '%-.64s' (Error: %d)",
"No puedo acceder al directorio (Error: %d)",
"No puedo bloquear archivo: (Error: %d)",
-"No puedo abrir archivo: '%-.64s'. (Error: %d)",
+"No puedo abrir archivo: '%-.64s' (Error: %d)",
"No puedo encontrar archivo: '%-.64s' (Error: %d)",
"No puedo leer el directorio de '%-.64s' (Error: %d)",
"No puedo cambiar al directorio de '%-.64s' (Error: %d)",
"El registro ha cambiado desde la ultima lectura de la tabla '%-.64s'",
-"Disco lleno (%s). Esperando para que se libere algo de espacio....",
+"Disco lleno (%s). Esperando para que se libere algo de espacio...",
"No puedo escribir, clave duplicada en la tabla '%-.64s'",
"Error en el cierre de '%-.64s' (Error: %d)",
"Error leyendo el fichero '%-.64s' (Error: %d)",
@@ -36,8 +36,8 @@
"El manejador de la tabla de '%-.64s' no tiene esta opcion",
"No puedo encontrar el registro en '%-.64s'",
"Informacion erronea en el archivo: '%-.64s'",
-"Clave de archivo erronea para la tabla: '%-.64s'. Intente repararlo",
-"Clave de archivo antigua para la tabla '%-.64s'; Reparelo!",
+"Clave de archivo erronea para la tabla: '%-.64s'; intente repararlo",
+"Clave de archivo antigua para la tabla '%-.64s'; reparelo!",
"'%-.64s' es de solo lectura",
"Memoria insuficiente. Reinicie el demonio e intentelo otra vez (necesita %d bytes)",
"Memoria de ordenacion insuficiente. Incremente el tamano del buffer de ordenacion",
@@ -214,7 +214,7 @@
"CREATE DATABASE no permitido mientras un thread está ejerciendo un bloqueo de lectura global",
"Wrong arguments to %s",
"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
@@ -251,7 +251,7 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -265,3 +265,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index c613d205947..0d51cb4b543 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -7,9 +7,9 @@
"YES",
"Kan inte skapa filen '%-.64s' (Felkod: %d)",
"Kan inte skapa tabellen '%-.64s' (Felkod: %d)",
-"Kan inte skapa databasen '%-.64s'. (Felkod: %d)",
+"Kan inte skapa databasen '%-.64s' (Felkod: %d)",
"Databasen '%-.64s' existerar redan",
-"Kan inte radera databasen '%-.64s'. Databasen finns inte",
+"Kan inte radera databasen '%-.64s'; databasen finns inte",
"Fel vid radering av databasen (Kan inte radera '%-.64s'. Felkod: %d)",
"Fel vid radering av databasen (Kan inte radera biblioteket '%-.64s'. Felkod: %d)",
"Kan inte radera filen '%-.64s' (Felkod: %d)",
@@ -17,12 +17,12 @@
"Kan inte läsa filinformationen (stat) från '%-.64s' (Felkod: %d)",
"Kan inte inte läsa aktivt bibliotek. (Felkod: %d)",
"Kan inte låsa filen. (Felkod: %d)",
-"Kan inte använda '%-.64s'. (Felkod: %d)",
-"Hittar inte filen '%-.64s'. (Felkod: %d)",
-"Kan inte läsa från bibliotek '%-.64s'. (Felkod: %d)",
-"Kan inte byta till '%-.64s'. (Felkod: %d)",
+"Kan inte använda '%-.64s' (Felkod: %d)",
+"Hittar inte filen '%-.64s' (Felkod: %d)",
+"Kan inte läsa från bibliotek '%-.64s' (Felkod: %d)",
+"Kan inte byta till '%-.64s' (Felkod: %d)",
"Posten har förändrats sedan den lästes i register '%-.64s'",
-"Disken är full (%s). Väntar tills det finns ledigt utrymme....",
+"Disken är full (%s). Väntar tills det finns ledigt utrymme...",
"Kan inte skriva, dubbel söknyckel i register '%-.64s'",
"Fick fel vid stängning av '%-.64s' (Felkod: %d)",
"Fick fel vid läsning av '%-.64s' (Felkod %d)",
@@ -35,8 +35,8 @@
"Registrets databas har inte denna facilitet",
"Hittar inte posten",
"Felaktig fil: '%-.64s'",
-"Fatalt fel vid hantering av register '%-.64s'. Kör en reparation",
-"Gammal nyckelfil '%-.64s'. Reparera registret",
+"Fatalt fel vid hantering av register '%-.64s'; kör en reparation",
+"Gammal nyckelfil '%-.64s'; reparera registret",
"'%-.64s' är skyddad mot förändring",
"Oväntat slut på minnet, starta om programmet och försök på nytt (Behövde %d bytes)",
"Sorteringsbufferten räcker inte till. Kontrollera startparametrarna",
@@ -213,7 +213,7 @@
"CREATE DATABASE är inte tillåtet när man har ett globalt läslås",
"Felaktiga argument till %s",
"%-.32s@%-.64s har inte rättighet att skapa nya användare",
-"Felaktig tabelldefinition. Alla tabeller i en MERGE-tabell måste vara i samma databas",
+"Felaktig tabelldefinition; alla tabeller i en MERGE-tabell måste vara i samma databas",
"Fick 'DEADLOCK' vid låsförsök av block/rad. Försök att starta om transaktionen",
"Tabelltypen har inte hantering av FULLTEXT-index",
"Kan inte lägga till 'FOREIGN KEY constraint'",
@@ -250,7 +250,7 @@
"Varje 'derived table' måste ha sitt eget alias",
"Select %u reducerades vid optimiering",
"Tabell '%-.64s' från en SELECT kan inte användas i %-.32s",
-"Klienten stöder inte autentiseringsprotokollet som begärts av servern. Överväg uppgradering av klientprogrammet.",
+"Klienten stöder inte autentiseringsprotokollet som begärts av servern; överväg uppgradering av klientprogrammet.",
"Alla delar av en SPATIAL KEY måste vara NOT NULL",
"COLLATION '%s' är inte tillåtet för CHARACTER SET '%s'",
"Slaven har redan startat",
@@ -264,3 +264,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 6505c3c9cac..4e22dbfcf3e 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -12,7 +12,7 @@
"ôáë",
"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÆÁÊÌ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÔÁÂÌÉÃÀ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.64s'. (ÐÏÍÉÌËÁ: %d)",
+"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.64s'. âÁÚÁ ÄÁÎÎÉÈ ¦ÓÎÕ¤",
"îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.64s'. âÁÚÁ ÄÁÎÎÉÈ ÎÅ ¦ÓÎÕ¤",
"îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ (îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ '%-.64s', ÐÏÍÉÌËÁ: %d)",
@@ -40,7 +40,7 @@
"äÅÓËÒÉÐÔÏÒ ÔÁÂÌÉæ '%-.64s' ÎÅ ÍÁ¤ 椧 ×ÌÁÓÔÉ×ÏÓÔ¦",
"îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ Õ '%-.64s'",
"èÉÂÎÁ ¦ÎÆÏÒÍÁÃ¦Ñ Õ ÆÁÊ̦: '%-.64s'",
-"èÉÂÎÉÊ ÆÁÊÌ ËÌÀÞÅÊ ÄÌÑ ÔÁÂÌÉæ: '%-.64s'. óÐÒÏÂÕÊÔÅ ÊÏÇÏ ×¦ÄÎÏ×ÉÔÉ",
+"èÉÂÎÉÊ ÆÁÊÌ ËÌÀÞÅÊ ÄÌÑ ÔÁÂÌÉæ: '%-.64s'; óÐÒÏÂÕÊÔÅ ÊÏÇÏ ×¦ÄÎÏ×ÉÔÉ",
"óÔÁÒÉÊ ÆÁÊÌ ËÌÀÞÅÊ ÄÌÑ ÔÁÂÌÉæ '%-.64s'; ÷¦ÄÎÏצÔØ ÊÏÇÏ!",
"ôÁÂÌÉÃÑ '%-.64s' Ô¦ÌØËÉ ÄÌÑ ÞÉÔÁÎÎÑ",
"âÒÁË ÐÁÍ'ÑÔ¦. òÅÓÔÁÒÔÕÊÔÅ ÓÅÒ×ÅÒ ÔÁ ÓÐÒÏÂÕÊÔÅ ÚÎÏ×Õ (ÐÏÔÒ¦ÂÎÏ %d ÂÁÊÔ¦×)",
@@ -218,7 +218,7 @@
"CREATE DATABASE ÎÅ ÄÏÚ×ÏÌÅÎÏ ÄÏËÉ Ç¦ÌËÁ ÐÅÒÅÂÕ×Á¤ Ð¦Ä ÚÁÇÁÌØÎÉÍ ÂÌÏËÕ×ÁÎÎÑÍ ÞÉÔÁÎÎÑ",
"èÉÂÎÉÊ ÁÒÇÕÍÅÎÔ ÄÌÑ %s",
"ëÏÒÉÓÔÕ×ÁÞÕ %-.32s@%-.64s ÎÅ ÄÏÚ×ÏÌÅÎÏ ÓÔ×ÏÒÀ×ÁÔÉ ÎÏ×ÉÈ ËÏÒÉÓÔÕ×ÁÞ¦×",
-"Incorrect table definition; All MERGE tables must be in the same database",
+"Incorrect table definition; all MERGE tables must be in the same database",
"Deadlock found when trying to get lock; Try restarting transaction",
"÷ÉËÏÒÉÓÔÁÎÉÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ FULLTEXT ¦ÎÄÅËÓ¦×",
"Cannot add foreign key constraint",
@@ -255,7 +255,7 @@
"Every derived table must have it's own alias",
"Select %u was ÓËÁÓÏ×ÁÎÏ ÐÒÉ ÏÐÔÉÍiÚÁÃii",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s",
-"Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
+"Client does not support authentication protocol requested by server; consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL",
"COLLATION '%s' is not valid for CHARACTER SET '%s'",
"The slave was already running",
@@ -269,3 +269,6 @@
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
"Can't drop one or more of the requested users"
"Can't revoke all privileges, grant for one or more of the requested users"
+"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
+"Illegal mix of collations for operation '%s'",
+"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
diff --git a/sql/slave.cc b/sql/slave.cc
index ccce8077cb8..c45c11f8bef 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2177,7 +2177,7 @@ extern "C" pthread_handler_decl(handle_slave_io,arg)
DBUG_ENTER("handle_slave_io");
#ifndef DBUG_OFF
-slave_begin:
+slave_begin:
#endif
DBUG_ASSERT(mi->inited);
mysql= NULL ;
@@ -2218,7 +2218,7 @@ slave_begin:
if (!(mi->mysql = mysql = mysql_init(NULL)))
{
- sql_print_error("Slave I/O thread: error in mc_mysql_init()");
+ sql_print_error("Slave I/O thread: error in mysql_init()");
goto err;
}
@@ -2270,7 +2270,7 @@ dump");
goto err;
}
- thd->proc_info = "Waiiting to reconnect after a failed dump request";
+ thd->proc_info = "Waiting to reconnect after a failed dump request";
end_server(mysql);
/*
First time retry immediately, assuming that we can recover
@@ -3075,7 +3075,8 @@ replication resumed in log '%s' at position %s", mi->user,
static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
bool suppress_warnings)
{
- return connect_to_master(thd, mysql, mi, 1, suppress_warnings);
+ DBUG_ENTER("safe_reconnect");
+ DBUG_RETURN(connect_to_master(thd, mysql, mi, 1, suppress_warnings));
}
diff --git a/sql/spatial.cc b/sql/spatial.cc
index c8dfb490a39..00db94a07d6 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -5,31 +5,31 @@
/***************************** GClassInfo *******************************/
-#define IMPLEMENT_GEOM(class_name, type_id, name) \
-{ \
- (GF_InitFromText) &class_name::init_from_text, \
- (GF_GetDataAsText) &class_name::get_data_as_text, \
- (GF_GetDataSize) &class_name::get_data_size, \
- (GF_GetMBR) &class_name::get_mbr, \
- (GF_GetD) &class_name::get_x, \
- (GF_GetD) &class_name::get_y, \
- (GF_GetD) &class_name::length, \
- (GF_GetD) &class_name::area, \
- (GF_GetI) &class_name::is_closed, \
- (GF_GetUI) &class_name::num_interior_ring, \
- (GF_GetUI) &class_name::num_points, \
- (GF_GetUI) &class_name::num_geometries, \
- (GF_GetUI) &class_name::dimension, \
- (GF_GetWS) &class_name::start_point, \
- (GF_GetWS) &class_name::end_point, \
- (GF_GetWS) &class_name::exterior_ring, \
- (GF_GetWS) &class_name::centroid, \
- (GF_GetUIWS) &class_name::point_n, \
- (GF_GetUIWS) &class_name::interior_ring_n, \
- (GF_GetUIWS) &class_name::geometry_n, \
- class_name::type_id, \
- name, \
- NULL \
+#define IMPLEMENT_GEOM(class_name, type_id, name) \
+{ \
+ (GF_InitFromText) &class_name::init_from_wkt, \
+ (GF_GetDataAsText) &class_name::get_data_as_wkt, \
+ (GF_GetDataSize) &class_name::get_data_size, \
+ (GF_GetMBR) &class_name::get_mbr, \
+ (GF_GetD) &class_name::get_x, \
+ (GF_GetD) &class_name::get_y, \
+ (GF_GetD) &class_name::length, \
+ (GF_GetD) &class_name::area, \
+ (GF_GetI) &class_name::is_closed, \
+ (GF_GetUI) &class_name::num_interior_ring, \
+ (GF_GetUI) &class_name::num_points, \
+ (GF_GetUI) &class_name::num_geometries, \
+ (GF_GetUI) &class_name::dimension, \
+ (GF_GetWS) &class_name::start_point, \
+ (GF_GetWS) &class_name::end_point, \
+ (GF_GetWS) &class_name::exterior_ring, \
+ (GF_GetWS) &class_name::centroid, \
+ (GF_GetUIWS) &class_name::point_n, \
+ (GF_GetUIWS) &class_name::interior_ring_n, \
+ (GF_GetUIWS) &class_name::geometry_n, \
+ class_name::type_id, \
+ name, \
+ NULL \
},
@@ -113,7 +113,7 @@ int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream
trs->set_error_msg("'(' expected");
return -1;
}
- if (init_from_text(trs, wkt)) return 1;
+ if (init_from_wkt(trs, wkt)) return 1;
if (trs->get_next_symbol() != ')')
{
trs->set_error_msg("')' expected");
@@ -161,7 +161,7 @@ size_t GPoint::get_data_size() const
return POINT_DATA_SIZE;
}
-int GPoint::init_from_text(GTextReadStream *trs, String *wkb)
+int GPoint::init_from_wkt(GTextReadStream *trs, String *wkb)
{
double x, y;
if (wkb->reserve(sizeof(double)*2))
@@ -176,7 +176,7 @@ int GPoint::init_from_text(GTextReadStream *trs, String *wkb)
return 0;
}
-int GPoint::get_data_as_text(String *txt) const
+int GPoint::get_data_as_wkt(String *txt) const
{
double x, y;
if (get_xy(&x, &y))
@@ -207,7 +207,7 @@ size_t GLineString::get_data_size() const
return 4 + n_points*POINT_DATA_SIZE;
}
-int GLineString::init_from_text(GTextReadStream *trs, String *wkb)
+int GLineString::init_from_wkt(GTextReadStream *trs, String *wkb)
{
uint32 n_points = 0;
int np_pos = wkb->length();
@@ -220,7 +220,7 @@ int GLineString::init_from_text(GTextReadStream *trs, String *wkb)
for (;;)
{
- if (p.init_from_text(trs, wkb))
+ if (p.init_from_wkt(trs, wkb))
return 1;
++n_points;
if (trs->get_next_toc_type() == GTextReadStream::comma)
@@ -239,7 +239,7 @@ int GLineString::init_from_text(GTextReadStream *trs, String *wkb)
return 0;
}
-int GLineString::get_data_as_text(String *txt) const
+int GLineString::get_data_as_wkt(String *txt) const
{
uint32 n_points;
const char *data = m_data;
@@ -459,7 +459,7 @@ size_t GPolygon::get_data_size() const
return data - m_data;
}
-int GPolygon::init_from_text(GTextReadStream *trs, String *wkb)
+int GPolygon::init_from_wkt(GTextReadStream *trs, String *wkb)
{
uint32 n_linear_rings = 0;
int lr_pos = wkb->length();
@@ -478,7 +478,7 @@ int GPolygon::init_from_text(GTextReadStream *trs, String *wkb)
trs->set_error_msg("'(' expected");
return 1;
}
- if (ls.init_from_text(trs, wkb))
+ if (ls.init_from_wkt(trs, wkb))
return 1;
if (trs->get_next_symbol() != ')')
{
@@ -503,7 +503,7 @@ int GPolygon::init_from_text(GTextReadStream *trs, String *wkb)
return 0;
}
-int GPolygon::get_data_as_text(String *txt) const
+int GPolygon::get_data_as_wkt(String *txt) const
{
uint32 n_linear_rings;
const char *data= m_data;
@@ -783,7 +783,7 @@ size_t GMultiPoint::get_data_size() const
return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE);
}
-int GMultiPoint::init_from_text(GTextReadStream *trs, String *wkb)
+int GMultiPoint::init_from_wkt(GTextReadStream *trs, String *wkb)
{
uint32 n_points = 0;
int np_pos = wkb->length();
@@ -799,7 +799,7 @@ int GMultiPoint::init_from_text(GTextReadStream *trs, String *wkb)
return 1;
wkb->q_append((char)wkbNDR);
wkb->q_append((uint32)wkbPoint);
- if (p.init_from_text(trs, wkb))
+ if (p.init_from_wkt(trs, wkb))
return 1;
++n_points;
if (trs->get_next_toc_type() == GTextReadStream::comma)
@@ -812,7 +812,7 @@ int GMultiPoint::init_from_text(GTextReadStream *trs, String *wkb)
return 0;
}
-int GMultiPoint::get_data_as_text(String *txt) const
+int GMultiPoint::get_data_as_wkt(String *txt) const
{
uint32 n_points;
const char *data= m_data;
@@ -904,7 +904,7 @@ size_t GMultiLineString::get_data_size() const
return data - m_data;
}
-int GMultiLineString::init_from_text(GTextReadStream *trs, String *wkb)
+int GMultiLineString::init_from_wkt(GTextReadStream *trs, String *wkb)
{
uint32 n_line_strings = 0;
int ls_pos = wkb->length();
@@ -928,7 +928,7 @@ int GMultiLineString::init_from_text(GTextReadStream *trs, String *wkb)
trs->set_error_msg("'(' expected");
return 1;
}
- if (ls.init_from_text(trs, wkb))
+ if (ls.init_from_wkt(trs, wkb))
return 1;
if (trs->get_next_symbol() != ')')
@@ -947,7 +947,7 @@ int GMultiLineString::init_from_text(GTextReadStream *trs, String *wkb)
return 0;
}
-int GMultiLineString::get_data_as_text(String *txt) const
+int GMultiLineString::get_data_as_wkt(String *txt) const
{
uint32 n_line_strings;
const char *data= m_data;
@@ -1120,7 +1120,7 @@ size_t GMultiPolygon::get_data_size() const
return data - m_data;
}
-int GMultiPolygon::init_from_text(GTextReadStream *trs, String *wkb)
+int GMultiPolygon::init_from_wkt(GTextReadStream *trs, String *wkb)
{
uint32 n_polygons = 0;
int np_pos = wkb->length();
@@ -1143,7 +1143,7 @@ int GMultiPolygon::init_from_text(GTextReadStream *trs, String *wkb)
trs->set_error_msg("'(' expected");
return 1;
}
- if (p.init_from_text(trs, wkb))
+ if (p.init_from_wkt(trs, wkb))
return 1;
if (trs->get_next_symbol() != ')')
{
@@ -1160,7 +1160,7 @@ int GMultiPolygon::init_from_text(GTextReadStream *trs, String *wkb)
return 0;
}
-int GMultiPolygon::get_data_as_text(String *txt) const
+int GMultiPolygon::get_data_as_wkt(String *txt) const
{
uint32 n_polygons;
const char *data= m_data;
@@ -1403,7 +1403,7 @@ size_t GGeometryCollection::get_data_size() const
return data - m_data;
}
-int GGeometryCollection::init_from_text(GTextReadStream *trs, String *wkb)
+int GGeometryCollection::init_from_wkt(GTextReadStream *trs, String *wkb)
{
uint32 n_objects = 0;
int no_pos = wkb->length();
@@ -1433,7 +1433,7 @@ int GGeometryCollection::init_from_text(GTextReadStream *trs, String *wkb)
return 0;
}
-int GGeometryCollection::get_data_as_text(String *txt) const
+int GGeometryCollection::get_data_as_wkt(String *txt) const
{
uint32 n_objects;
const char *data = m_data;
diff --git a/sql/spatial.h b/sql/spatial.h
index d9c14afbe30..5fda257f1b1 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -228,8 +228,8 @@ public:
class GClassInfo
{
public:
- GF_InitFromText init_from_text;
- GF_GetDataAsText get_data_as_text;
+ GF_InitFromText init_from_wkt;
+ GF_GetDataAsText get_data_as_wkt;
GF_GetDataSize get_data_size;
GF_GetMBR get_mbr;
GF_GetD get_x;
@@ -262,11 +262,11 @@ public:
const GClassInfo *get_class_info() const { return m_vmt; }
size_t get_data_size() const { return (this->*m_vmt->get_data_size)(); }
- int init_from_text(GTextReadStream *trs, String *wkb)
- { return (this->*m_vmt->init_from_text)(trs, wkb); }
+ int init_from_wkt(GTextReadStream *trs, String *wkb)
+ { return (this->*m_vmt->init_from_wkt)(trs, wkb); }
- int get_data_as_text(String *txt) const
- { return (this->*m_vmt->get_data_as_text)(txt); }
+ int get_data_as_wkt(String *txt) const
+ { return (this->*m_vmt->get_data_as_wkt)(txt); }
int get_mbr(MBR *mbr) const { return (this->*m_vmt->get_mbr)(mbr); }
int dimension(uint32 *dim) const
@@ -324,7 +324,7 @@ public:
return 1;
wkt->qs_append(get_class_info()->m_name);
wkt->qs_append('(');
- if (get_data_as_text(wkt))
+ if (get_data_as_wkt(wkt))
return 1;
wkt->qs_append(')');
return 0;
@@ -364,8 +364,8 @@ class GPoint: public Geometry
{
public:
size_t get_data_size() const;
- int init_from_text(GTextReadStream *trs, String *wkb);
- int get_data_as_text(String *txt) const;
+ int init_from_wkt(GTextReadStream *trs, String *wkb);
+ int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int get_xy(double *x, double *y) const
@@ -401,8 +401,8 @@ class GLineString: public Geometry
{
public:
size_t get_data_size() const;
- int init_from_text(GTextReadStream *trs, String *wkb);
- int get_data_as_text(String *txt) const;
+ int init_from_wkt(GTextReadStream *trs, String *wkb);
+ int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int length(double *len) const;
@@ -420,8 +420,8 @@ class GPolygon: public Geometry
{
public:
size_t get_data_size() const;
- int init_from_text(GTextReadStream *trs, String *wkb);
- int get_data_as_text(String *txt) const;
+ int init_from_wkt(GTextReadStream *trs, String *wkb);
+ int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int area(double *ar) const;
@@ -439,8 +439,8 @@ class GMultiPoint: public Geometry
{
public:
size_t get_data_size() const;
- int init_from_text(GTextReadStream *trs, String *wkb);
- int get_data_as_text(String *txt) const;
+ int init_from_wkt(GTextReadStream *trs, String *wkb);
+ int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int num_geometries(uint32 *num) const;
@@ -454,8 +454,8 @@ class GMultiLineString: public Geometry
{
public:
size_t get_data_size() const;
- int init_from_text(GTextReadStream *trs, String *wkb);
- int get_data_as_text(String *txt) const;
+ int init_from_wkt(GTextReadStream *trs, String *wkb);
+ int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int num_geometries(uint32 *num) const;
@@ -471,8 +471,8 @@ class GMultiPolygon: public Geometry
{
public:
size_t get_data_size() const;
- int init_from_text(GTextReadStream *trs, String *wkb);
- int get_data_as_text(String *txt) const;
+ int init_from_wkt(GTextReadStream *trs, String *wkb);
+ int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int num_geometries(uint32 *num) const;
@@ -488,8 +488,8 @@ class GGeometryCollection: public Geometry
{
public:
size_t get_data_size() const;
- int init_from_text(GTextReadStream *trs, String *wkb);
- int get_data_as_text(String *txt) const;
+ int init_from_wkt(GTextReadStream *trs, String *wkb);
+ int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int num_geometries(uint32 *num) const;
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 1b1f7c75c26..ced5993e293 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -44,12 +44,6 @@ int sortcmp2(void* cmp_arg __attribute__((unused)),
return sortcmp(a,b,a->charset());
}
-int stringcmp2(void* cmp_arg __attribute__((unused)),
- const String *a,const String *b)
-{
- return sortcmp(a,b,&my_charset_bin);
-}
-
int compare_double2(void* cmp_arg __attribute__((unused)),
const double *s, const double *t)
{
diff --git a/sql/sql_analyse.h b/sql/sql_analyse.h
index 2087e6b2b75..3d1cffecaef 100644
--- a/sql/sql_analyse.h
+++ b/sql/sql_analyse.h
@@ -99,8 +99,6 @@ int collect_string(String *element, element_count count,
int sortcmp2(void* cmp_arg __attribute__((unused)),
const String *a,const String *b);
-int stringcmp2(void* cmp_arg __attribute__((unused)),
- const String *a,const String *b);
class field_str :public field_info
{
@@ -117,8 +115,7 @@ public:
max_arg("",default_charset_info), sum(0),
must_be_blob(0), was_zero_fill(0),
was_maybe_zerofill(0), can_be_still_num(1)
- { init_tree(&tree, 0, 0, sizeof(String), a->binary() ?
- (qsort_cmp2) stringcmp2 : (qsort_cmp2) sortcmp2,
+ { init_tree(&tree, 0, 0, sizeof(String), (qsort_cmp2) sortcmp2,
0, (tree_element_free) free_string, NULL); };
void add();
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 6ee423d4ed7..987053d17ca 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -35,8 +35,6 @@ static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
const char *name, const char *alias);
static void free_cache_entry(TABLE *entry);
static void mysql_rm_tmp_tables(void);
-static key_map get_key_map_from_key_list(TABLE *table,
- List<String> *index_list);
extern "C" byte *table_cache_key(const byte *record,uint *length,
@@ -2068,8 +2066,8 @@ bool setup_tables(TABLE_LIST *tables)
}
-static key_map get_key_map_from_key_list(TABLE *table,
- List<String> *index_list)
+key_map get_key_map_from_key_list(TABLE *table,
+ List<String> *index_list)
{
key_map map=0;
List_iterator_fast<String> it(*index_list);
@@ -2155,7 +2153,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
DBUG_ENTER("setup_conds");
thd->set_query_id=1;
- thd->cond_count= 0;
+ thd->lex.current_select->cond_count= 0;
if (*conds)
{
thd->where="where clause";
@@ -2173,7 +2171,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
if (table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
table->on_expr->check_cols(1))
DBUG_RETURN(1);
- thd->cond_count++;
+ thd->lex.current_select->cond_count++;
/* If it's a normal join, add the ON/USING expression to the WHERE */
if (!table->outer_join)
@@ -2219,7 +2217,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
}
}
cond_and->used_tables_cache= t1->map | t2->map;
- thd->cond_count+=cond_and->list.elements;
+ thd->lex.current_select->cond_count+=cond_and->list.elements;
if (!table->outer_join) // Not left join
{
if (!(*conds=and_conds(*conds, cond_and)))
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index fb088b602b1..c233ffd422a 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -107,7 +107,6 @@ THD::THD():user_time(0), is_fatal_error(0),
slave_thread = 0;
variables.pseudo_thread_id= 0;
file_id = 0;
- cond_count=0;
warn_id= 0;
db_charset= global_system_variables.character_set_database;
mysys_var=0;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 157a58cb8fa..f6336cb7dd9 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -366,6 +366,7 @@ struct system_variables
ulong net_retry_count;
ulong net_wait_timeout;
ulong net_write_timeout;
+ ulong preload_buff_size;
ulong query_cache_type;
ulong read_buff_size;
ulong read_rnd_buff_size;
@@ -502,8 +503,23 @@ public:
#ifdef SIGNAL_WITH_VIO_CLOSE
Vio* active_vio;
#endif
- ulonglong next_insert_id,last_insert_id,current_insert_id,
- limit_found_rows;
+ /*
+ next_insert_id is set on SET INSERT_ID= #. This is used as the next
+ generated auto_increment value in handler.cc
+ */
+ ulonglong next_insert_id;
+ /*
+ The insert_id used for the last statement or set by SET LAST_INSERT_ID=#
+ or SELECT LAST_INSERT_ID(#). Used for binary log and returned by
+ LAST_INSERT_ID()
+ */
+ ulonglong last_insert_id;
+ /*
+ Set to the first value that LAST_INSERT_ID() returned for the last
+ statement. When this is set, last_insert_id_used is set to true.
+ */
+ ulonglong current_insert_id;
+ ulonglong limit_found_rows;
ha_rows select_limit, offset_limit, cuted_fields,
sent_row_count, examined_row_count;
table_map used_tables;
@@ -519,7 +535,7 @@ public:
ulong row_count; // Row counter, mainly for errors and warnings
long dbug_thread_id;
pthread_t real_id;
- uint current_tablenr,tmp_table,cond_count;
+ uint current_tablenr,tmp_table;
uint server_status,open_options;
uint32 query_length;
uint32 db_length;
@@ -974,8 +990,7 @@ class user_var_entry
char *value;
ulong length, update_query_id, used_query_id;
Item_result type;
- CHARSET_INFO *var_charset;
- enum Item::coercion var_coercibility;
+ DTCollation collation;
};
/* Class for unique (removing of duplicates) */
diff --git a/sql/sql_client.cc b/sql/sql_client.cc
index 464596f0734..1ae9a23a924 100644
--- a/sql/sql_client.cc
+++ b/sql/sql_client.cc
@@ -18,7 +18,7 @@
This files defines some MySQL C API functions that are server specific
*/
-#include <mysql_priv.h>
+#include "mysql_priv.h"
/*
Function called by my_net_init() to set some check variables
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 1cb0ea2ea5f..470bffe56d9 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -136,7 +136,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
item_list= select_cursor->item_list;
select_cursor->with_wild= 0;
if (setup_ref_array(thd, &select_cursor->ref_pointer_array,
- (item_list.elements + select_cursor->with_sum_func +
+ (item_list.elements + select_cursor->select_items +
select_cursor->order_list.elements +
select_cursor->group_list.elements)) ||
setup_fields(thd, select_cursor->ref_pointer_array, first_table,
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 7c07c08bcac..79d13039784 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -222,6 +222,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
goto err;
}
+ if (err == HA_ERR_RECORD_DELETED)
+ continue;
if (err)
{
if (err != HA_ERR_KEY_NOT_FOUND && err != HA_ERR_END_OF_FILE)
@@ -233,31 +235,24 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
}
goto ok;
}
- if (cond)
+ if (cond && !cond->val_int())
+ continue;
+ if (!err && num_rows >= offset_limit)
{
- err=err;
- if (!cond->val_int())
- continue;
- }
- if (num_rows >= offset_limit)
- {
- if (!err)
+ String *packet = &thd->packet;
+ Item *item;
+ protocol->prepare_for_resend();
+ it.rewind();
+ while ((item=it++))
{
- String *packet = &thd->packet;
- Item *item;
- protocol->prepare_for_resend();
- it.rewind();
- while ((item=it++))
- {
- if (item->send(thd->protocol, &buffer))
- {
- protocol->free(); // Free used
- my_error(ER_OUT_OF_RESOURCES,MYF(0));
- goto err;
- }
- }
- protocol->write();
+ if (item->send(thd->protocol, &buffer))
+ {
+ protocol->free(); // Free used
+ my_error(ER_OUT_OF_RESOURCES,MYF(0));
+ goto err;
+ }
}
+ protocol->write();
}
num_rows++;
}
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index ba7c08ff15f..02fc8591370 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -22,6 +22,8 @@ struct st_find_field
Field *field;
};
+static void free_select(SQL_SELECT *sel);
+
/* Used fields */
static struct st_find_field init_used_fields[]=
@@ -62,6 +64,7 @@ enum enum_used_fields
help_relation_help_keyword_id
};
+
/*
Fill st_find_field structure with pointers to fields
@@ -94,8 +97,8 @@ static bool init_fields(THD *thd, TABLE_LIST *tables,
DBUG_RETURN(0);
}
-/*
+/*
Returns variants of found topic for help (if it is just single topic,
returns description and example, or else returns only names..)
@@ -135,7 +138,7 @@ void memorize_variant_topic(THD *thd, TABLE *topics, int count,
}
else
{
- if (count==1)
+ if (count == 1)
names->push_back(name);
String *new_name= new String;
get_field(mem_root,find_fields[help_topic_name].field,new_name);
@@ -557,7 +560,7 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
String **end= pointers + names->elements;
List_iterator<String> it(*names);
- for ( pos= pointers; pos!=end; (*pos++= it++));
+ for (pos= pointers; pos!=end; (*pos++= it++));
qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp);
@@ -627,6 +630,7 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
return prepare_simple_select(thd,cond,tables,table,error);
}
+
/*
Server-side function 'help'
@@ -783,6 +787,21 @@ int mysqld_help(THD *thd, const char *mask)
res= 0;
send_eof(thd);
+
end:
+ free_select(select_topics_by_name);
+ free_select(select_keyword_by_name);
+ free_select(select_cat_by_name);
+ free_select(select_topics_by_cat);
+ free_select(select_cat_by_cat);
+ free_select(select_root_cats);
+
DBUG_RETURN(res);
}
+
+
+static void free_select(SQL_SELECT *sel)
+{
+ if (sel)
+ delete sel->quick;
+}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 091de9d406f..947205949f1 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -404,13 +404,12 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
{
char buff[160];
if (duplic == DUP_IGNORE)
- sprintf(buff,ER(ER_INSERT_INFO),info.records,
- (lock_type == TL_WRITE_DELAYED) ? 0 :
- info.records-info.copied,
- thd->cuted_fields);
+ sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
+ (lock_type == TL_WRITE_DELAYED) ? (ulong) 0 :
+ (ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
else
- sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted,
- thd->cuted_fields);
+ sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
+ (ulong) info.deleted, (ulong) thd->cuted_fields);
::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff);
}
free_underlaid_joins(thd, &thd->lex.select_lex);
@@ -1494,11 +1493,11 @@ bool select_insert::send_eof()
{
char buff[160];
if (info.handle_duplicates == DUP_IGNORE)
- sprintf(buff,ER(ER_INSERT_INFO),info.records,info.records-info.copied,
- thd->cuted_fields);
+ sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
+ (ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
else
- sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted,
- thd->cuted_fields);
+ sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
+ (ulong) info.deleted, (ulong) thd->cuted_fields);
::send_ok(thd,info.copied+info.deleted,last_insert_id,buff);
return 0;
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 9bc4dfc74e7..425890ab446 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -111,7 +111,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->next_state=MY_LEX_START;
lex->end_of_query=(lex->ptr=buf)+length;
lex->yylineno = 1;
- lex->select_lex.create_refs=lex->in_comment=0;
+ lex->select_lex.parsing_place= SELECT_LEX_NODE::NO_MATTER;
+ lex->in_comment=0;
lex->length=0;
lex->select_lex.in_sum_expr=0;
lex->select_lex.expr_list.empty();
@@ -121,6 +122,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
lex->sql_command=SQLCOM_END;
+ lex->duplicates= DUP_ERROR;
return lex;
}
@@ -555,10 +557,12 @@ int yylex(void *arg, void *yythd)
return(IDENT);
case MY_LEX_IDENT_SEP: // Found ident and now '.'
- lex->next_state=MY_LEX_IDENT_START;// Next is an ident (not a keyword)
yylval->lex_str.str=(char*) lex->ptr;
yylval->lex_str.length=1;
c=yyGet(); // should be '.'
+ lex->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
+ if (!ident_map[yyPeek()]) // Probably ` or "
+ lex->next_state= MY_LEX_START;
return((int) c);
case MY_LEX_NUMBER_IDENT: // number or ident which num-start
@@ -599,7 +603,7 @@ int yylex(void *arg, void *yythd)
yyUnget();
}
// fall through
- case MY_LEX_IDENT_START: // Incomplete ident
+ case MY_LEX_IDENT_START: // We come here after '.'
#if defined(USE_MB) && defined(USE_MB_IDENT)
if (use_mb(cs))
{
@@ -687,6 +691,7 @@ int yylex(void *arg, void *yythd)
}
if (c == delim)
yySkip(); // Skip end `
+ lex->next_state= MY_LEX_START;
return(IDENT);
}
case MY_LEX_SIGNED_NUMBER: // Incomplete signed number
@@ -705,9 +710,9 @@ int yylex(void *arg, void *yythd)
if (c != '.')
{
if (c == '-' && my_isspace(cs,yyPeek()))
- state=MY_LEX_COMMENT;
+ state= MY_LEX_COMMENT;
else
- state = MY_LEX_CHAR; // Return sign as single char
+ state= MY_LEX_CHAR; // Return sign as single char
break;
}
yyUnget(); // Fix for next loop
@@ -866,7 +871,7 @@ int yylex(void *arg, void *yythd)
else
state=MY_LEX_CHAR; // Return '*'
break;
- case MY_LEX_SET_VAR: // Check if ':='
+ case MY_LEX_SET_VAR: // Check if ':='
if (yyPeek() != '=')
{
state=MY_LEX_CHAR; // Return ':'
@@ -902,8 +907,8 @@ int yylex(void *arg, void *yythd)
state = MY_LEX_REAL; // Real
else
{
- state = MY_LEX_CHAR; // return '.'
- lex->next_state=MY_LEX_IDENT_START;// Next is an ident (not a keyword)
+ state= MY_LEX_IDENT_SEP; // return '.'
+ yyUnget(); // Put back '.'
}
break;
case MY_LEX_USER_END: // end '@' of user@hostname
@@ -931,8 +936,11 @@ int yylex(void *arg, void *yythd)
case MY_LEX_SYSTEM_VAR:
yylval->lex_str.str=(char*) lex->ptr;
yylval->lex_str.length=1;
- lex->next_state=MY_LEX_IDENT_OR_KEYWORD;
yySkip(); // Skip '@'
+ lex->next_state= (state_map[yyPeek()] ==
+ MY_LEX_USER_VARIABLE_DELIMITER ?
+ MY_LEX_OPERATOR_OR_IDENT :
+ MY_LEX_IDENT_OR_KEYWORD);
return((int) '@');
case MY_LEX_IDENT_OR_KEYWORD:
/*
@@ -940,7 +948,6 @@ int yylex(void *arg, void *yythd)
We should now be able to handle:
[(global | local | session) .]variable_name
*/
-
while (ident_map[c=yyGet()]) ;
if (c == '.')
lex->next_state=MY_LEX_IDENT_SEP;
@@ -962,8 +969,11 @@ int yylex(void *arg, void *yythd)
void st_select_lex_node::init_query()
{
- no_table_names_allowed= uncacheable= dependent= 0;
+ options= 0;
+ linkage= UNSPECIFIED_TYPE;
+ no_error= no_table_names_allowed= uncacheable= dependent= 0;
ref_pointer_array= 0;
+ cond_count= 0;
}
void st_select_lex_node::init_select()
@@ -973,14 +983,15 @@ void st_select_lex_node::init_select()
order_list.next= (byte**) &order_list.first;
select_limit= HA_POS_ERROR;
offset_limit= 0;
+ select_items= 0;
with_sum_func= 0;
- create_refs= 0;
+ parsing_place= SELECT_LEX_NODE::NO_MATTER;
}
void st_select_lex_unit::init_query()
{
- linkage= GLOBAL_OPTIONS_TYPE;
st_select_lex_node::init_query();
+ linkage= GLOBAL_OPTIONS_TYPE;
global_parameters= this;
select_limit_cnt= HA_POS_ERROR;
offset_limit_cnt= 0;
@@ -994,24 +1005,27 @@ void st_select_lex_unit::init_query()
void st_select_lex::init_query()
{
st_select_lex_node::init_query();
- table_list.elements= 0;
- table_list.first= 0;
- table_list.next= (byte**) &table_list.first;
+ table_list.empty();
item_list.empty();
join= 0;
+ where= 0;
olap= UNSPECIFIED_OLAP_TYPE;
- having_fix_field= 0;
+ insert_select= having_fix_field= 0;
with_wild= 0;
}
void st_select_lex::init_select()
{
st_select_lex_node::init_select();
- group_list.elements= 0;
- group_list.first= 0;
- group_list.next= (byte**) &group_list.first;
+ group_list.empty();
+ type= db= db1= table1= db2= table2= 0;
+ having= 0;
+ group_list.empty();
+ use_index_ptr= ignore_index_ptr= 0;
+ table_join_options= 0;
+ in_sum_expr= with_wild= 0;
options= 0;
- where= having= 0;
+ braces= 0;
when_list.empty();
expr_list.empty();
interval_list.empty();
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index a01c98bb283..faf7e16e54a 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -59,7 +59,7 @@ enum enum_sql_command {
SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
- SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
+ SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, SQLCOM_PRELOAD_KEYS,
SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
SQLCOM_ROLLBACK, SQLCOM_COMMIT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER,
@@ -77,7 +77,6 @@ enum enum_sql_command {
SQLCOM_END
};
-
typedef List<Item> List_item;
typedef struct st_lex_master_info
@@ -191,6 +190,13 @@ protected:
*master, *slave, /* vertical links */
*link_next, **link_prev; /* list of whole SELECT_LEX */
public:
+ enum enum_parsing_place
+ {
+ NO_MATTER,
+ IN_HAVING,
+ SELECT_LIST
+ };
+
ulong options;
enum sub_select_type linkage;
SQL_LIST order_list; /* ORDER clause */
@@ -200,16 +206,18 @@ public:
// Arrays of pointers to top elements of all_fields list
Item **ref_pointer_array;
- uint with_sum_func; /* sum function indicator and number of it */
- bool create_refs;
+ uint select_items; /* number of items in select_list */
+ uint cond_count; /* number of arguments of and/or/xor in where/having */
+ enum_parsing_place parsing_place; /* where we are parsing expression */
+ bool with_sum_func; /* sum function indicator */
bool dependent; /* dependent from outer select subselect */
bool uncacheable; /* result of this query can't be cached */
bool no_table_names_allowed; /* used for global order by */
+ bool no_error; /* suppress error message (convert it to warnings) */
static void *operator new(size_t size)
{
- // TODO: Change to alloc() and explicitely clear elements in constructors
- return (void*) sql_calloc((uint) size);
+ return (void*) sql_alloc((uint) size);
}
static void operator delete(void *ptr,size_t size) {}
st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {}
@@ -352,6 +360,14 @@ public:
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
/* TRUE when having fix field called in processing of this SELECT */
bool having_fix_field;
+ /*
+ TRUE for primary st_select_lex structure of simple INSERT/REPLACE
+ (used for name resolution, see Item_fiels & Item_ref fix_fields,
+ FALSE for INSERT/REPLACE ... SELECT, because it's
+ st_select_lex->table_list will be preprocessed (first table removed)
+ before passing to handle_select)
+ */
+ bool insert_select;
void init_query();
void init_select();
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 12acfb9b5df..d030eaf617c 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -318,8 +318,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
error= -1; // Error on read
goto err;
}
- sprintf(name,ER(ER_LOAD_INFO),info.records,info.deleted,
- info.records-info.copied,thd->cuted_fields);
+ sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted,
+ (ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
send_ok(thd,info.copied+info.deleted,0L,name);
// on the slave thd->query is never initialized
if (!thd->slave_thread)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 47c7026c184..9e670a97e92 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1057,6 +1057,11 @@ bool do_command(THD *thd)
net= &thd->net;
thd->current_tablenr=0;
+ /*
+ indicator of uninitialized lex => normal flow of errors handling
+ (see my_message_sql)
+ */
+ thd->lex.current_select= 0;
packet=0;
old_timeout=net->read_timeout;
@@ -1285,6 +1290,11 @@ restore_user:
mysql_stmt_free(thd, packet);
break;
}
+ case COM_RESET_STMT:
+ {
+ mysql_stmt_reset(thd, packet);
+ break;
+ }
case COM_QUERY:
{
if (alloc_query(thd, packet, packet_length))
@@ -1881,6 +1891,15 @@ mysql_execute_command(THD *thd)
res = mysql_restore_table(thd, tables);
break;
}
+ case SQLCOM_PRELOAD_KEYS:
+ {
+ if (check_db_used(thd, tables) ||
+ check_access(thd, INDEX_ACL, tables->db, &tables->grant.privilege))
+ goto error;
+ res = mysql_preload_keys(thd, tables);
+ break;
+ }
+
#ifndef EMBEDDED_LIBRARY
case SQLCOM_CHANGE_MASTER:
@@ -3379,11 +3398,6 @@ static bool check_merge_table_access(THD *thd, char *db,
{
if (!tmp->db || !tmp->db[0])
tmp->db=db;
- else if (strcmp(tmp->db,db))
- {
- send_error(thd,ER_UNION_TABLES_IN_DIFFERENT_DIR);
- return 1;
- }
}
error=check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
table_list);
@@ -3561,15 +3575,20 @@ mysql_new_select(LEX *lex, bool move_down)
void create_select_for_variable(const char *var_name)
{
+ THD *thd;
LEX *lex;
- LEX_STRING tmp;
+ LEX_STRING tmp, null_lex_string;
DBUG_ENTER("create_select_for_variable");
- lex= current_lex;
+
+ thd= current_thd;
+ lex= &thd->lex;
mysql_init_select(lex);
lex->sql_command= SQLCOM_SELECT;
tmp.str= (char*) var_name;
tmp.length=strlen(var_name);
- add_item_to_list(lex->thd, get_system_var(OPT_SESSION, tmp));
+ bzero((char*) &null_lex_string.str, sizeof(null_lex_string));
+ add_item_to_list(thd, get_system_var(thd, OPT_SESSION, tmp,
+ null_lex_string));
DBUG_VOID_RETURN;
}
@@ -3581,7 +3600,7 @@ void mysql_init_multi_delete(LEX *lex)
lex->select_lex.select_limit= lex->unit.select_limit_cnt=
HA_POS_ERROR;
lex->auxilliary_table_list= lex->select_lex.table_list;
- lex->select_lex.init_query();
+ lex->select_lex.table_list.empty();
}
@@ -4107,6 +4126,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->lock_type= lock_type;
ptr->updating= test(table_options & TL_OPTION_UPDATING);
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
+ ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
ptr->derived= table->sel;
if (use_index)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index,
@@ -4415,6 +4435,7 @@ static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name)
return 0;
}
+
/*
Check if the select is a simple select (not an union)
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index fcddc2d2252..550e4bbe086 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -659,10 +659,13 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
wild_num, conds, og_num, order, group, having, proc,
select_lex, unit, 0))
DBUG_RETURN(1);
+#ifndef EMBEDDED_LIBRARY
if (send_prep_stmt(stmt, fields.elements) ||
thd->protocol_simple.send_fields(&fields, 0) ||
+ net_flush(&thd->net) ||
send_item_params(stmt))
DBUG_RETURN(1);
+#endif
join->cleanup();
}
DBUG_RETURN(0);
@@ -962,7 +965,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
PREP_STMT *stmt;
DBUG_ENTER("mysql_stmt_reset");
- if (!(stmt=find_prepared_statement(thd, stmt_id, "close")))
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "reset")))
{
send_error(thd);
DBUG_VOID_RETURN;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 248496d6b43..0aa7e67a12b 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -31,8 +31,11 @@
#include <ft_global.h>
const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
- "MAYBE_REF","ALL","range","index","fulltext" };
+ "MAYBE_REF","ALL","range","index","fulltext",
+ "ref_or_null"
+};
+static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
DYNAMIC_ARRAY *keyuse);
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
@@ -106,6 +109,8 @@ static int join_read_prev_same(READ_RECORD *info);
static int join_read_prev(READ_RECORD *info);
static int join_ft_read_first(JOIN_TAB *tab);
static int join_ft_read_next(READ_RECORD *info);
+static int join_read_always_key_or_null(JOIN_TAB *tab);
+static int join_read_next_same_or_null(READ_RECORD *info);
static COND *make_cond_for_table(COND *cond,table_map table,
table_map used_table);
static Item* part_of_refkey(TABLE *form,Field *field);
@@ -137,6 +142,7 @@ static ORDER *create_distinct_group(THD *thd, ORDER *order,
static bool test_if_subpart(ORDER *a,ORDER *b);
static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables);
static void calc_group_buffer(JOIN *join,ORDER *group);
+static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
static bool alloc_group_fields(JOIN *join,ORDER *group);
// Create list for using with tempory table
static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
@@ -288,7 +294,7 @@ JOIN::prepare(Item ***rref_pointer_array,
fields_list,
&all_fields, wild_num))) ||
setup_ref_array(thd, rref_pointer_array, (fields_list.elements +
- select_lex->with_sum_func +
+ select_lex->select_items +
og_num)) ||
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
&all_fields, 1) ||
@@ -436,6 +442,9 @@ JOIN::optimize()
DBUG_RETURN(0);
optimized= 1;
+ // Ignore errors of execution if option IGNORE present
+ if (thd->lex.duplicates == DUP_IGNORE)
+ thd->lex.current_select->no_error= 1;
#ifdef HAVE_REF_TO_FIELDS // Not done yet
/* Add HAVING to WHERE if possible */
if (having && !group_list && !sum_func_count)
@@ -1114,12 +1123,12 @@ JOIN::exec()
DBUG_VOID_RETURN;
curr_join->exec_tmp_table2= exec_tmp_table2;
}
- if (group_list)
+ if (curr_join->group_list)
{
thd->proc_info= "Creating sort index";
if (create_sort_index(thd, curr_join->join_tab, curr_join->group_list,
HA_POS_ERROR, HA_POS_ERROR) ||
- alloc_group_fields(curr_join, curr_join->group_list))
+ make_group_fields(this, curr_join))
{
DBUG_VOID_RETURN;
}
@@ -1128,6 +1137,20 @@ JOIN::exec()
thd->proc_info="Copying to group table";
tmp_error= -1;
+ if (curr_join != this)
+ {
+ if (sum_funcs2)
+ {
+ curr_join->sum_funcs= sum_funcs2;
+ curr_join->sum_funcs_end= sum_funcs_end2;
+ }
+ else
+ {
+ curr_join->alloc_func_list();
+ sum_funcs2= curr_join->sum_funcs;
+ sum_funcs_end2= curr_join->sum_funcs_end;
+ }
+ }
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1) ||
(tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
@@ -1186,7 +1209,10 @@ JOIN::exec()
if (curr_join->group || curr_join->tmp_table_param.sum_func_count ||
(procedure && (procedure->flags & PROC_GROUP)))
{
- alloc_group_fields(curr_join, curr_join->group_list);
+ if (make_group_fields(this, curr_join))
+ {
+ DBUG_VOID_RETURN;
+ }
if (!items3)
{
if (!items0)
@@ -1227,7 +1253,7 @@ JOIN::exec()
{
// Some tables may have been const
curr_join->tmp_having->update_used_tables();
- JOIN_TAB *table= &curr_join->join_tab[const_tables];
+ JOIN_TAB *table= &curr_join->join_tab[curr_join->const_tables];
table_map used_tables= curr_join->const_table_map | table->table->map;
Item* sort_table_cond= make_cond_for_table(curr_join->tmp_having,
@@ -1263,7 +1289,7 @@ JOIN::exec()
We can abort sorting after thd->select_limit rows if we there is no
WHERE clause for any tables after the sorted one.
*/
- JOIN_TAB *table= &curr_join->join_tab[const_tables+1];
+ JOIN_TAB *table= &curr_join->join_tab[curr_join->const_tables+1];
JOIN_TAB *end_table= &curr_join->join_tab[tables];
for (; table < end_table ; table++)
{
@@ -1456,8 +1482,9 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
DYNAMIC_ARRAY *keyuse_array)
{
int error;
- uint i,table_count,const_count,found_ref,refs,key,const_ref,eq_part;
- table_map found_const_table_map,all_table_map;
+ uint i,table_count,const_count,key;
+ table_map found_const_table_map, all_table_map, found_ref, refs;
+ key_map const_ref, eq_part;
TABLE **table_vector;
JOIN_TAB *stat,*stat_end,*s,**stat_ref;
KEYUSE *keyuse,*start_keyuse;
@@ -1475,7 +1502,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
join->best_ref=stat_vector;
stat_end=stat+table_count;
- found_const_table_map=all_table_map=0;
+ found_const_table_map= all_table_map=0;
const_count=0;
for (s=stat,i=0 ; tables ; s++,tables=tables->next,i++)
@@ -1632,16 +1659,17 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
key=keyuse->key;
s->keys|= (key_map) 1 << key; // QQ: remove this ?
- refs=const_ref=eq_part=0;
+ refs=const_ref=0;
+ eq_part=0;
do
{
- if (keyuse->val->type() != Item::NULL_ITEM)
+ if (keyuse->val->type() != Item::NULL_ITEM && !keyuse->optimize)
{
if (!((~found_const_table_map) & keyuse->used_tables))
const_ref|= (key_map) 1 << keyuse->keypart;
else
refs|=keyuse->used_tables;
- eq_part|= (uint) 1 << keyuse->keypart;
+ eq_part|= (key_map) 1 << keyuse->keypart;
}
keyuse++;
} while (keyuse->table == table && keyuse->key == key);
@@ -1700,8 +1728,6 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
if (s->worst_seeks < 2.0) // Fix for small tables
s->worst_seeks=2.0;
- /* if (s->type == JT_EQ_REF)
- continue; */
if (s->const_keys)
{
ha_rows records;
@@ -1752,7 +1778,10 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
join->found_const_table_map=found_const_table_map;
if (join->const_tables != join->tables)
+ {
+ optimize_keyuse(join, keyuse_array);
find_best_combination(join,all_table_map & ~join->const_table_map);
+ }
else
{
memcpy((gptr) join->best_positions,(gptr) join->positions,
@@ -1774,13 +1803,26 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
typedef struct key_field_t { // Used when finding key fields
Field *field;
Item *val; // May be empty if diff constant
- uint level,const_level; // QQ: Remove const_level
+ uint level;
+ uint optimize;
bool eq_func;
- bool exists_optimize;
} KEY_FIELD;
+/* Values in optimize */
+#define KEY_OPTIMIZE_EXISTS 1
+#define KEY_OPTIMIZE_REF_OR_NULL 2
-/* merge new key definitions to old ones, remove those not used in both */
+/*
+ Merge new key definitions to old ones, remove those not used in both
+
+ This is called for OR between different levels
+
+ To be able to do 'ref_or_null' we merge a comparison of a column
+ and 'column IS NULL' to one test. This is useful for sub select queries
+ that are internally transformed to something like:
+
+ SELECT * FROM t1 WHERE t1.key=outer_ref_field or t1.key IS NULL
+*/
static KEY_FIELD *
merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
@@ -1802,20 +1844,46 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
{
if (new_fields->val->used_tables())
{
+ /*
+ If the value matches, we can use the key reference.
+ If not, we keep it until we have examined all new values
+ */
if (old->val->eq(new_fields->val, old->field->binary()))
{
- old->level=old->const_level=and_level;
- old->exists_optimize&=new_fields->exists_optimize;
+ old->level= and_level;
+ old->optimize= ((old->optimize & new_fields->optimize &
+ KEY_OPTIMIZE_EXISTS) |
+ ((old->optimize | new_fields->optimize) &
+ KEY_OPTIMIZE_REF_OR_NULL));
}
}
- else if (old->val->eq(new_fields->val, old->field->binary()) &&
- old->eq_func && new_fields->eq_func)
+ else if (old->eq_func && new_fields->eq_func &&
+ old->val->eq(new_fields->val, old->field->binary()))
+
{
- old->level=old->const_level=and_level;
- old->exists_optimize&=new_fields->exists_optimize;
+ old->level= and_level;
+ old->optimize= ((old->optimize & new_fields->optimize &
+ KEY_OPTIMIZE_EXISTS) |
+ ((old->optimize | new_fields->optimize) &
+ KEY_OPTIMIZE_REF_OR_NULL));
}
- else // Impossible; remove it
+ else if (old->eq_func && new_fields->eq_func &&
+ (old->val->is_null() || new_fields->val->is_null()))
{
+ /* field = expression OR field IS NULL */
+ old->level= and_level;
+ old->optimize= KEY_OPTIMIZE_REF_OR_NULL;
+ /* Remember the NOT NULL value */
+ if (old->val->is_null())
+ old->val= new_fields->val;
+ }
+ else
+ {
+ /*
+ We are comparing two different const. In this case we can't
+ use a key-lookup on this so it's better to remove the value
+ and let the range optimzier handle it
+ */
if (old == --first_free) // If last item
break;
*old= *first_free; // Remove old value
@@ -1827,7 +1895,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
/* Remove all not used items */
for (KEY_FIELD *old=start ; old != first_free ;)
{
- if (old->level != and_level && old->const_level != and_level)
+ if (old->level != and_level)
{ // Not used in all levels
if (old == --first_free)
break;
@@ -1840,32 +1908,53 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
}
+/*
+ Add a possible key to array of possible keys if it's usable as a key
+
+ SYNPOSIS
+ add_key_field()
+ key_fields Pointer to add key, if usable
+ and_level And level, to be stored in KEY_FIELD
+ field Field used in comparision
+ eq_func True if we used =, <=> or IS NULL
+ value Value used for comparison with field
+ Is NULL for BETWEEN and IN
+ usable_tables Tables which can be used for key optimization
+
+ NOTES
+ If we are doing a NOT NULL comparison on a NOT NULL field in a outer join
+ table, we store this to be able to do not exists optimization later.
+
+ RETURN
+ *key_fields is incremented if we stored a key in the array
+*/
+
static void
add_key_field(KEY_FIELD **key_fields,uint and_level,
Field *field,bool eq_func,Item *value,
table_map usable_tables)
{
- bool exists_optimize=0;
+ uint exists_optimize= 0;
if (!(field->flags & PART_KEY_FLAG))
{
// Don't remove column IS NULL on a LEFT JOIN table
if (!eq_func || !value || value->type() != Item::NULL_ITEM ||
!field->table->maybe_null || field->null_ptr)
return; // Not a key. Skip it
- exists_optimize=1;
+ exists_optimize= KEY_OPTIMIZE_EXISTS;
}
else
{
table_map used_tables=0;
- if (value && (used_tables=value->used_tables()) &
- (field->table->map | RAND_TABLE_BIT))
+ if (value && ((used_tables=value->used_tables()) &
+ (field->table->map | RAND_TABLE_BIT)))
return;
if (!(usable_tables & field->table->map))
{
if (!eq_func || !value || value->type() != Item::NULL_ITEM ||
!field->table->maybe_null || field->null_ptr)
return; // Can't use left join optimize
- exists_optimize=1;
+ exists_optimize= KEY_OPTIMIZE_EXISTS;
}
else
{
@@ -1880,20 +1969,23 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
return; // Can't be used as eq key
}
- /* Save the following cases:
- Field op constant
- Field LIKE constant where constant doesn't start with a wildcard
- Field = field2 where field2 is in a different table
- Field op formula
- Field IS NULL
- Field IS NOT NULL
+ /*
+ Save the following cases:
+ Field op constant
+ Field LIKE constant where constant doesn't start with a wildcard
+ Field = field2 where field2 is in a different table
+ Field op formula
+ Field IS NULL
+ Field IS NOT NULL
*/
stat[0].key_dependent|=used_tables;
if (value->const_item())
stat[0].const_keys |= possible_keys;
- /* We can't always use indexes when comparing a string index to a
- number. cmp_type() is checked to allow compare of dates to numbers */
+ /*
+ We can't always use indexes when comparing a string index to a
+ number. cmp_type() is checked to allow compare of dates to numbers
+ */
if (!eq_func ||
field->result_type() == STRING_RESULT &&
value->result_type() != STRING_RESULT &&
@@ -1902,11 +1994,11 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
}
}
/* Store possible eq field */
- (*key_fields)->field=field;
- (*key_fields)->eq_func=eq_func;
- (*key_fields)->val=value;
- (*key_fields)->level=(*key_fields)->const_level=and_level;
- (*key_fields)->exists_optimize=exists_optimize;
+ (*key_fields)->field= field;
+ (*key_fields)->eq_func= eq_func;
+ (*key_fields)->val= value;
+ (*key_fields)->level= and_level;
+ (*key_fields)->optimize= exists_optimize;
(*key_fields)++;
}
@@ -1926,12 +2018,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
while ((item=li++))
add_key_fields(stat,key_fields,and_level,item,usable_tables);
for (; org_key_fields != *key_fields ; org_key_fields++)
- {
- if (org_key_fields->const_level == org_key_fields->level)
- org_key_fields->const_level=org_key_fields->level= *and_level;
- else
- org_key_fields->const_level= *and_level;
- }
+ org_key_fields->level= *and_level;
}
else
{
@@ -1958,7 +2045,8 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
case Item_func::OPTIMIZE_NONE:
break;
case Item_func::OPTIMIZE_KEY:
- if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM)
+ if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
+ !(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
add_key_field(key_fields,*and_level,
((Item_field*) (cond_func->key_item()->real_item()))
->field,
@@ -1969,7 +2057,8 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
bool equal_func=(cond_func->functype() == Item_func::EQ_FUNC ||
cond_func->functype() == Item_func::EQUAL_FUNC);
- if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
+ if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
+ !(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
{
add_key_field(key_fields,*and_level,
((Item_field*) (cond_func->arguments()[0])->real_item())
@@ -1978,7 +2067,8 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
(cond_func->arguments()[1]),usable_tables);
}
if (cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
- cond_func->functype() != Item_func::LIKE_FUNC)
+ cond_func->functype() != Item_func::LIKE_FUNC &&
+ !(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT))
{
add_key_field(key_fields,*and_level,
((Item_field*) (cond_func->arguments()[1])->real_item())
@@ -1990,7 +2080,8 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
}
case Item_func::OPTIMIZE_NULL:
/* column_name IS [NOT] NULL */
- if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
+ if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
+ !(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
{
add_key_field(key_fields,*and_level,
((Item_field*) (cond_func->arguments()[0])->real_item())
@@ -2024,7 +2115,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
TABLE *form= field->table;
KEYUSE keyuse;
- if (key_field->eq_func && !key_field->exists_optimize)
+ if (key_field->eq_func && !(key_field->optimize & KEY_OPTIMIZE_EXISTS))
{
for (uint key=0 ; key < form->keys ; key++)
{
@@ -2042,7 +2133,9 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
keyuse.val = key_field->val;
keyuse.key = key;
keyuse.keypart=part;
+ keyuse.keypart_map= (key_part_map) 1 << part;
keyuse.used_tables=key_field->val->used_tables();
+ keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
}
}
@@ -2126,16 +2219,23 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
}
+
static int
sort_keyuse(KEYUSE *a,KEYUSE *b)
{
+ int res;
if (a->table->tablenr != b->table->tablenr)
return (int) (a->table->tablenr - b->table->tablenr);
if (a->key != b->key)
return (int) (a->key - b->key);
if (a->keypart != b->keypart)
return (int) (a->keypart - b->keypart);
- return test(a->used_tables) - test(b->used_tables); // Place const first
+ // Place const values before other ones
+ if ((res= test(a->used_tables) - test(b->used_tables)))
+ return res;
+ /* Place rows that are not 'OPTIMIZE_REF_OR_NULL' first */
+ return (int) ((a->optimize & KEY_OPTIMIZE_REF_OR_NULL) -
+ (b->optimize & KEY_OPTIMIZE_REF_OR_NULL));
}
@@ -2151,30 +2251,28 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
SELECT_LEX *select_lex)
{
uint and_level,i,found_eq_constant;
+ KEY_FIELD *key_fields,*end;
+ if (!(key_fields=(KEY_FIELD*)
+ thd->alloc(sizeof(key_fields[0])*
+ (thd->lex.current_select->cond_count+1)*2)))
+ return TRUE; /* purecov: inspected */
+ and_level=0; end=key_fields;
+ if (cond)
+ add_key_fields(join_tab,&end,&and_level,cond,normal_tables);
+ for (i=0 ; i < tables ; i++)
{
- KEY_FIELD *key_fields,*end;
-
- if (!(key_fields=(KEY_FIELD*)
- thd->alloc(sizeof(key_fields[0])*(thd->cond_count+1)*2)))
- return TRUE; /* purecov: inspected */
- and_level=0; end=key_fields;
- if (cond)
- add_key_fields(join_tab,&end,&and_level,cond,normal_tables);
- for (i=0 ; i < tables ; i++)
+ if (join_tab[i].on_expr)
{
- if (join_tab[i].on_expr)
- {
- add_key_fields(join_tab,&end,&and_level,join_tab[i].on_expr,
- join_tab[i].table->map);
- }
+ add_key_fields(join_tab,&end,&and_level,join_tab[i].on_expr,
+ join_tab[i].table->map);
}
- if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
- return TRUE;
- /* fill keyuse with found key parts */
- for (KEY_FIELD *field=key_fields ; field != end ; field++)
- add_key_part(keyuse,field);
}
+ if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
+ return TRUE;
+ /* fill keyuse with found key parts */
+ for (KEY_FIELD *field=key_fields ; field != end ; field++)
+ add_key_part(keyuse,field);
if (select_lex->ftfunc_list->elements)
{
@@ -2182,9 +2280,10 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
}
/*
- Remove ref if there is a keypart which is a ref and a const.
- Remove keyparts without previous keyparts.
Special treatment for ft-keys.
+ Remove the following things from KEYUSE:
+ - ref if there is a keypart which is a ref and a const.
+ - keyparts without previous keyparts.
*/
if (keyuse->elements)
{
@@ -2202,8 +2301,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
for (i=0 ; i < keyuse->elements-1 ; i++,use++)
{
if (!use->used_tables)
- use->table->const_key_parts[use->key] |=
- (key_part_map) 1 << use->keypart;
+ use->table->const_key_parts[use->key]|= use->keypart_map;
if (use->keypart != FT_KEYPART)
{
if (use->key == prev->key && use->table == prev->table)
@@ -2232,6 +2330,41 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
return FALSE;
}
+/*
+ Update some values in keyuse for faster find_best_combination() loop
+*/
+
+static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
+{
+ KEYUSE *end,*keyuse= dynamic_element(keyuse_array, 0, KEYUSE*);
+
+ for (end= keyuse+ keyuse_array->elements ; keyuse < end ; keyuse++)
+ {
+ table_map map;
+ /*
+ If we find a ref, assume this table matches a proportional
+ part of this table.
+ For example 100 records matching a table with 5000 records
+ gives 5000/100 = 50 records per key
+ Constant tables are ignored.
+ To avoid bad matches, we don't make ref_table_rows less than 100.
+ */
+ keyuse->ref_table_rows= ~(table_map) 0; // If no ref
+ if (keyuse->used_tables &
+ (map= (keyuse->used_tables & ~join->const_table_map &
+ ~OUTER_REF_TABLE_BIT)))
+ {
+ uint tablenr;
+ for (tablenr=0 ; ! (map & 1) ; map>>=1, tablenr++) ;
+ if (map == 1) // Only one table
+ {
+ TABLE *tmp_table=join->all_tables[tablenr];
+ keyuse->ref_table_rows= max(tmp_table->file->records, 100);
+ }
+ }
+ }
+}
+
/*****************************************************************************
Go through all combinations of not marked tables and find the one
@@ -2318,7 +2451,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
uint max_key_part=0;
/* Test how we can use keys */
- rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE; /* Assumed records/key */
+ rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE; // Assumed records/key
for (keyuse=s->keyuse ; keyuse->table == table ;)
{
key_map found_part=0;
@@ -2326,44 +2459,27 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
uint key=keyuse->key;
KEY *keyinfo=table->key_info+key;
bool ft_key=(keyuse->keypart == FT_KEYPART);
+ uint found_ref_or_null= 0;
+ /* Calculate how many key segments of the current key we can use */
start_key=keyuse;
do
{
uint keypart=keyuse->keypart;
+ uint found_part_ref_or_null= KEY_OPTIMIZE_REF_OR_NULL;
do
{
- if (!ft_key)
- {
- table_map map;
- if (!(rest_tables & keyuse->used_tables))
- {
- found_part|= (key_part_map) 1 << keypart;
- found_ref|= keyuse->used_tables;
- }
- /*
- If we find a ref, assume this table matches a proportional
- part of this table.
- For example 100 records matching a table with 5000 records
- gives 5000/100 = 50 records per key
- Constant tables are ignored and to avoid bad matches,
- we don't make rec less than 100.
- */
- if (keyuse->used_tables &
- (map=(keyuse->used_tables & ~join->const_table_map &
- ~OUTER_REF_TABLE_BIT)))
- {
- uint tablenr;
- for (tablenr=0 ; ! (map & 1) ; map>>=1, tablenr++) ;
- if (map == 1) // Only one table
- {
- TABLE *tmp_table=join->all_tables[tablenr];
- if (rec > tmp_table->file->records && rec > 100)
- rec=max(tmp_table->file->records,100);
- }
- }
+ if (!(rest_tables & keyuse->used_tables) &&
+ !(found_ref_or_null & keyuse->optimize))
+ {
+ found_part|=keyuse->keypart_map;
+ found_ref|= keyuse->used_tables;
+ if (rec > keyuse->ref_table_rows)
+ rec= keyuse->ref_table_rows;
+ found_part_ref_or_null&= keyuse->optimize;
}
keyuse++;
+ found_ref_or_null|= found_part_ref_or_null;
} while (keyuse->table == table && keyuse->key == key &&
keyuse->keypart == keypart);
} while (keyuse->table == table && keyuse->key == key);
@@ -2373,8 +2489,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
*/
if (!found_part && !ft_key)
continue; // Nothing usable found
- if (rec == 0)
- rec=1L; // Fix for small tables
+ if (rec < MATCHING_ROWS_IN_OTHER_TABLE)
+ rec= MATCHING_ROWS_IN_OTHER_TABLE; // Fix for small tables
/*
ft-keys require special treatment
@@ -2393,7 +2509,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
/*
Check if we found full key
*/
- if (found_part == PREV_BITS(uint,keyinfo->key_parts))
+ if (found_part == PREV_BITS(uint,keyinfo->key_parts) &&
+ !found_ref_or_null)
{ /* use eq key */
max_key_part= (uint) ~0;
if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
@@ -2446,7 +2563,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
Set tmp to (previous record count) * (records / combination)
*/
if ((found_part & 1) &&
- !(table->file->index_flags(key) & HA_ONLY_WHOLE_INDEX))
+ (!(table->file->index_flags(key) & HA_ONLY_WHOLE_INDEX) ||
+ found_part == PREV_BITS(uint,keyinfo->key_parts)))
{
max_key_part=max_part_bit(found_part);
/*
@@ -2496,6 +2614,12 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
}
records=(ulong) tmp;
}
+ if (found_ref_or_null)
+ {
+ /* We need to do two key searches to find key */
+ tmp*= 2.0;
+ records*= 2.0;
+ }
}
if (table->used_keys & ((key_map) 1 << key))
{
@@ -2745,9 +2869,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
TABLE *table;
KEY *keyinfo;
- /*
- Use best key from find_best
- */
+ /* Use best key from find_best */
table=j->table;
key=keyuse->key;
keyinfo=table->key_info+key;
@@ -2763,14 +2885,22 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
else
{
keyparts=length=0;
+ uint found_part_ref_or_null= 0;
+ /*
+ Calculate length for the used key
+ Stop if there is a missing key part or when we find second key_part
+ with KEY_OPTIMIZE_REF_OR_NULL
+ */
do
{
- if (!((~used_tables) & keyuse->used_tables))
+ if (!(~used_tables & keyuse->used_tables))
{
- if (keyparts == keyuse->keypart)
+ if (keyparts == keyuse->keypart &&
+ !(found_part_ref_or_null & keyuse->optimize))
{
keyparts++;
- length+=keyinfo->key_part[keyuse->keypart].store_length;
+ length+= keyinfo->key_part[keyuse->keypart].store_length;
+ found_part_ref_or_null|= keyuse->optimize;
}
}
keyuse++;
@@ -2793,8 +2923,8 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
j->ref.key_err=1;
keyuse=org_keyuse;
- store_key **ref_key=j->ref.key_copy;
- byte *key_buff=j->ref.key_buff;
+ store_key **ref_key= j->ref.key_copy;
+ byte *key_buff=j->ref.key_buff, *null_ref_key= 0;
if (ftkey)
{
j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
@@ -2822,9 +2952,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
maybe_null ? (char*) key_buff : 0,
keyinfo->key_part[i].length, keyuse->val);
if (thd->is_fatal_error)
- {
return TRUE;
- }
tmp.copy();
}
else
@@ -2832,17 +2960,25 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
keyuse,join->const_table_map,
&keyinfo->key_part[i],
(char*) key_buff,maybe_null);
+ /* Remmeber if we are going to use REF_OR_NULL */
+ if (keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL)
+ null_ref_key= key_buff;
key_buff+=keyinfo->key_part[i].store_length;
}
} /* not ftkey */
*ref_key=0; // end_marker
- if (j->type == JT_FT) /* no-op */;
- else if (j->type == JT_CONST)
- j->table->const_table=1;
+ if (j->type == JT_FT)
+ return 0;
+ if (j->type == JT_CONST)
+ j->table->const_table= 1;
else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY))
- != HA_NOSAME) ||
- keyparts != keyinfo->key_parts)
- j->type=JT_REF; /* Must read with repeat */
+ != HA_NOSAME) || keyparts != keyinfo->key_parts ||
+ null_ref_key)
+ {
+ /* Must read with repeat */
+ j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
+ j->null_ref_key= null_ref_key;
+ }
else if (ref_key == j->ref.key_copy)
{
/*
@@ -3153,6 +3289,7 @@ make_join_readinfo(JOIN *join, uint options)
table->file->extra(HA_EXTRA_KEYREAD);
}
break;
+ case JT_REF_OR_NULL:
case JT_REF:
table->status=STATUS_NO_RECORD;
if (tab->select)
@@ -3163,14 +3300,22 @@ make_join_readinfo(JOIN *join, uint options)
delete tab->quick;
tab->quick=0;
table->file->index_init(tab->ref.key);
- tab->read_first_record= join_read_always_key;
- tab->read_record.read_record= join_read_next_same;
if (table->used_keys & ((key_map) 1 << tab->ref.key) &&
!table->no_keyread)
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
}
+ if (tab->type == JT_REF)
+ {
+ tab->read_first_record= join_read_always_key;
+ tab->read_record.read_record= join_read_next_same;
+ }
+ else
+ {
+ tab->read_first_record= join_read_always_key_or_null;
+ tab->read_record.read_record= join_read_next_same_or_null;
+ }
break;
case JT_FT:
table->status=STATUS_NO_RECORD;
@@ -4142,10 +4287,10 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case STRING_RESULT:
if (item->max_length > 255)
new_field= new Field_blob(item->max_length,maybe_null,
- item->name,table,item->str_value.charset());
+ item->name,table,item->charset());
else
new_field= new Field_string(item->max_length,maybe_null,
- item->name,table,item->str_value.charset());
+ item->name,table,item->charset());
break;
case ROW_RESULT:
default:
@@ -5181,6 +5326,40 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
The different ways to read a record
Returns -1 if row was not found, 0 if row was found and 1 on errors
*****************************************************************************/
+
+/* Help function when we get some an error from the table handler */
+
+static int report_error(TABLE *table, int error)
+{
+ if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND)
+ {
+ table->status= STATUS_GARBAGE;
+ return -1; // key not found; ok
+ }
+ /*
+ Locking reads can legally return also these errors, do not
+ print them to the .err log
+ */
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("Got error %d when reading table '%s'",
+ error, table->path);
+ table->file->print_error(error,MYF(0));
+ return 1;
+}
+
+
+static int safe_index_read(JOIN_TAB *tab)
+{
+ int error;
+ TABLE *table= tab->table;
+ if ((error=table->file->index_read(table->record[0],
+ tab->ref.key_buff,
+ tab->ref.key_length, HA_READ_KEY_EXACT)))
+ return report_error(table, error);
+ return 0;
+}
+
+
static int
join_read_const_table(JOIN_TAB *tab, POSITION *pos)
{
@@ -5235,10 +5414,7 @@ join_read_system(JOIN_TAB *tab)
table->primary_key)))
{
if (error != HA_ERR_END_OF_FILE)
- {
- table->file->print_error(error,MYF(0));
- return 1;
- }
+ return report_error(table, error);
table->null_row=1; // This is ok.
empty_record(table); // Make empty record
return -1;
@@ -5272,15 +5448,7 @@ join_read_const(JOIN_TAB *tab)
table->null_row=1;
empty_record(table);
if (error != HA_ERR_KEY_NOT_FOUND)
- {
- /* Locking reads can legally return also these errors, do not
- print them to the .err log */
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
- sql_print_error("read_const: Got error %d when reading table %s",
- error, table->path);
- table->file->print_error(error,MYF(0));
- return 1;
- }
+ return report_error(table, error);
return -1;
}
store_record(table,record[1]);
@@ -5313,12 +5481,7 @@ join_read_key(JOIN_TAB *tab)
tab->ref.key_buff,
tab->ref.key_length,HA_READ_KEY_EXACT);
if (error && error != HA_ERR_KEY_NOT_FOUND)
- {
- sql_print_error("read_key: Got error %d when reading table '%s'",error,
- table->path);
- table->file->print_error(error,MYF(0));
- return 1;
- }
+ return report_error(table, error);
}
table->null_row=0;
return table->status ? -1 : 0;
@@ -5338,18 +5501,13 @@ join_read_always_key(JOIN_TAB *tab)
tab->ref.key_length,HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND)
- {
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
- sql_print_error("read_const: Got error %d when reading table %s",error,
- table->path);
- table->file->print_error(error,MYF(0));
- return 1;
- }
+ return report_error(table, error);
return -1; /* purecov: inspected */
}
return 0;
}
+
/*
This function is used when optimizing away ORDER BY in
SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
@@ -5368,13 +5526,7 @@ join_read_last_key(JOIN_TAB *tab)
tab->ref.key_length)))
{
if (error != HA_ERR_KEY_NOT_FOUND)
- {
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
- sql_print_error("read_const: Got error %d when reading table %s",error,
- table->path);
- table->file->print_error(error,MYF(0));
- return 1;
- }
+ return report_error(table, error);
return -1; /* purecov: inspected */
}
return 0;
@@ -5401,19 +5553,14 @@ join_read_next_same(READ_RECORD *info)
tab->ref.key_length)))
{
if (error != HA_ERR_END_OF_FILE)
- {
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
- sql_print_error("read_next: Got error %d when reading table %s",error,
- table->path);
- table->file->print_error(error,MYF(0));
- return 1;
- }
+ return report_error(table, error);
table->status= STATUS_GARBAGE;
return -1;
}
return 0;
}
+
static int
join_read_prev_same(READ_RECORD *info)
{
@@ -5422,23 +5569,9 @@ join_read_prev_same(READ_RECORD *info)
JOIN_TAB *tab=table->reginfo.join_tab;
if ((error=table->file->index_prev(table->record[0])))
- {
- if (error != HA_ERR_END_OF_FILE)
- {
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
- sql_print_error("read_next: Got error %d when reading table %s",error,
- table->path);
- table->file->print_error(error,MYF(0));
- error= 1;
- }
- else
- {
- table->status= STATUS_GARBAGE;
- error= -1;
- }
- }
- else if (key_cmp(table, tab->ref.key_buff, tab->ref.key,
- tab->ref.key_length))
+ return report_error(table, error);
+ if (key_cmp(table, tab->ref.key_buff, tab->ref.key,
+ tab->ref.key_length))
{
table->status=STATUS_NOT_FOUND;
error= -1;
@@ -5475,6 +5608,7 @@ join_init_read_record(JOIN_TAB *tab)
return (*tab->read_record.read_record)(&tab->read_record);
}
+
static int
join_read_first(JOIN_TAB *tab)
{
@@ -5492,17 +5626,10 @@ join_read_first(JOIN_TAB *tab)
tab->read_record.file=table->file;
tab->read_record.index=tab->index;
tab->read_record.record=table->record[0];
- error=tab->table->file->index_first(tab->table->record[0]);
- if (error)
+ if ((error=tab->table->file->index_first(tab->table->record[0])))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
- {
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
- sql_print_error("read_first_with_key: Got error %d when reading table",
- error);
- table->file->print_error(error,MYF(0));
- return 1;
- }
+ report_error(table, error);
return -1;
}
return 0;
@@ -5512,23 +5639,13 @@ join_read_first(JOIN_TAB *tab)
static int
join_read_next(READ_RECORD *info)
{
- int error=info->file->index_next(info->record);
- if (error)
- {
- if (error != HA_ERR_END_OF_FILE)
- {
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
- sql_print_error(
- "read_next_with_key: Got error %d when reading table %s",
- error, info->table->path);
- info->file->print_error(error,MYF(0));
- return 1;
- }
- return -1;
- }
+ int error;
+ if ((error=info->file->index_next(info->record)))
+ return report_error(info->table, error);
return 0;
}
+
static int
join_read_last(JOIN_TAB *tab)
{
@@ -5546,19 +5663,8 @@ join_read_last(JOIN_TAB *tab)
tab->read_record.file=table->file;
tab->read_record.index=tab->index;
tab->read_record.record=table->record[0];
- error=tab->table->file->index_last(tab->table->record[0]);
- if (error)
- {
- if (error != HA_ERR_END_OF_FILE)
- {
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
- sql_print_error("read_last_with_key: Got error %d when reading table",
- error, table->path);
- table->file->print_error(error,MYF(0));
- return 1;
- }
- return -1;
- }
+ if ((error= tab->table->file->index_last(tab->table->record[0])))
+ return report_error(table, error);
return 0;
}
@@ -5566,20 +5672,9 @@ join_read_last(JOIN_TAB *tab)
static int
join_read_prev(READ_RECORD *info)
{
- int error=info->file->index_prev(info->record);
- if (error)
- {
- if (error != HA_ERR_END_OF_FILE)
- {
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
- sql_print_error(
- "read_prev_with_key: Got error %d when reading table: %s",
- error,info->table->path);
- info->file->print_error(error,MYF(0));
- return 1;
- }
- return -1;
- }
+ int error;
+ if ((error= info->file->index_prev(info->record)))
+ return report_error(info->table, error);
return 0;
}
@@ -5596,42 +5691,57 @@ join_ft_read_first(JOIN_TAB *tab)
#endif
table->file->ft_init();
- error=table->file->ft_read(table->record[0]);
- if (error)
- {
- if (error != HA_ERR_END_OF_FILE)
- {
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
- sql_print_error("ft_read_first: Got error %d when reading table %s",
- error, table->path);
- table->file->print_error(error,MYF(0));
- return 1;
- }
- return -1;
- }
+ if ((error= table->file->ft_read(table->record[0])))
+ return report_error(table, error);
return 0;
}
static int
join_ft_read_next(READ_RECORD *info)
{
- int error=info->file->ft_read(info->table->record[0]);
- if (error)
- {
- if (error != HA_ERR_END_OF_FILE)
- {
- if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
- sql_print_error("ft_read_next: Got error %d when reading table %s",
- error, info->table->path);
- info->file->print_error(error,MYF(0));
- return 1;
- }
- return -1;
- }
+ int error;
+ if ((error= info->file->ft_read(info->table->record[0])))
+ return report_error(info->table, error);
return 0;
}
+/*
+ Reading of key with key reference and one part that may be NULL
+*/
+
+static int
+join_read_always_key_or_null(JOIN_TAB *tab)
+{
+ int res;
+
+ /* First read according to key which is NOT NULL */
+ *tab->null_ref_key=0;
+ if ((res= join_read_always_key(tab)) >= 0)
+ return res;
+
+ /* Then read key with null value */
+ *tab->null_ref_key= 1;
+ return safe_index_read(tab);
+}
+
+
+static int
+join_read_next_same_or_null(READ_RECORD *info)
+{
+ int error;
+ if ((error= join_read_next_same(info)) >= 0)
+ return error;
+ JOIN_TAB *tab= info->table->reginfo.join_tab;
+
+ /* Test if we have already done a read after null key */
+ if (*tab->null_ref_key)
+ return -1; // All keys read
+ *tab->null_ref_key= 1; // Read null key
+ return safe_index_read(tab);
+}
+
+
/*****************************************************************************
The different end of select functions
These functions returns < 0 when end is reached, 0 on ok and > 0 if a
@@ -6358,10 +6468,13 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
}
ref_key= -1;
- if (tab->ref.key >= 0) // Constant range in WHERE
+ /* Test if constant range in WHERE */
+ if (tab->ref.key >= 0)
{
ref_key= tab->ref.key;
ref_key_parts= tab->ref.key_parts;
+ if (tab->type == JT_REF_OR_NULL)
+ DBUG_RETURN(0);
}
else if (select && select->quick) // Range found by opt_range
{
@@ -7230,9 +7343,11 @@ find_order_in_list(THD *thd, Item **ref_pointer_array,
}
order->in_field_list=0;
Item *it= *order->item;
- if (it->fix_fields(thd, tables, order->item) || it->check_cols(1) ||
+ if (it->fix_fields(thd, tables, order->item) ||
+ //'it' ressigned because fix_field can change it
+ (it= *order->item)->check_cols(1) ||
thd->is_fatal_error)
- return 1; // Wrong field
+ return 1; // Wrong field
uint el= all_fields.elements;
all_fields.push_front(it); // Add new field to field list
ref_pointer_array[el]= it;
@@ -7546,6 +7661,37 @@ calc_group_buffer(JOIN *join,ORDER *group)
join->tmp_table_param.group_null_parts=null_parts;
}
+/*
+ alloc group fields or take prepared (chached)
+
+ SYNOPSYS
+ make_group_fields()
+ main_join - join of current select
+ curr_join - current join (join of current select or temporary copy of it)
+
+ RETURN
+ 0 - ok
+ 1 - failed
+*/
+
+static bool
+make_group_fields(JOIN *main_join, JOIN *curr_join)
+{
+ if (main_join->group_fields_cache.elements)
+ {
+ curr_join->group_fields= main_join->group_fields_cache;
+ curr_join->sort_and_group= 1;
+ }
+ else
+ {
+ if (alloc_group_fields(curr_join, curr_join->group_list))
+ {
+ return (1);
+ }
+ main_join->group_fields_cache= curr_join->group_fields;
+ }
+ return (0);
+}
/*
Get a list of buffers for saveing last group
@@ -7572,6 +7718,7 @@ alloc_group_fields(JOIN *join,ORDER *group)
static int
test_if_group_changed(List<Item_buff> &list)
{
+ DBUG_ENTER("test_if_group_changed");
List_iterator<Item_buff> li(list);
int idx= -1,i;
Item_buff *buff;
@@ -7581,7 +7728,8 @@ test_if_group_changed(List<Item_buff> &list)
if (buff->cmp())
idx=i;
}
- return idx;
+ DBUG_PRINT("info", ("idx: %d", idx));
+ DBUG_RETURN(idx);
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index df21d337b54..7de9007369e 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -27,8 +27,10 @@
typedef struct keyuse_t {
TABLE *table;
Item *val; /* or value if no field */
- uint key,keypart;
table_map used_tables;
+ uint key, keypart, optimize;
+ key_map keypart_map;
+ ha_rows ref_table_rows;
} KEYUSE;
class store_key;
@@ -73,7 +75,7 @@ typedef struct st_join_cache {
*/
enum join_type { JT_UNKNOWN,JT_SYSTEM,JT_CONST,JT_EQ_REF,JT_REF,JT_MAYBE_REF,
- JT_ALL, JT_RANGE, JT_NEXT, JT_FT};
+ JT_ALL, JT_RANGE, JT_NEXT, JT_FT, JT_REF_OR_NULL};
class JOIN;
@@ -85,6 +87,7 @@ typedef struct st_join_table {
QUICK_SELECT *quick;
Item *on_expr;
const char *info;
+ byte *null_ref_key;
int (*read_first_record)(struct st_join_table *tab);
int (*next_select)(JOIN *,struct st_join_table *,bool);
READ_RECORD read_record;
@@ -137,12 +140,14 @@ class JOIN :public Sql_alloc
POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1];
double best_read;
List<Item> *fields;
- List<Item_buff> group_fields;
+ List<Item_buff> group_fields, group_fields_cache;
TABLE *tmp_table;
// used to store 2 possible tmp table of SELECT
TABLE *exec_tmp_table1, *exec_tmp_table2;
THD *thd;
Item_sum **sum_funcs, ***sum_funcs_end;
+ /* second copy of sumfuncs (for queries with 2 temporary tables */
+ Item_sum **sum_funcs2, ***sum_funcs_end2;
Procedure *procedure;
Item *having;
Item *tmp_having; // To store Having when processed temporary table
@@ -196,7 +201,7 @@ class JOIN :public Sql_alloc
send_records(0), found_records(0), examined_rows(0),
exec_tmp_table1(0), exec_tmp_table2(0),
thd(thd_arg),
- sum_funcs(0),
+ sum_funcs(0),sum_funcs2(0),
procedure(0),
having(0), tmp_having(0),
select_options(select_options_arg),
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 1c4954e0276..e8cb59e387e 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -27,8 +27,6 @@
#include "ha_berkeley.h" // For berkeley_show_logs
#endif
-/* extern "C" pthread_mutex_t THR_LOCK_keycache; */
-
static const char *grant_names[]={
"select","insert","update","delete","create","drop","reload","shutdown",
"process","file","grant","references","index","alter"};
@@ -43,15 +41,11 @@ static int mysql_find_files(THD *thd,List<char> *files, const char *db,
static int
store_create_info(THD *thd, TABLE *table, String *packet);
-static void
-append_identifier(THD *thd, String *packet, const char *name);
-
-extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd;
-/****************************************************************************
-** Send list of databases
-** A database is a directory in the mysql_data_home directory
-****************************************************************************/
+/*
+ Report list of databases
+ A database is a directory in the mysql_data_home directory
+*/
int
mysqld_show_dbs(THD *thd,const char *wild)
@@ -1002,8 +996,8 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
}
-static void
-append_identifier(THD *thd, String *packet, const char *name)
+void
+append_identifier(THD *thd, String *packet, const char *name, uint length)
{
char qtype;
if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
@@ -1014,12 +1008,12 @@ append_identifier(THD *thd, String *packet, const char *name)
if (thd->options & OPTION_QUOTE_SHOW_CREATE)
{
packet->append(&qtype, 1);
- packet->append(name, 0, system_charset_info);
+ packet->append(name, length, system_charset_info);
packet->append(&qtype, 1);
}
else
{
- packet->append(name, 0, system_charset_info);
+ packet->append(name, length, system_charset_info);
}
}
@@ -1050,7 +1044,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append("CREATE TEMPORARY TABLE ", 23);
else
packet->append("CREATE TABLE ", 13);
- append_identifier(thd,packet,table->real_name);
+ append_identifier(thd,packet, table->real_name, strlen(table->real_name));
packet->append(" (\n", 3);
Field **ptr,*field;
@@ -1061,7 +1055,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
uint flags = field->flags;
packet->append(" ", 2);
- append_identifier(thd,packet,field->field_name);
+ append_identifier(thd,packet,field->field_name, strlen(field->field_name));
packet->append(' ');
// check for surprises from the previous call to Field::sql_type()
if (type.ptr() != tmp)
@@ -1152,7 +1146,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append("KEY ", 4);
if (!found_primary)
- append_identifier(thd, packet, key_info->name);
+ append_identifier(thd, packet, key_info->name, strlen(key_info->name));
if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
!limited_mysql_mode && !foreign_db_mode)
@@ -1174,7 +1168,8 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append(',');
if (key_part->field)
- append_identifier(thd,packet,key_part->field->field_name);
+ append_identifier(thd,packet,key_part->field->field_name,
+ strlen(key_part->field->field_name));
if (!key_part->field ||
(key_part->length !=
table->field[key_part->fieldnr-1]->key_length() &&
@@ -1190,17 +1185,17 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append(')');
}
+ /*
+ Get possible foreign key definitions stored in InnoDB and append them
+ to the CREATE TABLE statement
+ */
handler *file = table->file;
+ char* for_str= file->get_foreign_key_create_info();
- /* Get possible foreign key definitions stored in InnoDB and append them
- to the CREATE TABLE statement */
-
- char* for_str = file->get_foreign_key_create_info();
-
- if (for_str) {
- packet->append(for_str, strlen(for_str));
-
- file->free_foreign_key_create_info(for_str);
+ if (for_str)
+ {
+ packet->append(for_str, strlen(for_str));
+ file->free_foreign_key_create_info(for_str);
}
packet->append("\n)", 2);
@@ -1267,7 +1262,8 @@ store_create_info(THD *thd, TABLE *table, String *packet)
{
char buff[100];
sprintf(buff," RAID_TYPE=%s RAID_CHUNKS=%d RAID_CHUNKSIZE=%ld",
- my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE);
+ my_raid_type(file->raid_type), file->raid_chunks,
+ file->raid_chunksize/RAID_BLOCK_SIZE);
packet->append(buff);
}
}
@@ -1531,12 +1527,14 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
char buff[1024];
List<Item> field_list;
Protocol *protocol= thd->protocol;
+ LEX_STRING null_lex_str;
DBUG_ENTER("mysqld_show");
field_list.push_back(new Item_empty_string("Variable_name",30));
field_list.push_back(new Item_empty_string("Value",256));
if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1); /* purecov: inspected */
+ null_lex_str.str= 0; // For sys_var->value_ptr()
/* pthread_mutex_lock(&THR_LOCK_keycache); */
pthread_mutex_lock(&LOCK_status);
@@ -1555,7 +1553,8 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
if (show_type == SHOW_SYS)
{
show_type= ((sys_var*) value)->type();
- value= (char*) ((sys_var*) value)->value_ptr(thd, value_type);
+ value= (char*) ((sys_var*) value)->value_ptr(thd, value_type,
+ &null_lex_str);
}
pos= end= buff;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 0a3e8d0db9f..e7d7b08c93c 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -390,6 +390,23 @@ bool String::append(IO_CACHE* file, uint32 arg_length)
return FALSE;
}
+bool String::append_with_prefill(const char *s,uint32 arg_length,
+ uint32 full_length, char fill_char)
+{
+ int t_length= arg_length > full_length ? arg_length : full_length;
+
+ if (realloc(str_length + t_length))
+ return TRUE;
+ t_length= full_length - arg_length;
+ if (t_length > 0)
+ {
+ bfill(Ptr+str_length, t_length, fill_char);
+ str_length=str_length + t_length;
+ }
+ append(s, arg_length);
+ return FALSE;
+}
+
uint32 String::numchars()
{
return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
diff --git a/sql/sql_string.h b/sql/sql_string.h
index e88c9389589..d446d26298b 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -189,6 +189,8 @@ public:
bool append(const char *s,uint32 arg_length=0);
bool append(const char *s,uint32 arg_length, CHARSET_INFO *cs);
bool append(IO_CACHE* file, uint32 arg_length);
+ bool append_with_prefill(const char *s, uint32 arg_length,
+ uint32 full_length, char fill_char);
int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
int strstr_case(const String &s,uint32 offset=0);
int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 60e034302a0..e16d7a0067d 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1404,6 +1404,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
goto err;
continue;
}
+ table->table->pos_in_table_list= table;
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
@@ -1560,6 +1561,28 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
/*
+ Preload specified indexes for a table into key cache
+
+ SYNOPSIS
+ mysql_preload_keys()
+ thd Thread object
+ tables Table list (one table only)
+
+ RETURN VALUES
+ 0 ok
+ -1 error
+*/
+
+int mysql_preload_keys(THD* thd, TABLE_LIST* tables)
+{
+ DBUG_ENTER("mysql_preload_keys");
+ DBUG_RETURN(mysql_admin_table(thd, tables, 0,
+ "preload_keys", TL_READ, 0, 0, 0,
+ &handler::preload_keys));
+}
+
+
+/*
Create a table identical to the specified table
SYNOPSIS
@@ -2402,8 +2425,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
query_cache_invalidate3(thd, table_list, 0);
end_temporary:
- sprintf(tmp_name,ER(ER_INSERT_INFO),(ulong) (copied+deleted),
- (ulong) deleted, thd->cuted_fields);
+ sprintf(tmp_name, ER(ER_INSERT_INFO), (ulong) (copied + deleted),
+ (ulong) deleted, (ulong) thd->cuted_fields);
send_ok(thd,copied+deleted,0L,tmp_name);
thd->some_tables_deleted=0;
DBUG_RETURN(0);
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 35d133789d4..bd97a68e2d3 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -159,7 +159,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
item_list= select_cursor->item_list;
select_cursor->with_wild= 0;
if (setup_ref_array(thd, &select_cursor->ref_pointer_array,
- (item_list.elements + select_cursor->with_sum_func +
+ (item_list.elements + select_cursor->select_items +
select_cursor->order_list.elements +
select_cursor->group_list.elements)) ||
setup_fields(thd, select_cursor->ref_pointer_array, first_table,
@@ -344,7 +344,8 @@ int st_select_lex_unit::exec()
if (select_limit_cnt == HA_POS_ERROR)
thd->options&= ~OPTION_FOUND_ROWS;
fake_select->ftfunc_list= &empty_list;
-
+ fake_select->table_list.link_in_list((byte *)&result_table_list,
+ (byte **)&result_table_list.next);
res= mysql_select(thd, &ref_pointer_array, &result_table_list,
0, item_list, NULL,
global_parameters->order_list.elements,
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 989d17b006b..e1c28dd0e4d 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -373,8 +373,8 @@ int mysql_update(THD *thd,
else
{
char buff[80];
- sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated,
- (long) thd->cuted_fields);
+ sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
+ (ulong) thd->cuted_fields);
send_ok(thd,
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
thd->insert_id_used ? thd->insert_id() : 0L,buff);
@@ -993,8 +993,8 @@ bool multi_update::send_eof()
}
- sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated,
- (long) thd->cuted_fields);
+ sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
+ (ulong) thd->cuted_fields);
::send_ok(thd,
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
thd->insert_id_used ? thd->insert_id() : 0L,buff);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a109ca23891..0bb20b74016 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -163,6 +163,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token VARIANCE_SYM
%token STOP_SYM
%token SUM_SYM
+%token ADDDATE_SYM
%token SUPER_SYM
%token TRUNCATE_SYM
%token UNLOCK_SYM
@@ -256,6 +257,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token KEY_SYM
%token LEADING
%token LEAST_SYM
+%token LEAVES
%token LEVEL_SYM
%token LEX_HOSTNAME
%token LIKE
@@ -430,6 +432,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token VARYING
%token ZEROFILL
+%token ADDDATE_SYM
%token AGAINST
%token ATAN
%token BETWEEN_SYM
@@ -444,6 +447,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DATE_ADD_INTERVAL
%token DATE_SUB_INTERVAL
%token DAY_HOUR_SYM
+%token DAY_MICROSECOND_SYM
%token DAY_MINUTE_SYM
%token DAY_SECOND_SYM
%token DAY_SYM
@@ -466,6 +470,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token GEOMETRYCOLLECTION
%token GROUP_CONCAT_SYM
%token GROUP_UNIQUE_USERS
+%token HOUR_MICROSECOND_SYM
%token HOUR_MINUTE_SYM
%token HOUR_SECOND_SYM
%token HOUR_SYM
@@ -480,6 +485,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token LOCATE
%token MAKE_SET_SYM
%token MASTER_POS_WAIT
+%token MICROSECOND_SYM
+%token MINUTE_MICROSECOND_SYM
%token MINUTE_SECOND_SYM
%token MINUTE_SYM
%token MODE_SYM
@@ -504,7 +511,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token RIGHT
%token ROUND
%token SECOND_SYM
+%token SECOND_MICROSECOND_SYM
%token SHARE_SYM
+%token SUBDATE_SYM
%token SUBSTRING
%token SUBSTRING_INDEX
%token TRIM
@@ -560,7 +569,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
- NCHAR_STRING
+ NCHAR_STRING opt_component
%type <lex_str_ptr>
opt_table_alias
@@ -579,7 +588,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
type int_type real_type order_dir opt_field_spec lock_option
udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type opt_var_ident_type
- delete_option opt_temporary all_or_any opt_distinct
+ delete_option opt_temporary all_or_any opt_distinct opt_ignore_leaves
%type <ulong_num>
ULONG_NUM raid_types merge_insert_types
@@ -608,7 +617,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
key_alg opt_btree_or_rtree
%type <string_list>
- key_usage_list
+ key_usage_list
%type <key_part>
key_part
@@ -656,10 +665,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <NONE>
query verb_clause create change select do drop insert replace insert2
insert_values update delete truncate rename
- show describe load alter optimize flush
+ show describe load alter optimize preload flush
reset purge begin commit rollback slave master_def master_defs
repair restore backup analyze check start
field_list field_list_item field_spec kill column_def key_def
+ preload_list preload_keys
select_item_list select_item values_list no_braces
opt_limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
@@ -728,6 +738,7 @@ verb_clause:
| lock
| kill
| optimize
+ | preload
| purge
| rename
| repair
@@ -934,8 +945,13 @@ create3:
LEX *lex=Lex;
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST;
}
- select_options select_item_list opt_select_from union_clause {}
+ select_options select_item_list
+ {
+ Select->parsing_place= SELECT_LEX_NODE::NO_MATTER;
+ }
+ opt_select_from union_clause {}
;
opt_as:
@@ -1524,6 +1540,10 @@ opt_ident:
/* empty */ { $$=(char*) 0; } /* Defaultlength */
| field_ident { $$=$1.str; };
+opt_component:
+ /* empty */ { $$.str= 0; $$.length= 0; }
+ | '.' ident { $$=$2; };
+
string_list:
text_string { Lex->interval_list.push_back($1); }
| string_list ',' text_string { Lex->interval_list.push_back($3); };
@@ -1589,6 +1609,7 @@ alter_list_item:
LEX *lex=Lex;
lex->length=lex->dec=0; lex->type=0; lex->interval=0;
lex->default_value=lex->comment=0;
+ lex->charset= NULL;
lex->simple_alter=0;
}
type opt_attribute
@@ -1835,6 +1856,55 @@ table_to_table:
YYABORT;
};
+preload:
+ LOAD INDEX INTO CACHE_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command=SQLCOM_PRELOAD_KEYS;
+ }
+ preload_list
+ {}
+ ;
+
+preload_list:
+ preload_keys
+ | preload_list ',' preload_keys;
+
+preload_keys:
+ table_ident preload_keys_spec opt_ignore_leaves
+ {
+ LEX *lex=Lex;
+ SELECT_LEX *sel= &lex->select_lex;
+ if (!sel->add_table_to_list(lex->thd, $1, NULL, $3,
+ TL_READ,
+ sel->get_use_index(),
+ (List<String> *)0))
+ YYABORT;
+ }
+ ;
+
+preload_keys_spec:
+ keys_or_index { Select->select_lex()->interval_list.empty(); }
+ preload_key_list_or_empty
+ {
+ LEX *lex=Lex;
+ SELECT_LEX *sel= &lex->select_lex;
+ sel->use_index= sel->interval_list;
+ sel->use_index_ptr= &sel->use_index;
+ }
+ ;
+
+preload_key_list_or_empty:
+ /* empty */
+ | '(' key_usage_list2 ')' {}
+ ;
+
+opt_ignore_leaves:
+ /* empty */
+ { $$= 0; }
+ | IGNORE_SYM LEAVES { $$= TL_OPTION_IGNORE_LEAVES; }
+ ;
+
/*
Select : retrieve data from table
*/
@@ -1895,8 +1965,13 @@ select_part2:
lex->lock_option= TL_READ; /* Only for global SELECT */
if (sel->linkage != UNION_TYPE)
mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST;
+ }
+ select_options select_item_list
+ {
+ Select->parsing_place= SELECT_LEX_NODE::NO_MATTER;
}
- select_options select_item_list select_into select_lock_type;
+ select_into select_lock_type;
select_into:
opt_limit_clause {}
@@ -2034,9 +2109,9 @@ all_or_any: ALL { $$ = 1; }
/* expressions that begin with 'expr' */
expr_expr:
expr IN_SYM '(' expr_list ')'
- { $$= new Item_func_in($1,*$4); }
+ { $4->push_front($1); $$= new Item_func_in(*$4); }
| expr NOT IN_SYM '(' expr_list ')'
- { $$= new Item_func_not(new Item_func_in($1,*$5)); }
+ { $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
| expr IN_SYM in_subselect
{ $$= new Item_in_subselect(YYTHD, $1, $3); }
| expr NOT IN_SYM in_subselect
@@ -2136,9 +2211,9 @@ no_in_expr:
/* expressions that begin with 'expr' that does NOT follow AND */
no_and_expr:
no_and_expr IN_SYM '(' expr_list ')'
- { $$= new Item_func_in($1,*$4); }
+ { $4->push_front($1); $$= new Item_func_in(*$4); }
| no_and_expr NOT IN_SYM '(' expr_list ')'
- { $$= new Item_func_not(new Item_func_in($1,*$5)); }
+ { $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
| no_and_expr IN_SYM in_subselect
{ $$= new Item_in_subselect(YYTHD, $1, $3); }
| no_and_expr NOT IN_SYM in_subselect
@@ -2213,9 +2288,9 @@ simple_expr:
$$= new Item_func_get_user_var($2);
Lex->uncacheable();
}
- | '@' '@' opt_var_ident_type ident_or_text
+ | '@' '@' opt_var_ident_type ident_or_text opt_component
{
- if (!($$= get_system_var((enum_var_type) $3, $4)))
+ if (!($$= get_system_var(YYTHD, (enum_var_type) $3, $4, $5)))
YYABORT;
}
| sum_expr
@@ -2271,6 +2346,10 @@ simple_expr:
{ $$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5);}
| FUNC_ARG3 '(' expr ',' expr ',' expr ')'
{ $$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7);}
+ | ADDDATE_SYM '(' expr ',' expr ')'
+ { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 0);}
+ | ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
+ { $$= new Item_date_add_interval($3, $6, $7, 0); }
| ATAN '(' expr ')'
{ $$= new Item_func_atan($3); }
| ATAN '(' expr ',' expr ')'
@@ -2305,8 +2384,12 @@ simple_expr:
$$= new Item_func_database();
Lex->safe_to_cache_query=0;
}
+ | DATE_SYM '(' expr ')'
+ { $$= new Item_date_typecast($3); }
+ | DAY_SYM '(' expr ')'
+ { $$= new Item_func_dayofmonth($3); }
| ELT_FUNC '(' expr ',' expr_list ')'
- { $$= new Item_func_elt($3, *$5); }
+ { $5->push_front($3); $$= new Item_func_elt(*$5); }
| MAKE_SET_SYM '(' expr ',' expr_list ')'
{ $$= new Item_func_make_set($3, *$5); }
| ENCRYPT '(' expr ')'
@@ -2344,7 +2427,7 @@ simple_expr:
$$= new Item_func_date_format (new Item_func_from_unixtime($3),$5,0);
}
| FIELD_FUNC '(' expr ',' expr_list ')'
- { $$= new Item_func_field($3, *$5); }
+ { $5->push_front($3); $$= new Item_func_field(*$5); }
| GEOMFROMTEXT '(' expr ')'
{ $$= new Item_func_geometry_from_text($3); }
| GEOMFROMTEXT '(' expr ',' expr ')'
@@ -2377,7 +2460,7 @@ simple_expr:
}
| LAST_INSERT_ID '(' ')'
{
- $$= get_system_var(OPT_SESSION, "last_insert_id", 14,
+ $$= get_system_var(YYTHD, OPT_SESSION, "last_insert_id", 14,
"last_insert_id()");
Lex->safe_to_cache_query= 0;
}
@@ -2421,6 +2504,8 @@ simple_expr:
$$= new Item_master_pos_wait($3, $5, $7);
Lex->safe_to_cache_query=0;
}
+ | MICROSECOND_SYM '(' expr ')'
+ { $$= new Item_func_microsecond($3); }
| MINUTE_SYM '(' expr ')'
{ $$= new Item_func_minute($3); }
| MOD_SYM '(' expr ',' expr ')'
@@ -2482,6 +2567,10 @@ simple_expr:
| ROUND '(' expr ')'
{ $$= new Item_func_round($3, new Item_int((char*)"0",0,1),0); }
| ROUND '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,0); }
+ | SUBDATE_SYM '(' expr ',' expr ')'
+ { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 1);}
+ | SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
+ { $$= new Item_date_add_interval($3, $6, $7, 1); }
| SECOND_SYM '(' expr ')'
{ $$= new Item_func_second($3); }
| SUBSTRING '(' expr ',' expr ',' expr ')'
@@ -2494,6 +2583,12 @@ simple_expr:
{ $$= new Item_func_substr($3,$5); }
| SUBSTRING_INDEX '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_substr_index($3,$5,$7); }
+ | TIME_SYM '(' expr ')'
+ { $$= new Item_time_typecast($3); }
+ | TIMESTAMP '(' expr ')'
+ { $$= new Item_datetime_typecast($3); }
+ | TIMESTAMP '(' expr ',' expr ')'
+ { $$= new Item_func_add_time($3, $5, 1, 0); }
| TRIM '(' expr ')'
{ $$= new Item_func_trim($3); }
| TRIM '(' LEADING expr FROM expr ')'
@@ -2910,15 +3005,20 @@ using_list:
interval:
DAY_HOUR_SYM { $$=INTERVAL_DAY_HOUR; }
+ | DAY_MICROSECOND_SYM { $$=INTERVAL_DAY_MICROSECOND; }
| DAY_MINUTE_SYM { $$=INTERVAL_DAY_MINUTE; }
| DAY_SECOND_SYM { $$=INTERVAL_DAY_SECOND; }
| DAY_SYM { $$=INTERVAL_DAY; }
+ | HOUR_MICROSECOND_SYM { $$=INTERVAL_HOUR_MICROSECOND; }
| HOUR_MINUTE_SYM { $$=INTERVAL_HOUR_MINUTE; }
| HOUR_SECOND_SYM { $$=INTERVAL_HOUR_SECOND; }
| HOUR_SYM { $$=INTERVAL_HOUR; }
+ | MICROSECOND_SYM { $$=INTERVAL_MICROSECOND; }
+ | MINUTE_MICROSECOND_SYM { $$=INTERVAL_MINUTE_MICROSECOND; }
| MINUTE_SECOND_SYM { $$=INTERVAL_MINUTE_SECOND; }
| MINUTE_SYM { $$=INTERVAL_MINUTE; }
| MONTH_SYM { $$=INTERVAL_MONTH; }
+ | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; }
| SECOND_SYM { $$=INTERVAL_SECOND; }
| YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; }
| YEAR_SYM { $$=INTERVAL_YEAR; };
@@ -2950,10 +3050,15 @@ where_clause:
having_clause:
/* empty */
- | HAVING { Select->select_lex()->create_refs= 1; } expr
+ | HAVING
+ {
+ Select->select_lex()->parsing_place= SELECT_LEX_NODE::IN_HAVING;
+ }
+ expr
{
SELECT_LEX *sel= Select->select_lex();
- sel->having= $3; sel->create_refs=0;
+ sel->having= $3;
+ sel->parsing_place= SELECT_LEX_NODE::NO_MATTER;
if ($3)
$3->top_level_item();
}
@@ -3296,6 +3401,7 @@ insert:
lex->sql_command = SQLCOM_INSERT;
/* for subselects */
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
+ lex->select_lex.insert_select= 1;
} insert_lock_option
opt_ignore insert2
{
@@ -3311,6 +3417,7 @@ replace:
LEX *lex=Lex;
lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE;
+ lex->select_lex.insert_select= 1;
}
replace_lock_option insert2
{
@@ -3375,8 +3482,18 @@ insert_values:
SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT);
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex);
+ /*
+ it is not simple select => table list will be
+ preprocessed before passing to handle_select
+ */
+ lex->select_lex.insert_select= 0;
+ lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST;
+ }
+ select_options select_item_list
+ {
+ Select->parsing_place= SELECT_LEX_NODE::NO_MATTER;
}
- select_options select_item_list opt_select_from select_lock_type
+ opt_select_from select_lock_type
union_clause {}
;
@@ -3499,7 +3616,6 @@ delete:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_DELETE;
- lex->select_lex.options= 0;
lex->lock_option= lex->thd->update_lock_default;
lex->select_lex.init_order();
}
@@ -3626,7 +3742,7 @@ show_param:
Lex->mi.pos = $12;
Lex->mi.server_id = $16;
}
- | BINARY LOGS_SYM
+ | master_or_binary LOGS_SYM
{
Lex->sql_command = SQLCOM_SHOW_BINLOGS;
}
@@ -3686,6 +3802,8 @@ show_param:
{ Lex->sql_command= SQLCOM_SHOW_CHARSETS; }
| COLLATION_SYM wild
{ Lex->sql_command= SQLCOM_SHOW_COLLATIONS; }
+ | BERKELEY_DB_SYM LOGS_SYM
+ { Lex->sql_command= SQLCOM_SHOW_LOGS; }
| LOGS_SYM
{ Lex->sql_command= SQLCOM_SHOW_LOGS; }
| GRANTS FOR_SYM user
@@ -3716,6 +3834,10 @@ show_param:
Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
};
+master_or_binary:
+ MASTER_SYM
+ | BINARY;
+
opt_db:
/* empty */ { $$= 0; }
| from_or_in ident { $$= $2.str; };
@@ -3833,8 +3955,7 @@ purge:
;
purge_options:
- LOGS_SYM purge_option
- | MASTER_SYM LOGS_SYM purge_option
+ master_or_binary LOGS_SYM purge_option
;
purge_option:
@@ -4057,7 +4178,10 @@ simple_ident:
ident
{
SELECT_LEX_NODE *sel=Select;
- $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str);
+ $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
+ sel->get_in_sum_expr() > 0) ?
+ (Item*) new Item_field(NullS,NullS,$1.str) :
+ (Item*) new Item_ref(NullS,NullS,$1.str);
}
| ident '.' ident
{
@@ -4070,7 +4194,10 @@ simple_ident:
ER(ER_TABLENAME_NOT_ALLOWED_HERE),
MYF(0), $1.str, thd->where);
}
- $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str);
+ $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
+ sel->get_in_sum_expr() > 0) ?
+ (Item*) new Item_field(NullS,$1.str,$3.str) :
+ (Item*) new Item_ref(NullS,$1.str,$3.str);
}
| '.' ident '.' ident
{
@@ -4083,7 +4210,10 @@ simple_ident:
ER(ER_TABLENAME_NOT_ALLOWED_HERE),
MYF(0), $2.str, thd->where);
}
- $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str);
+ $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
+ sel->get_in_sum_expr() > 0) ?
+ (Item*) new Item_field(NullS,$2.str,$4.str) :
+ (Item*) new Item_ref(NullS,$2.str,$4.str);
}
| ident '.' ident '.' ident
{
@@ -4096,7 +4226,14 @@ simple_ident:
ER(ER_TABLENAME_NOT_ALLOWED_HERE),
MYF(0), $3.str, thd->where);
}
- $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str);
+ $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
+ sel->get_in_sum_expr() > 0) ?
+ (Item*) new Item_field((YYTHD->client_capabilities &
+ CLIENT_NO_SCHEMA ? NullS : $1.str),
+ $3.str, $5.str) :
+ (Item*) new Item_ref((YYTHD->client_capabilities &
+ CLIENT_NO_SCHEMA ? NullS : $1.str),
+ $3.str, $5.str);
};
@@ -4205,6 +4342,7 @@ user:
keyword:
ACTION {}
+ | ADDDATE_SYM {}
| AFTER_SYM {}
| AGAINST {}
| AGGREGATE_SYM {}
@@ -4279,6 +4417,7 @@ keyword:
| INSERT_METHOD {}
| RELAY_THREAD {}
| LAST_SYM {}
+ | LEAVES {}
| LEVEL_SYM {}
| LINESTRING {}
| LOCAL_SYM {}
@@ -4299,6 +4438,7 @@ keyword:
| MEDIUM_SYM {}
| MERGE_SYM {}
| MEMORY_SYM {}
+ | MICROSECOND_SYM {}
| MINUTE_SYM {}
| MIN_ROWS {}
| MODIFY_SYM {}
@@ -4364,6 +4504,7 @@ keyword:
| STATUS_SYM {}
| STOP_SYM {}
| STRING_SYM {}
+ | SUBDATE_SYM {}
| SUBJECT_SYM {}
| SUPER_SYM {}
| TEMPORARY {}
@@ -4494,6 +4635,27 @@ internal_variable_name:
YYABORT;
$$=tmp;
}
+ | ident '.' ident
+ {
+ sys_var *tmp=find_sys_var($3.str, $3.length);
+ if (!tmp)
+ YYABORT;
+ if (!tmp->is_struct())
+ net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str);
+ tmp->base_name= $1;
+ $$=tmp;
+ }
+ | DEFAULT '.' ident
+ {
+ sys_var *tmp=find_sys_var($3.str, $3.length);
+ if (!tmp)
+ YYABORT;
+ if (!tmp->is_struct())
+ net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str);
+ tmp->base_name.str= (char*) "default";
+ tmp->base_name.length= 7;
+ $$=tmp;
+ }
;
isolation_types:
diff --git a/sql/table.cc b/sql/table.cc
index 908d6807450..0fc2a09f749 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -395,7 +395,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
else
{
- if (!(charset=get_charset((uint) strpos[14], MYF(0))))
+ if (!strpos[14])
+ charset= &my_charset_bin;
+ else if (!(charset=get_charset((uint) strpos[14], MYF(0))))
charset= (outparam->table_charset ? outparam->table_charset:
default_charset_info);
}
diff --git a/sql/table.h b/sql/table.h
index c9f35887a27..096053ff338 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -182,6 +182,7 @@ typedef struct st_table_list
bool straight; /* optimize with prev table */
bool updating; /* for replicate-do/ignore table */
bool force_index; /* Prefer index over table scan */
+ bool ignore_leaves; /* Preload only non-leaf nodes */
} TABLE_LIST;
typedef struct st_changed_table_list
diff --git a/sql/time.cc b/sql/time.cc
index b6ca306e523..70ae8dcd8ed 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -432,6 +432,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
l_time->minute=date[4];
l_time->second=date[5];
l_time->second_part=date[6];
+ l_time->neg= 0;
DBUG_RETURN(l_time->time_type=
(number_of_fields <= 3 ? TIMESTAMP_DATE : TIMESTAMP_FULL));
}
@@ -581,7 +582,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
/* Get fractional second part */
if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
{
- uint field_length=3;
+ uint field_length=5;
str++; value=(uint) (uchar) (*str - '0');
while (++str != end &&
my_isdigit(&my_charset_latin1,str[0]) &&
@@ -604,6 +605,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
l_time->minute=date[2];
l_time->second=date[3];
l_time->second_part=date[4];
+ l_time->time_type= TIMESTAMP_TIME;
/* Check if there is garbage at end of the TIME specification */
if (str != end && current_thd->count_cuted_fields)
@@ -636,3 +638,13 @@ void localtime_to_TIME(TIME *to, struct tm *from)
to->minute= (int) from->tm_min;
to->second= (int) from->tm_sec;
}
+
+void calc_time_from_sec(TIME *to, long seconds, long microseconds)
+{
+ long t_seconds;
+ to->hour= seconds/3600L;
+ t_seconds= seconds%3600L;
+ to->minute= t_seconds/60L;
+ to->second= t_seconds%60L;
+ to->second_part= microseconds;
+}
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 5e723281d3f..3e634f54b4f 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -460,8 +460,10 @@ static bool pack_fields(File file,List<create_field> &create_fields)
buff[13]= (uchar) field->sql_type;
if (field->sql_type == FIELD_TYPE_GEOMETRY)
buff[14]= (uchar) field->geom_type;
- else
+ else if (field->charset)
buff[14]= (uchar) field->charset->number;
+ else
+ buff[14]= 0; // Numerical
int2store(buff+15, field->comment.length);
comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id);
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index f5da95571c4..1982b9e3ba8 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -2030,7 +2030,7 @@ CHARSET_INFO my_charset_utf8_bin=
3, /* mbmaxlen */
0,
&my_charset_handler,
- &my_collation_ci_handler
+ &my_collation_bin_handler
};
diff --git a/tests/client_test.c b/tests/client_test.c
index d22aa900a4e..2741da1bbba 100644
--- a/tests/client_test.c
+++ b/tests/client_test.c
@@ -7327,6 +7327,136 @@ static void test_free_store_result()
mysql_stmt_close(stmt);
}
+/********************************************************
+ To test SQLmode
+*********************************************************/
+
+static void test_sqlmode()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[2];
+ char c1[5], c2[5];
+ int rc;
+
+ myheader("test_sqlmode");
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_piping");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_piping(name varchar(10))");
+ myquery(rc);
+
+ /* PIPES_AS_CONCAT */
+ strcpy(query,"SET SQL_MODE=\"PIPES_AS_CONCAT\"");
+ fprintf(stdout,"\n With %s", query);
+ rc = mysql_query(mysql,query);
+ myquery(rc);
+
+ strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
+ fprintf(stdout,"\n query: %s", query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ fprintf(stdout,"\n total parameters: %ld", mysql_param_count(stmt));
+
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (char *)c1;
+ bind[0].buffer_length= 2;
+ bind[0].is_null= 0;
+ bind[0].length= 0;
+
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= (char *)c2;
+ bind[1].buffer_length= 3;
+ bind[1].is_null= 0;
+ bind[1].length= 0;
+
+ rc = mysql_bind_param(stmt, bind);
+ mystmt(stmt,rc);
+
+ strcpy(c1,"My"); strcpy(c2, "SQL");
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ mysql_stmt_close(stmt);
+ verify_col_data("test_piping","name","MySQL");
+
+ rc = mysql_query(mysql,"DELETE FROM test_piping");
+ myquery(rc);
+
+ strcpy(query, "SELECT connection_id ()");
+ fprintf(stdout,"\n query: %s", query);
+ stmt = mysql_prepare(mysql, query, 70);
+ mystmt_init_r(stmt);
+
+ /* ANSI */
+ strcpy(query,"SET SQL_MODE=\"ANSI\"");
+ fprintf(stdout,"\n With %s", query);
+ rc = mysql_query(mysql,query);
+ myquery(rc);
+
+ strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
+ fprintf(stdout,"\n query: %s", query);
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+ fprintf(stdout,"\n total parameters: %ld", mysql_param_count(stmt));
+
+ rc = mysql_bind_param(stmt, bind);
+ mystmt(stmt,rc);
+
+ strcpy(c1,"My"); strcpy(c2, "SQL");
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ mysql_stmt_close(stmt);
+ verify_col_data("test_piping","name","MySQL");
+
+ /* ANSI mode spaces ... */
+ strcpy(query, "SELECT connection_id ()");
+ fprintf(stdout,"\n query: %s", query);
+ stmt = mysql_prepare(mysql, query, 70);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+ fprintf(stdout,"\n returned 1 row\n");
+
+ mysql_stmt_close(stmt);
+
+ /* IGNORE SPACE MODE */
+ strcpy(query,"SET SQL_MODE=\"IGNORE_SPACE\"");
+ fprintf(stdout,"\n With %s", query);
+ rc = mysql_query(mysql,query);
+ myquery(rc);
+
+ strcpy(query, "SELECT connection_id ()");
+ fprintf(stdout,"\n query: %s", query);
+ stmt = mysql_prepare(mysql, query, 70);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+ fprintf(stdout,"\n returned 1 row");
+
+ mysql_stmt_close(stmt);
+}
+
+
/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -7467,10 +7597,6 @@ int main(int argc, char **argv)
start_time= time((time_t *)0);
client_query(); /* simple client query test */
- test_mem_overun();
- test_list_fields();
- test_fetch_offset(); /* to test mysql_fetch_column with offset */
- test_fetch_column(); /* to test mysql_fetch_column */
#if NOT_YET_WORKING
/* Used for internal new development debugging */
test_drop_temp(); /* to test DROP TEMPORARY TABLE Access checks */
@@ -7572,6 +7698,11 @@ int main(int argc, char **argv)
test_free_result(); /* test mysql_stmt_free_result() */
test_free_store_result(); /* test to make sure stmt results are cleared
during stmt_free_result() */
+ test_mem_overun(); /* memory ovverun bug */
+ test_list_fields(); /* list_fields test */
+ test_fetch_offset(); /* to test mysql_fetch_column with offset */
+ test_fetch_column(); /* to test mysql_fetch_column */
+ test_sqlmode(); /* test for SQL_MODE */
end_time= time((time_t *)0);
total_time+= difftime(end_time, start_time);