diff options
555 files changed, 38121 insertions, 8503 deletions
diff --git a/.bzrignore b/.bzrignore index 388dcac2ca6..6e1da35a08f 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1127,3 +1127,145 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +*.bin +*.exe +*.idb +*.lib +*.map +*.obj +*.pch +*.pdb +*.res +*.sbr +./copy_mysql_files.bat +./fix-project-files +./mysql*.ds? +./mysql.ncb +./mysql.sln +./mysql.suo +./prepare +./README.build-files +bdb/*.ds? +bdb/*.vcproj +client/*.ds? +client/*.vcproj +client/completion_hash.cpp +client/mysql.cpp +client/mysqladmin.cpp +client/mysqlbinlog.cpp +client/readline.cpp +client/sql_string.cpp +client_debug/* +client_release/* +comp_err/*.ds? +comp_err/*.vcproj +contrib/*.ds? +contrib/*.vcproj +dbug/*.ds? +dbug/*.vcproj +examples/*.ds? +examples/*.vcproj +examples/udf_example/udf_example.def +heap/*.ds? +heap/*.vcproj +innobase/*.ds? +innobase/*.vcproj +isam/*.ds? +isam/*.vcproj +isamchk/*.ds? +isamchk/*.vcproj +lib_debug/* +lib_release/* +libmysql/*.ds? +libmysql/*.vcproj +libmysql/debug/libmysql.exp +libmysql/release/libmysql.exp +libmysqld/*.ds? +libmysqld/*.vcproj +libmysqld/emb_qcache.cpp +libmysqld/lib_sql.cpp +libmysqld/sql_yacc.cpp +libmysqld/sql_yacc.h +libmysqltest/*.ds? +libmysqltest/*.vcproj +libmysqltest/mytest.c +merge/*.ds? +merge/*.vcproj +my_print_defaults/*.ds? +my_print_defaults/*.vcproj +myisam/*.ds? +myisam/*.vcproj +myisam_ftdump/*.ds? +myisam_ftdump/*.vcproj +myisamchk/*.ds? +myisamchk/*.vcproj +myisamlog/*.ds? +myisamlog/*.vcproj +myisammrg/*.ds? +myisammrg/*.vcproj +myisampack/*.ds? +myisampack/*.vcproj +mysql-test/*.ds? +mysql-test/*.vcproj +mysql-test/r/*.err +mysql-test/r/*.out +mysqlbinlog/*.ds? +mysqlbinlog/*.vcproj +mysqlcheck/*.ds? +mysqlcheck/*.vcproj +mysqldemb/*.ds? +mysqldemb/*.vcproj +mysqlserver/*.ds? +mysqlserver/*.vcproj +mysys/*.ds? +mysys/*.vcproj +mysys/my_new.cpp +mysys/raid.cpp +pack_isam/*.ds? +perror/*.ds? +perror/*.vcproj +regex/*.ds? +regex/*.vcproj +replace/*.ds? +replace/*.vcproj +server-tools/instance-manager/buffer.cpp +server-tools/instance-manager/command.cpp +server-tools/instance-manager/commands.cpp +server-tools/instance-manager/guardian.cpp +server-tools/instance-manager/instance.cpp +server-tools/instance-manager/instance_map.cpp +server-tools/instance-manager/instance_options.cpp +server-tools/instance-manager/listener.cpp +server-tools/instance-manager/log.cpp +server-tools/instance-manager/manager.cpp +server-tools/instance-manager/messages.cpp +server-tools/instance-manager/mysql_connection.cpp +server-tools/instance-manager/mysqlmanager.cpp +server-tools/instance-manager/options.cpp +server-tools/instance-manager/parse.cpp +server-tools/instance-manager/parse_output.cpp +server-tools/instance-manager/priv.cpp +server-tools/instance-manager/protocol.cpp +server-tools/instance-manager/thread_registry.cpp +server-tools/instance-manager/user_map.cpp +sql/*.cpp +sql/*.ds? +sql/*.vcproj +sql/max/* +sql/message.h +sql/message.mc +sql/message.rc +strings/*.ds? +strings/*.vcproj +test1/* +tests/*.ds? +tests/*.vcproj +thr_insert_test/* +thr_test/* +vio/*.ds? +vio/*.vcproj +vio/viotest-sslconnect.cpp +vio/viotest.cpp +zlib/*.ds? +zlib/*.vcproj +libmysqld/ha_blackhole.cc diff --git a/BUILD/Makefile.am b/BUILD/Makefile.am index 45c1aaa1a76..a5f3623c25e 100644 --- a/BUILD/Makefile.am +++ b/BUILD/Makefile.am @@ -21,27 +21,46 @@ EXTRA_DIST = FINISH.sh \ SETUP.sh \ autorun.sh \ check-cpu \ + cleanup \ compile-alpha \ compile-alpha-ccc \ compile-alpha-cxx \ compile-alpha-debug \ + compile-amd64-debug-max \ + compile-amd64-max \ + compile-darwin-mwcc \ + compile-dist \ + compile-hpux11-parisc2-aCC \ compile-ia64-debug-max \ + compile-irix-mips64-mipspro \ compile-pentium \ compile-pentium-debug \ compile-pentium-debug-max \ + compile-pentium-debug-max-no-embedded \ + compile-pentium-debug-max-no-ndb \ compile-pentium-debug-no-bdb \ compile-pentium-debug-openssl \ compile-pentium-debug-yassl \ compile-pentium-gcov \ compile-pentium-gprof \ + compile-pentium-icc \ + compile-pentium-icc-valgrind-max \ + compile-pentium-icc-yassl \ compile-pentium-max \ compile-pentium-myodbc \ compile-pentium-mysqlfs-debug \ compile-pentium-pgcc \ + compile-pentium-valgrind-max \ + compile-pentium64-debug \ + compile-pentium64-debug-max \ + compile-pentium64-valgrind-max \ + compile-ppc \ + compile-ppc-debug \ + compile-ppc-debug-max \ + compile-ppc-debug-max-no-ndb \ + compile-ppc-max \ compile-solaris-sparc \ compile-solaris-sparc-debug \ - compile-irix-mips64-mipspro \ - compile-hpux11-parisc2-aCC \ compile-solaris-sparc-forte \ compile-solaris-sparc-purify diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 96ec5803b63..4f2065657d5 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -44,17 +44,21 @@ set -e export AM_MAKEFLAGS AM_MAKEFLAGS="-j 4" +# SSL library to use. Should be changed to --with-yassl +SSL_LIBRARY=--with-openssl + # If you are not using codefusion add "-Wpointer-arith" to WARNINGS # The following warning flag will give too many warnings: # -Wshadow -Wunused -Winline (The later isn't usable in C++ as # __attribute()__ doesn't work with gnu C++) + global_warnings="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings" #debug_extra_warnings="-Wuninitialized" c_warnings="$global_warnings -Wunused" cxx_warnings="$global_warnings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor" -base_max_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-openssl --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine --with-csv-storage-engine" -base_max_no_ndb_configs="--with-innodb --with-berkeley-db --without-ndbcluster --with-archive-storage-engine --with-openssl --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine --with-csv-storage-engine" -max_leave_isam_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-federated-storage-engine --with-blackhole-storage-engine --with-csv-storage-engine --with-openssl --with-embedded-server --with-big-tables" +base_max_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine --with-csv-storage-engine $SSL_LIBRARY" +base_max_no_ndb_configs="--with-innodb --with-berkeley-db --without-ndbcluster --with-archive-storage-engine --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine --with-csv-storage-engine $SSL_LIBRARY" +max_leave_isam_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-federated-storage-engine --with-blackhole-storage-engine --with-csv-storage-engine $SSL_LIBRARY --with-embedded-server --with-big-tables" max_configs="$base_max_configs --with-embedded-server" max_no_ndb_configs="$base_max_no_ndb_configs --with-embedded-server" diff --git a/BUILD/compile-pentium64-debug-max b/BUILD/compile-pentium64-debug-max new file mode 100755 index 00000000000..f0745c88c90 --- /dev/null +++ b/BUILD/compile-pentium64-debug-max @@ -0,0 +1,13 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" $@ --with-debug=full + +extra_flags="$pentium64_cflags $debug_cflags $max_cflags" +c_warnings="$c_warnings $debug_extra_warnings" +cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$pentium_configs $debug_configs $max_configs" + +extra_configs="$extra_configs " + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium64-valgrind-max b/BUILD/compile-pentium64-valgrind-max index 2e4ff8e0082..ef932920130 100755 --- a/BUILD/compile-pentium64-valgrind-max +++ b/BUILD/compile-pentium64-valgrind-max @@ -3,13 +3,13 @@ path=`dirname $0` . "$path/SETUP.sh" -extra_flags="$pentium64_cflags $debug_cflags -USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify -DMYSQL_SERVER_SUFFIX=-valgrind-max" +extra_flags="$pentium64_cflags $debug_cflags $max_cflags -USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify -DMYSQL_SERVER_SUFFIX=-valgrind-max" c_warnings="$c_warnings $debug_extra_warnings" cxx_warnings="$cxx_warnings $debug_extra_warnings" extra_configs="$pentium_configs $debug_configs" # We want to test isam when building with valgrind -extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-isam --with-embedded-server --with-openssl --with-raid --with-ndbcluster" +extra_configs="$extra_configs $max_leave_isam_configs --with-isam" . "$path/FINISH.sh" diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index fe263b79325..22d183eae3a 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -2,7 +2,7 @@ #shift FROM=$USER@mysql.com -INTERNALS=internals@lists.mysql.com +COMMITS=commits@lists.mysql.com DOCS=docs-commit@mysql.com LIMIT=10000 VERSION="5.0" @@ -61,14 +61,14 @@ EOF ) | /usr/sbin/sendmail -t #++ -# internals@ mail +# commits@ mail #-- - echo "Notifying internals list at $INTERNALS" + echo "Notifying commits list at $COMMITS" ( cat <<EOF List-ID: <bk.mysql-$VERSION> From: $FROM -To: $INTERNALS +To: $COMMITS Subject: bk commit into $VERSION tree ($CHANGESET)$BS X-CSetKey: <$CSETKEY> $BH diff --git a/Docs/Makefile.am b/Docs/Makefile.am index b1f69381774..542c82d8f58 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -18,11 +18,11 @@ noinst_SCRIPTS = Support/generate-text-files.pl EXTRA_DIST = $(noinst_SCRIPTS) mysql.info INSTALL-BINARY -all: txt_files - -txt_files: ../INSTALL-SOURCE ../INSTALL-WIN-SOURCE ../EXCEPTIONS-CLIENT \ +TXT_FILES= ../INSTALL-SOURCE ../INSTALL-WIN-SOURCE ../EXCEPTIONS-CLIENT \ INSTALL-BINARY ../support-files/MacOSX/ReadMe.txt +all-local: $(TXT_FILES) + # make sure that "make install" installs the info page, too # automake only seems to take care of this automatically, # if we're building the info page from texi directly. @@ -30,28 +30,37 @@ install-data-hook: mysql.info $(mkinstalldirs) $(DESTDIR)$(infodir) $(INSTALL_DATA) $(srcdir)/mysql.info $(DESTDIR)$(infodir) -CLEAN_FILES: $(txt_files) - touch $(txt_files) +uninstall-local: + @RM@ -f $(DESTDIR)$(infodir)/mysql.info + +# Problems with "make distclean", works differently for make files +# generated by different versions of the automake. Some require the +# generated files explicitly in DISTCLEANFILES. +DISTCLEANFILES = $(TXT_FILES) + +# This target is not used in builds, just for convinience +CLEAN_FILES: $(TXT_FILES) + touch $(TXT_FILES) GT = $(srcdir)/Support/generate-text-files.pl ../INSTALL-SOURCE: mysql.info $(GT) - perl -w $(GT) mysql.info "installing-source" "windows-source-build" > $@ + perl -w $(GT) $< "installing-source" "windows-source-build" > $@ ../INSTALL-WIN-SOURCE: mysql.info $(GT) - perl -w $(GT) mysql.info "windows-source-build" "post-installation" > $@ + perl -w $(GT) $< "windows-source-build" "post-installation" > $@ # We put the description for the binary installation here so that # people who download source wont have to see it. It is moved up to # the toplevel by the script that makes the binary tar files. INSTALL-BINARY: mysql.info $(GT) - perl -w $(GT) mysql.info "installing-binary" "installing-source" > $@ + perl -w $(GT) $< "installing-binary" "installing-source" > $@ ../EXCEPTIONS-CLIENT: mysql.info $(GT) - perl -w $(GT) mysql.info "mysql-floss-license-exception" "function-index" > $@ + perl -w $(GT) $< "mysql-floss-license-exception" "function-index" > $@ ../support-files/MacOSX/ReadMe.txt: mysql.info $(GT) - perl -w $(GT) mysql.info "mac-os-x-installation" "netware-installation" > $@ + perl -w $(GT) $< "mac-os-x-installation" "netware-installation" > $@ # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/Makefile.am b/Makefile.am index 403a4ba2137..f0784a9baed 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,8 @@ AUTOMAKE_OPTIONS = foreign # These are built from source in the Docs directory -EXTRA_DIST = INSTALL-SOURCE README COPYING EXCEPTIONS-CLIENT +EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \ + README COPYING EXCEPTIONS-CLIENT SUBDIRS = . include @docs_dirs@ @zlib_dir@ @yassl_dir@ \ @readline_topdir@ sql-common \ @thread_dirs@ pstack \ @@ -34,16 +35,19 @@ DIST_SUBDIRS = . include @docs_dirs@ zlib \ BUILD netware os2 @libmysqld_dirs@ \ @bench_dirs@ support-files @tools_dirs@ -# Relink after clean -linked_sources = linked_client_sources linked_server_sources \ - linked_libmysql_sources linked_libmysql_r_sources \ - linked_libmysqld_sources linked_libmysqldex_sources \ +# Run these targets before any others, also make part of clean target, +# to make sure we create new links after a clean. +BUILT_SOURCES = linked_client_sources linked_server_sources \ + @linked_client_targets@ \ + @linked_libmysqld_targets@ \ linked_include_sources @linked_netware_sources@ -CLEANFILES = $(linked_sources) - -# This is just so that the linking is done early. -all-local: $(linked_sources) +# The db.h file is a bit special, see note in "configure.in". +# In the case we didn't compile with bdb, a dummy file is put +# there, but will not be removed by the bdb make file becuase +# it will never be called. +CLEANFILES = $(BUILT_SOURCES) bdb/build_unix/db.h +DISTCLEANFILES = ac_available_languages_fragment linked_include_sources: cd include; $(MAKE) link_sources @@ -73,13 +77,8 @@ linked_netware_sources: cd @netware_dir@; $(MAKE) link_sources echo timestamp > linked_netware_sources -#avoid recursive make calls in sql directory linked_server_sources: - cd sql; rm -f mini_client_errors.c;\ - @LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c;\ - rm -f pack.c;@LN_CP_F@ ../sql-common/pack.c pack.c;\ - rm -f client.c;@LN_CP_F@ ../sql-common/client.c client.c;\ - rm -f my_time.c;@LN_CP_F@ ../sql-common/my_time.c my_time.c + cd sql; $(MAKE) link_sources echo timestamp > linked_server_sources # Create permission databases @@ -91,42 +90,41 @@ bin-dist: all # Remove BK's "SCCS" subdirectories from source distribution dist-hook: - rm -rf `find $(distdir) -type d -name SCCS` + rm -rf `find $(distdir) -type d -name SCCS -print` tags: support-files/build-tags .PHONY: init-db bin-dist -# Test installation. Ports are configurable from the environment. - -MYSQL_TEST_MANAGER_PORT = 9305 -MYSQL_TEST_MASTER_PORT = 9306 -MYSQL_TEST_SLAVE_PORT = 9308 -MYSQL_TEST_NDB_PORT = 9350 -MYSQL_TEST_RUN_ARGS = --manager-port=$(MYSQL_TEST_MANAGER_PORT) \ - --master_port=$(MYSQL_TEST_MASTER_PORT) \ - --slave_port=$(MYSQL_TEST_SLAVE_PORT) \ - --ndbcluster_port=$(MYSQL_TEST_NDB_PORT) +# Target 'test' will run the regression test suite using the built server. +# +# If you are running in a shared environment, users can avoid clashing +# port numbers by setting individual small numbers 1-100 to the +# environment variable MTR_BUILD_THREAD. The script "mysql-test-run" +# will then calculate the various port numbers it needs from this, +# making sure each user use different ports. test: cd mysql-test ; \ - ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) && \ - ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) --ps-protocol + ./mysql-test-run && \ + ./mysql-test-run --ps-protocol test-force: - cd mysql-test ; \ - ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) --force ; \ - ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) --ps-protocol --force + cd mysql-test; \ + ./mysql-test-run --force && \ + ./mysql-test-run --ps-protocol --force +# We are testing a new Perl version of the test script test-pl: - cd mysql-test ; \ - ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) && \ - ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) --ps-protocol + cd mysql-test; \ + ./mysql-test-run.pl && \ + ./mysql-test-run.pl --ps-protocol test-force-pl: - cd mysql-test ; \ - ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) --force ; \ - ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) --ps-protocol --force + cd mysql-test; \ + ./mysql-test-run.pl --force && \ + ./mysql-test-run.pl --ps-protocol --force # Don't update the files from bitkeeper %::SCCS/s.% + diff --git a/NEW-RPMS/.cvsignore b/NEW-RPMS/.cvsignore deleted file mode 100644 index eee690e5a6c..00000000000 --- a/NEW-RPMS/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -MySQL-*.rpm diff --git a/VC++Files/mysqlbinlog/mysqlbinlog.vcproj b/VC++Files/mysqlbinlog/mysqlbinlog.vcproj index 9d5d4db2565..bfe70d6d1af 100644 --- a/VC++Files/mysqlbinlog/mysqlbinlog.vcproj +++ b/VC++Files/mysqlbinlog/mysqlbinlog.vcproj @@ -22,7 +22,7 @@ Name="VCCLCompilerTool" Optimization="0" OptimizeForProcessor="2" - AdditionalIncludeDirectories="../include,../,../sql" + AdditionalIncludeDirectories="../include,../,../sql,../strings" PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS;MYSQL_SERVER" RuntimeLibrary="1" PrecompiledHeaderFile=".\Debug/mysqlbinlog.pch" diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index 7a9ad3e1c76..817e3224ea4 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -456,7 +456,7 @@ SOURCE=.\gstream.cpp # End Source File # Begin Source File -SOURCE=.\examples\ha_archive.cpp +SOURCE=.\ha_archive.cpp # End Source File # Begin Source File diff --git a/bdb/dist/gen_rec.awk b/bdb/dist/gen_rec.awk index 75f2e86ca9e..e1b75699027 100644 --- a/bdb/dist/gen_rec.awk +++ b/bdb/dist/gen_rec.awk @@ -180,7 +180,7 @@ BEGIN { t = types[i]; if (modes[i] == "POINTER") { ndx = index(t, "*"); - t = substr(types[i], 0, ndx - 2); + t = substr(types[i], 1, ndx - 2); } printf("\t%s\t%s;\n", t, vars[i]) >> HFILE } diff --git a/client/Makefile.am b/client/Makefile.am index d47e9f98f5e..804f194085f 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -22,8 +22,10 @@ else yassl_dummy_link_fix= endif #AUTOMAKE_OPTIONS = nostdinc -INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ - -I$(top_srcdir)/regex $(openssl_includes) +INCLUDES = -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/regex \ + $(openssl_includes) $(yassl_includes) LIBS = @CLIENT_LIBS@ LDADD= @CLIENT_EXTRA_LDFLAGS@ \ $(top_builddir)/libmysql/libmysqlclient.la @@ -54,12 +56,12 @@ DEFS = -DUNDEF_THREADS_HACK link_sources: for f in $(sql_src) ; do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(top_srcdir)/sql/$$f $(srcdir)/$$f; \ + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \ done; \ for f in $(strings_src) ; do \ rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(top_srcdir)/strings/$$f $(srcdir)/$$f; \ + @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \ done; # Don't update the files from bitkeeper diff --git a/client/mysql.cc b/client/mysql.cc index bf417e73e22..98af6561966 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -259,7 +259,7 @@ static COMMANDS commands[] = { { "quit", 'q', com_quit, 0, "Quit mysql." }, { "rehash", '#', com_rehash, 0, "Rebuild completion hash." }, { "source", '.', com_source, 1, - "Execute a SQL script file. Takes a file name as an argument."}, + "Execute an SQL script file. Takes a file name as an argument."}, { "status", 's', com_status, 0, "Get status information from the server."}, #ifdef USE_POPEN { "system", '!', com_shell, 1, "Execute a system shell command."}, @@ -527,7 +527,7 @@ static struct my_option my_long_options[] = {"help", 'I', "Synonym for -?", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __NETWARE__ - {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", + {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"auto-rehash", OPT_AUTO_REHASH, @@ -728,7 +728,7 @@ static void usage(int version) my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE, readline, rl_library_version); #else - printf("%s Ver %s Distrib %s, for %s (%s)", my_progname, VER, + printf("%s Ver %s Distrib %s, for %s (%s)\n", my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); #endif @@ -1133,10 +1133,11 @@ static COMMANDS *find_command(char *name,char cmd_char) parsing the row and calling find_command() */ if (strstr(name, "\\g") || (strstr(name, delimiter) && - strlen(name) >= 9 && - my_strnncoll(charset_info,(uchar*) name, - 9, - (const uchar*) "delimiter", 9))) + !(strlen(name) >= 9 && + !my_strnncoll(charset_info, + (uchar*) name, 9, + (const uchar*) "delimiter", + 9)))) DBUG_RETURN((COMMANDS *) 0); if ((end=strcont(name," \t"))) { @@ -1871,9 +1872,13 @@ com_help(String *buffer __attribute__((unused)), if (help_arg) return com_server_help(buffer,line,help_arg+1); - put_info("\nFor the complete MySQL Manual online, visit:\n http://www.mysql.com/documentation\n", INFO_INFO); - put_info("For info on technical support from MySQL developers, visit:\n http://www.mysql.com/support\n", INFO_INFO); - put_info("For info on MySQL books, utilities, consultants, etc., visit:\n http://www.mysql.com/portal\n", INFO_INFO); + put_info("\nFor information about MySQL products and services, visit:\n" + " http://www.mysql.com/\n" + "For developer information, including the MySQL Reference Manual, " + "visit:\n" + " http://dev.mysql.com/\n" + "To buy MySQL Network Support, training, or other products, visit:\n" + " https://shop.mysql.com/\n", INFO_INFO); put_info("List of all MySQL commands:", INFO_INFO); if (!named_cmds) put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO); diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index ec136402bd8..8d2e040b21f 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -127,7 +127,7 @@ static TYPELIB command_typelib= static struct my_option my_long_options[] = { #ifdef __NETWARE__ - {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", + {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"count", 'c', @@ -161,7 +161,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"port", 'P', "Port number to use for connection.", (gptr*) &tcp_port, - (gptr*) &tcp_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, + (gptr*) &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relative", 'r', diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 6cba3c0cb44..ae482a155d5 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -67,7 +67,7 @@ static const char* database= 0; static my_bool force_opt= 0, short_form= 0, remote_opt= 0; static ulonglong offset = 0; static const char* host = 0; -static int port = MYSQL_PORT; +static int port= 0; static const char* sock= 0; static const char* user = 0; static char* pass = 0; @@ -647,7 +647,7 @@ static struct my_option my_long_options[] = { #ifdef __NETWARE__ - {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", + {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif /* @@ -688,7 +688,7 @@ static struct my_option my_long_options[] = {"password", 'p', "Password to connect to remote server.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Use port to connect to the remote server.", - (gptr*) &port, (gptr*) &port, 0, GET_INT, REQUIRED_ARG, MYSQL_PORT, 0, 0, + (gptr*) &port, (gptr*) &port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"position", 'j', "Deprecated. Use --start-position instead.", (gptr*) &start_position, (gptr*) &start_position, 0, GET_ULL, diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 2eb3e55c2e9..2ad35098c33 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -63,7 +63,7 @@ static struct my_option my_long_options[] = (gptr*) &opt_all_in_1, (gptr*) &opt_all_in_1, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __NETWARE__ - {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", + {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"auto-repair", OPT_AUTO_REPAIR, @@ -122,7 +122,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, + (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/client/mysqldump.c b/client/mysqldump.c index eb814c267ed..454fc0df84e 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -173,7 +173,7 @@ static struct my_option my_long_options[] = "Allow creation of column names that are keywords.", (gptr*) &opt_keywords, (gptr*) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __NETWARE__ - {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", + {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"character-sets-dir", OPT_CHARSETS_DIR, @@ -330,7 +330,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, + (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -342,7 +342,7 @@ static struct my_option my_long_options[] = {"result-file", 'r', "Direct output to a given file. This option should be used in MSDOS, because it prevents new line '\\n' from being converted to '\\r\\n' (carriage return + line feed).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"routines", 'R', "Dump routines FUNCTIONS and PROCEDURES.", + {"routines", 'R', "Dump stored routines (functions and procedures).", (gptr*) &opt_routines, (gptr*) &opt_routines, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"set-charset", OPT_SET_CHARSET, @@ -1460,6 +1460,8 @@ static uint get_table_structure(char *table, char *db, char *table_type, { fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n", opt_quoted_table); + fprintf(sql_file, "/*!50001 DROP TABLE IF EXISTS %s*/;\n", + opt_quoted_table); check_io(sql_file); } @@ -1471,7 +1473,8 @@ static uint get_table_structure(char *table, char *db, char *table_type, */ row= mysql_fetch_row(result); - fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0), row[1]); + fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0), + row[1]); while((row= mysql_fetch_row(result))) { @@ -1838,12 +1841,13 @@ DELIMITER ;;\n"); while ((row= mysql_fetch_row(result))) { fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n\ -/*!50003 CREATE TRIGGER %s %s %s ON %s FOR EACH ROW%s */;;\n\n", +/*!50003 CREATE TRIGGER %s %s %s ON %s FOR EACH ROW%s%s */;;\n\n", row[6], /* sql_mode */ quote_name(row[0], name_buff, 0), /* Trigger */ row[4], /* Timing */ row[1], /* Event */ result_table, + (strchr(" \t\n\r", *(row[3]))) ? "" : " ", row[3] /* Statement */); } if (mysql_num_rows(result)) @@ -2148,6 +2152,8 @@ static void dump_table(char *table, char *db) for (i = 0; i < mysql_num_fields(res); i++) { int is_blob; + ulong length= lengths[i]; + if (!(field = mysql_fetch_field(res))) { my_snprintf(query, QUERY_LENGTH, @@ -2174,7 +2180,6 @@ static void dump_table(char *table, char *db) field->type == MYSQL_TYPE_TINY_BLOB)) ? 1 : 0; if (extended_insert) { - ulong length = lengths[i]; if (i == 0) dynstr_set(&extended_row,"("); else @@ -2264,19 +2269,19 @@ static void dump_table(char *table, char *db) { print_xml_tag1(md_result_file, "\t\t", "field name=", field->name, ""); - print_quoted_xml(md_result_file, row[i], lengths[i]); + print_quoted_xml(md_result_file, row[i], length); fputs("</field>\n", md_result_file); } - else if (opt_hex_blob && is_blob) + else if (opt_hex_blob && is_blob && length) { /* sakaik got the idea to to provide blob's in hex notation. */ - char *ptr= row[i], *end= ptr+ lengths[i]; + char *ptr= row[i], *end= ptr + length; fputs("0x", md_result_file); for (; ptr < end ; ptr++) fprintf(md_result_file, "%02X", *((uchar *)ptr)); } else - unescape(md_result_file, row[i], lengths[i]); + unescape(md_result_file, row[i], length); } else { diff --git a/client/mysqlimport.c b/client/mysqlimport.c index ca0a751e963..8694093f06b 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -59,7 +59,7 @@ static char *shared_memory_base_name=0; static struct my_option my_long_options[] = { #ifdef __NETWARE__ - {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", + {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"character-sets-dir", OPT_CHARSETS_DIR, @@ -121,7 +121,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, + (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -518,6 +518,13 @@ int main(int argc, char **argv) free_defaults(argv_to_free); return(1); /* purecov: deadcode */ } + + if (mysql_query(sock, "set @@character_set_database=binary;")) + { + db_error(sock); /* We shall countinue here, if --force was given */ + return(1); + } + if (lock_tables) lock_table(sock, argc, argv); for (; *argv != NULL; argv++) diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 8f6be6cf70b..504f0d9844b 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -157,7 +157,7 @@ int main(int argc, char **argv) static struct my_option my_long_options[] = { #ifdef __NETWARE__ - {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", + {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"character-sets-dir", 'c', "Directory where character sets are.", @@ -188,7 +188,7 @@ static struct my_option my_long_options[] = "Password to use when connecting to server. If password is not given it's asked from the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, + (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __WIN__ {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, diff --git a/client/mysqltest.c b/client/mysqltest.c index 6653d24e575..3a4ce5ce7cf 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -77,7 +77,6 @@ #define PAD_SIZE 128 #define MAX_CONS 128 #define MAX_INCLUDE_DEPTH 16 -#define LAZY_GUESS_BUF_SIZE 8192 #define INIT_Q_LINES 1024 #define MIN_VAR_ALLOC 32 #define BLOCK_STACK_DEPTH 32 @@ -1837,23 +1836,28 @@ void free_replace() DBUG_VOID_RETURN; } - -int select_connection_name(const char *name) +struct connection * find_connection_by_name(const char *name) { struct connection *con; - DBUG_ENTER("select_connection2"); - DBUG_PRINT("enter",("name: '%s'", name)); - for (con= cons; con < next_con; con++) { if (!strcmp(con->name, name)) { - cur_con= con; - DBUG_RETURN(0); + return con; } } - die("connection '%s' not found in connection pool", name); - DBUG_RETURN(1); /* Never reached */ + return 0; /* Connection not found */ +} + + +int select_connection_name(const char *name) +{ + DBUG_ENTER("select_connection2"); + DBUG_PRINT("enter",("name: '%s'", name)); + + if (!(cur_con= find_connection_by_name(name))) + die("connection '%s' not found in connection pool", name); + DBUG_RETURN(0); } @@ -1883,7 +1887,7 @@ int close_connection(struct st_query *q) DBUG_PRINT("enter",("name: '%s'",p)); if (!*p) - die("Missing connection name in connect"); + die("Missing connection name in disconnect"); name= p; while (*p && !my_isspace(charset_info,*p)) p++; @@ -1906,6 +1910,14 @@ int close_connection(struct st_query *q) } #endif mysql_close(&con->mysql); + my_free(con->name, MYF(0)); + /* + When the connection is closed set name to "closed_connection" + to make it possible to reuse the connection name. + The connection slot will not be reused + */ + if (!(con->name = my_strdup("closed_connection", MYF(MY_WME)))) + die("Out of memory"); DBUG_RETURN(0); } } @@ -1919,20 +1931,35 @@ int close_connection(struct st_query *q) future to handle quotes. For now we assume that anything that is not a comma, a space or ) belongs to the argument. space is a chopper, comma or ) are delimiters/terminators + + SYNOPSIS + safe_get_param + str - string to get param from + arg - pointer to string where result will be stored + msg - Message to display if param is not found + if msg is 0 this param is not required and param may be empty + + RETURNS + pointer to str after param + */ char* safe_get_param(char *str, char** arg, const char *msg) { DBUG_ENTER("safe_get_param"); + if(!*str) + { + if (msg) + die(msg); + *arg= str; + DBUG_RETURN(str); + } while (*str && my_isspace(charset_info,*str)) str++; *arg= str; - for (; *str && *str != ',' && *str != ')' ; str++) - { - if (my_isspace(charset_info,*str)) - *str= 0; - } - if (!*str) + while (*str && *str != ',' && *str != ')') + str++; + if (msg && !*arg) die(msg); *str++= 0; @@ -2117,71 +2144,137 @@ err: } +/* + Open a new connection to MySQL Server with the parameters + specified + + SYNOPSIS + do_connect() + q called command + + DESCRIPTION + connect(<name>,<host>,<user>,<pass>,<db>,[<port>,<sock>[<opts>]]); + + <name> - name of the new connection + <host> - hostname of server + <user> - user to connect as + <pass> - password used when connecting + <db> - initial db when connected + <port> - server port + <sock> - server socket + <opts> - options to use for the connection + SSL - use SSL if available + COMPRESS - use compression if available + + */ + int do_connect(struct st_query *q) { char *con_name, *con_user,*con_pass, *con_host, *con_port_str, - *con_db, *con_sock; - char *p= q->first_argument; + *con_db, *con_sock, *con_options; + char *con_buf, *p; char buff[FN_REFLEN]; int con_port; + bool con_ssl= 0; + bool con_compress= 0; int free_con_sock= 0; int error= 0; int create_conn= 1; + VAR *var_port, *var_sock; DBUG_ENTER("do_connect"); - DBUG_PRINT("enter",("connect: %s",p)); + DBUG_PRINT("enter",("connect: %s", q->first_argument)); + + /* Make a copy of query before parsing, safe_get_param will modify */ + if (!(con_buf= my_strdup(q->first_argument, MYF(MY_WME)))) + die("Could not allocate con_buf"); + p= con_buf; if (*p != '(') die("Syntax error in connect - expected '(' found '%c'", *p); p++; - p= safe_get_param(p, &con_name, "missing connection name"); - p= safe_get_param(p, &con_host, "missing connection host"); - p= safe_get_param(p, &con_user, "missing connection user"); - p= safe_get_param(p, &con_pass, "missing connection password"); - p= safe_get_param(p, &con_db, "missing connection db"); - if (!*p || *p == ';') /* Default port and sock */ - { - con_port= port; - con_sock= (char*) unix_sock; - } - else + p= safe_get_param(p, &con_name, "Missing connection name"); + p= safe_get_param(p, &con_host, "Missing connection host"); + p= safe_get_param(p, &con_user, "Missing connection user"); + p= safe_get_param(p, &con_pass, "Missing connection password"); + p= safe_get_param(p, &con_db, "Missing connection db"); + + /* Port */ + p= safe_get_param(p, &con_port_str, 0); + if (*con_port_str) { - VAR* var_port, *var_sock; - p= safe_get_param(p, &con_port_str, "missing connection port"); if (*con_port_str == '$') { if (!(var_port= var_get(con_port_str, 0, 0, 0))) - die("Unknown variable '%s'", con_port_str+1); + die("Unknown variable '%s'", con_port_str+1); con_port= var_port->int_val; } else + { con_port= atoi(con_port_str); - p= safe_get_param(p, &con_sock, "missing connection socket"); + if (con_port == 0) + die("Illegal argument for port: '%s'", con_port_str); + } + } + else + { + con_port= port; + } + + /* Sock */ + p= safe_get_param(p, &con_sock, 0); + if (*con_sock) + { if (*con_sock == '$') { if (!(var_sock= var_get(con_sock, 0, 0, 0))) - die("Unknown variable '%s'", con_sock+1); + die("Unknown variable '%s'", con_sock+1); if (!(con_sock= (char*)my_malloc(var_sock->str_val_len+1, MYF(0)))) - die("Out of memory"); + die("Out of memory"); free_con_sock= 1; memcpy(con_sock, var_sock->str_val, var_sock->str_val_len); con_sock[var_sock->str_val_len]= 0; } } - q->last_argument= p; + else + { + con_sock= (char*) unix_sock; + } + + /* Options */ + p= safe_get_param(p, &con_options, 0); + while (*con_options) + { + char* str= con_options; + while (*str && !my_isspace(charset_info, *str)) + str++; + *str++= 0; + if (!strcmp(con_options, "SSL")) + con_ssl= 1; + else if (!strcmp(con_options, "COMPRESS")) + con_compress= 1; + else + die("Illegal option to connect: %s", con_options); + con_options= str; + } + /* Note: 'p' is pointing into the copy 'con_buf' */ + q->last_argument= q->first_argument + (p - con_buf); if (next_con == cons_end) die("Connection limit exhausted - increase MAX_CONS in mysqltest.c"); + if (find_connection_by_name(con_name)) + die("Connection %s already exists", con_name); + if (!mysql_init(&next_con->mysql)) die("Failed on mysql_init()"); - if (opt_compress) + if (opt_compress || con_compress) mysql_options(&next_con->mysql,MYSQL_OPT_COMPRESS,NullS); mysql_options(&next_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0); mysql_options(&next_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name); #ifdef HAVE_OPENSSL - if (opt_use_ssl) + if (opt_use_ssl || con_ssl) mysql_ssl_set(&next_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); #endif @@ -2212,6 +2305,7 @@ int do_connect(struct st_query *q) } if (free_con_sock) my_free(con_sock, MYF(MY_WME)); + my_free(con_buf, MYF(MY_WME)); DBUG_RETURN(error); } @@ -2637,10 +2731,8 @@ end: static struct my_option my_long_options[] = { - {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", - 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"database", 'D', "Database to use.", (gptr*) &db, (gptr*) &db, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, + 0, 0, 0, 0, 0, 0}, {"basedir", 'b', "Basedir for tests.", (gptr*) &opt_basedir, (gptr*) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"big-test", 'B', "Define BIG_TEST to 1.", (gptr*) &opt_big_test, @@ -2648,13 +2740,17 @@ static struct my_option my_long_options[] = {"compress", 'C', "Use the compressed server/client protocol.", (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, - 0, 0, 0, 0, 0, 0}, + {"database", 'D', "Database to use.", (gptr*) &db, (gptr*) &db, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef DBUG_OFF + {"debug", '#', "This is a non-debug version. Catch this and exit", + 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, +#else + {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", + 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"host", 'h', "Connect to host.", (gptr*) &host, (gptr*) &host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"manager-user", OPT_MANAGER_USER, "Undocumented: Used for debugging.", - (gptr*) &manager_user, (gptr*) &manager_user, 0, GET_STR, REQUIRED_ARG, 0, - 0, 0, 0, 0, 0}, {"manager-host", OPT_MANAGER_HOST, "Undocumented: Used for debugging.", (gptr*) &manager_host, (gptr*) &manager_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -2663,13 +2759,16 @@ static struct my_option my_long_options[] = {"manager-port", OPT_MANAGER_PORT, "Undocumented: Used for debugging.", (gptr*) &manager_port, (gptr*) &manager_port, 0, GET_INT, REQUIRED_ARG, MYSQL_MANAGER_PORT, 0, 0, 0, 0, 0}, + {"manager-user", OPT_MANAGER_USER, "Undocumented: Used for debugging.", + (gptr*) &manager_user, (gptr*) &manager_user, 0, GET_STR, REQUIRED_ARG, 0, + 0, 0, 0, 0, 0}, {"manager-wait-timeout", OPT_MANAGER_WAIT_TIMEOUT, "Undocumented: Used for debugging.", (gptr*) &manager_wait_timeout, (gptr*) &manager_wait_timeout, 0, GET_INT, REQUIRED_ARG, 3, 0, 0, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Port number to use for connection.", (gptr*) &port, - (gptr*) &port, 0, GET_INT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, + (gptr*) &port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ps-protocol", OPT_PS_PROTOCOL, "Use prepared statements protocol for communication", (gptr*) &ps_protocol, (gptr*) &ps_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -3220,20 +3319,23 @@ static int handle_error(const char *query, struct st_query *q, ((q->expected_errno[i].type == ERR_SQLSTATE) && (strcmp(q->expected_errno[i].code.sqlstate, err_sqlstate) == 0))) { - if (q->expected_errors == 1) + if (!disable_result_log) { - /* Only log error if there is one possible error */ - dynstr_append_mem(ds, "ERROR ", 6); - replace_dynstr_append(ds, err_sqlstate); - dynstr_append_mem(ds, ": ", 2); - replace_dynstr_append(ds, err_error); - dynstr_append_mem(ds,"\n",1); + if (q->expected_errors == 1) + { + /* Only log error if there is one possible error */ + dynstr_append_mem(ds, "ERROR ", 6); + replace_dynstr_append(ds, err_sqlstate); + dynstr_append_mem(ds, ": ", 2); + replace_dynstr_append(ds, err_error); + dynstr_append_mem(ds,"\n",1); + } + /* Don't log error if we may not get an error */ + else if (q->expected_errno[0].type == ERR_SQLSTATE || + (q->expected_errno[0].type == ERR_ERRNO && + q->expected_errno[0].code.errnum != 0)) + dynstr_append(ds,"Got one of the listed errors\n"); } - /* Don't log error if we may not get an error */ - else if (q->expected_errno[0].type == ERR_SQLSTATE || - (q->expected_errno[0].type == ERR_ERRNO && - q->expected_errno[0].code.errnum != 0)) - dynstr_append(ds,"Got one of the listed errors\n"); /* OK */ DBUG_RETURN(0); } @@ -3241,11 +3343,14 @@ static int handle_error(const char *query, struct st_query *q, DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors)); - dynstr_append_mem(ds, "ERROR ",6); - replace_dynstr_append(ds, err_sqlstate); - dynstr_append_mem(ds, ": ", 2); - replace_dynstr_append(ds, err_error); - dynstr_append_mem(ds, "\n", 1); + if (!disable_result_log) + { + dynstr_append_mem(ds, "ERROR ",6); + replace_dynstr_append(ds, err_sqlstate); + dynstr_append_mem(ds, ": ", 2); + replace_dynstr_append(ds, err_error); + dynstr_append_mem(ds, "\n", 1); + } if (i) { @@ -3522,19 +3627,24 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) /* Read result from each column */ for (col_idx= 0; col_idx < num_fields; col_idx++) { - /* FIXME is string terminated? */ - const char *val= (const char *)bind[col_idx].buffer; - ulonglong len= *bind[col_idx].length; + const char *val; + ulonglong len; if (col_idx < max_replace_column && replace_column[col_idx]) { val= replace_column[col_idx]; len= strlen(val); } - if (*bind[col_idx].is_null) + else if (*bind[col_idx].is_null) { val= "NULL"; len= 4; } + else + { + /* FIXME is string terminated? */ + val= (const char *) bind[col_idx].buffer; + len= *bind[col_idx].length; + } if (!display_result_vertically) { if (col_idx) /* No tab before first col */ diff --git a/cmd-line-utils/libedit/Makefile.am b/cmd-line-utils/libedit/Makefile.am index af1bf8b2c97..ae6755f1c5c 100644 --- a/cmd-line-utils/libedit/Makefile.am +++ b/cmd-line-utils/libedit/Makefile.am @@ -2,8 +2,8 @@ # Makefile for the GNU readline library. # Copyright (C) 1994,1996,1997 Free Software Foundation, Inc. -ASRC=vi.c emacs.c common.c -AHDR=vi.h emacs.h common.h +ASRC = $(srcdir)/vi.c $(srcdir)/emacs.c $(srcdir)/common.c +AHDR = vi.h emacs.h common.h INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ -I$(srcdir)/../.. -I.. @@ -42,16 +42,16 @@ SUFFIXES = .sh $< > $@-t @MV@ $@-t $@ -vi.h: vi.c makelist - sh ./makelist -h ./vi.c > $@.tmp && \ +vi.h: $(srcdir)/vi.c makelist + sh ./makelist -h $(srcdir)/vi.c > $@.tmp && \ mv $@.tmp $@ -emacs.h: emacs.c makelist - sh ./makelist -h ./emacs.c > $@.tmp && \ +emacs.h: $(srcdir)/emacs.c makelist + sh ./makelist -h $(srcdir)/emacs.c > $@.tmp && \ mv $@.tmp $@ -common.h: common.c makelist - sh ./makelist -h ./common.c > $@.tmp && \ +common.h: $(srcdir)/common.c makelist + sh ./makelist -h $(srcdir)/common.c > $@.tmp && \ mv $@.tmp $@ help.c: ${ASRC} makelist diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4 index 6f93f38f119..5346b81fb03 100644 --- a/config/ac-macros/misc.m4 +++ b/config/ac-macros/misc.m4 @@ -693,6 +693,27 @@ dnl --------------------------------------------------------------------------- dnl END OF MYSQL_CHECK_BIG_TABLES SECTION dnl --------------------------------------------------------------------------- + +dnl --------------------------------------------------------------------------- +dnl Macro: MYSQL_CHECK_MAX_INDEXES +dnl Sets MAX_INDEXES +dnl --------------------------------------------------------------------------- +AC_DEFUN([MYSQL_CHECK_MAX_INDEXES], [ + AC_ARG_WITH([max-indexes], + [ + --with-max-indexes=\# Sets the maximum number of indexes per table, default 64], + [max_indexes="$withval"], + [max_indexes=64]) + AC_MSG_CHECKING([max indexes per table]) + AC_DEFINE_UNQUOTED([MAX_INDEXES], [$max_indexes], + [Maximum number of indexes per table]) + AC_MSG_RESULT([$max_indexes]) +]) +dnl --------------------------------------------------------------------------- +dnl END OF MYSQL_CHECK_MAX_INDEXES SECTION +dnl --------------------------------------------------------------------------- + + dnl MYSQL_NEEDS_MYSYS_NEW AC_DEFUN([MYSQL_NEEDS_MYSYS_NEW], [AC_CACHE_CHECK([needs mysys_new helpers], mysql_use_mysys_new, diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4 index dcd72cb14f1..77208faee0c 100644 --- a/config/ac-macros/yassl.m4 +++ b/config/ac-macros/yassl.m4 @@ -15,29 +15,29 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ fi AC_MSG_RESULT([using bundled yaSSL]) yassl_dir="extra/yassl" - openssl_libs="\ - -L\$(top_builddir)/extra/yassl/src -lyassl\ - -L\$(top_builddir)/extra/yassl/taocrypt/src -ltaocrypt" - openssl_includes="-I\$(top_srcdir)/extra/yassl/include" + yassl_libs="-L\$(top_srcdir)/extra/yassl/src -lyassl -L\$(top_srcdir)/extra/yassl/taocrypt/src -ltaocrypt" + yassl_includes="-I\$(top_srcdir)/extra/yassl/include" + yassl_libs_with_path="\$(top_srcdir)/extra/yassl/src/libyassl.la \$(top_srcdir)/extra/yassl/taocrypt/src/libtaocrypt.la" AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) AC_DEFINE([HAVE_YASSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) # System specific checks yassl_integer_extra_cxxflags="" case $host_cpu--$CXX_VERSION in sparc*--*Sun*C++*5.6*) - # Disable inlining when compiling taocrypt/src/integer.cpp - yassl_integer_extra_cxxflags="+d" - AC_MSG_NOTICE([disabling inlining for yassl/taocrypt/src/integer.cpp]) + # Disable inlining when compiling taocrypt/src/ + yassl_taocrypt_extra_cxxflags="+d" + AC_MSG_NOTICE([disabling inlining for yassl/taocrypt/src/]) ;; esac - AC_SUBST([yassl_integer_extra_cxxflags]) + AC_SUBST([yassl_taocrypt_extra_cxxflags]) else yassl_dir="" AC_MSG_RESULT(no) fi - AC_SUBST(openssl_libs) - AC_SUBST(openssl_includes) + AC_SUBST(yassl_libs) + AC_SUBST(yassl_libs_with_path) + AC_SUBST(yassl_includes) AC_SUBST(yassl_dir) AM_CONDITIONAL([HAVE_YASSL], [ test "with_yassl" = "yes" ]) ]) diff --git a/config/ac-macros/zlib.m4 b/config/ac-macros/zlib.m4 index 94a26f33dd3..ec55f19b98f 100644 --- a/config/ac-macros/zlib.m4 +++ b/config/ac-macros/zlib.m4 @@ -19,7 +19,7 @@ INCLUDES="$INCLUDES $ZLIB_INCLUDES" LIBS="$LIBS $ZLIB_LIBS" AC_CACHE_VAL([mysql_cv_compress], [AC_TRY_LINK([#include <zlib.h>], - [return compress(0, (unsigned long*) 0, "", 0);], + [return zlibCompileFlags();], [mysql_cv_compress="yes" AC_MSG_RESULT([ok])], [mysql_cv_compress="no"]) @@ -89,8 +89,9 @@ case $SYSTEM_TYPE in fi ;; *) - if test -f "$mysql_zlib_dir/lib/libz.a" -a \ - -f "$mysql_zlib_dir/include/zlib.h"; then + if test \( -f "$mysql_zlib_dir/lib/libz.a" -o -f "$mysql_zlib_dir/lib/libz.so" -o \ + -f "$mysql_zlib_dir/lib/libz.sl" -o -f "$mysql_zlib_dir/lib/libz.dylib" \) \ + -a -f "$mysql_zlib_dir/include/zlib.h"; then ZLIB_INCLUDES="-I$mysql_zlib_dir/include" ZLIB_LIBS="-L$mysql_zlib_dir/lib -lz" MYSQL_CHECK_ZLIB_DIR diff --git a/configure.in b/configure.in index 40ff480bb94..b5c31361b26 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.16) +AM_INIT_AUTOMAKE(mysql, 5.0.19) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -18,7 +18,7 @@ SHARED_LIB_VERSION=15:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=16 +NDB_VERSION_BUILD=19 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? @@ -71,7 +71,6 @@ AC_DEFINE_UNQUOTED([DOT_FRM_VERSION], [$DOT_FRM_VERSION], [Version of .frm files]) AC_SUBST(SHARED_LIB_VERSION) AC_SUBST(AVAILABLE_LANGUAGES) -AC_SUBST(AVAILABLE_LANGUAGES_ERRORS) AC_SUBST([NDB_VERSION_MAJOR]) AC_SUBST([NDB_VERSION_MINOR]) @@ -334,6 +333,10 @@ case "$target_os" in # Use the built-in alloca() CFLAGS="$CFLAGS -Kalloca" CXXFLAGS="$CFLAGS -Kalloca" + # Use no_implicit for templates + CXXFLAGS="$CXXFLAGS -Tno_implicit" + AC_DEFINE([HAVE_EXPLICIT_TEMPLATE_INSTANTIATION], + [1], [Defined by configure. Use explicit template instantiation.]) fi ;; esac @@ -1129,7 +1132,7 @@ dnl Is this the right match for DEC OSF on alpha? sql/Makefile.in) # Use gen_lex_hash.linux instead of gen_lex_hash # Add library dependencies to mysqld_DEPENDENCIES - lib_DEPENDENCIES="\$(bdb_libs_with_path) \$(innodb_libs) \$(ndbcluster_libs) \$(pstack_libs) \$(innodb_system_libs) \$(openssl_libs)" + lib_DEPENDENCIES="\$(bdb_libs_with_path) \$(innodb_libs) \$(ndbcluster_libs) \$(pstack_libs) \$(innodb_system_libs) \$(openssl_libs) \$(yassl_libs)" cat > $filesed << EOF s,\(^.*\$(MAKE) gen_lex_hash\)\$(EXEEXT),#\1, s,\(\./gen_lex_hash\)\$(EXEEXT),\1.linux, @@ -1583,6 +1586,19 @@ if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null; then OPTIMIZE_CXXFLAGS="-O3 -DNDEBUG" fi +# If the user specified CFLAGS, we won't add any optimizations +if test -n "$SAVE_CFLAGS" +then + OPTIMIZE_CFLAGS="" + DEBUG_OPTIMIZE_CC="" +fi +# Ditto for CXXFLAGS +if test -n "$SAVE_CXXFLAGS" +then + OPTIMIZE_CXXFLAGS="" + DEBUG_OPTIMIZE_CXX="" +fi + AC_ARG_WITH(debug, [ --without-debug Build a production version without debugging code], [with_debug=$withval], @@ -2214,6 +2230,7 @@ then AC_MSG_WARN([extra-tools disabled because --enable-thread-safe-client wasn't used]) else tools_dirs="tools" + AC_CONFIG_FILES(tools/Makefile) fi fi @@ -2235,9 +2252,12 @@ MYSQL_CHECK_OPENSSL MYSQL_CHECK_YASSL libmysqld_dirs= +linked_libmysqld_targets= if test "$with_embedded_server" = "yes" then libmysqld_dirs=libmysqld + linked_libmysqld_targets="linked_libmysqld_sources linked_libmysqldex_sources" + AC_CONFIG_FILES(libmysqld/Makefile libmysqld/examples/Makefile) # We can't build embedded library without building the server, because # we depend on libmysys, libmystrings, libmyisam, etc. with_server=yes @@ -2246,6 +2266,7 @@ fi # mysql_config --libmysqld-libs will print out something like # -L/path/to/lib/mysql -lmysqld -lmyisam -lmysys -lmystrings -ldbug ... AC_SUBST([libmysqld_dirs]) +AC_SUBST([linked_libmysqld_targets]) # Shall we build the docs? AC_ARG_WITH(docs, @@ -2272,10 +2293,14 @@ AC_ARG_WITH(man, if test "$with_man" = "yes" then man_dirs="man" + man1_files=`ls -1 $srcdir/man/*.1 | sed -e 's;^.*man/;;'` + man1_files=`echo $man1_files` else man_dirs="" + man1_files="" fi AC_SUBST(man_dirs) +AC_SUBST(man1_files) # Shall we build the bench code? AC_ARG_WITH(bench, @@ -2345,7 +2370,7 @@ then readline_basedir="libedit" readline_dir="$readline_topdir/$readline_basedir" readline_link="\$(top_builddir)/cmd-line-utils/libedit/libedit.a" - readline_h_ln_cmd="\$(LN) -s \$(top_builddir)/cmd-line-utils/libedit/readline readline" + readline_h_ln_cmd="\$(LN) -s \$(top_srcdir)/cmd-line-utils/libedit/readline readline" compile_libedit=yes AC_DEFINE_UNQUOTED(HAVE_HIST_ENTRY, 1) AC_DEFINE_UNQUOTED(USE_LIBEDIT_INTERFACE, 1) @@ -2355,7 +2380,7 @@ then readline_basedir="readline" readline_dir="$readline_topdir/$readline_basedir" readline_link="\$(top_builddir)/cmd-line-utils/readline/libreadline.a" - readline_h_ln_cmd="\$(LN) -s \$(top_builddir)/cmd-line-utils/readline readline" + readline_h_ln_cmd="\$(LN) -s \$(top_srcdir)/cmd-line-utils/readline readline" compile_readline=yes AC_DEFINE_UNQUOTED(USE_NEW_READLINE_INTERFACE, 1) else @@ -2388,6 +2413,7 @@ AC_SUBST(readline_link) AC_SUBST(readline_h_ln_cmd) MYSQL_CHECK_BIG_TABLES +MYSQL_CHECK_MAX_INDEXES MYSQL_CHECK_BDB MYSQL_CHECK_INNODB MYSQL_CHECK_EXAMPLEDB @@ -2411,6 +2437,7 @@ if test "$THREAD_SAFE_CLIENT" != "no" then sql_client_dirs="libmysql_r $sql_client_dirs" linked_client_targets="$linked_client_targets linked_libmysql_r_sources" + AC_CONFIG_FILES(libmysql_r/Makefile) AC_DEFINE([THREAD_SAFE_CLIENT], [1], [Should be client be thread safe]) fi @@ -2739,12 +2766,11 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl myisam/Makefile myisammrg/Makefile dnl os2/Makefile os2/include/Makefile os2/include/sys/Makefile dnl man/Makefile BUILD/Makefile vio/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 SSL/Makefile dnl dbug/Makefile scripts/Makefile dnl - include/Makefile sql-bench/Makefile tools/Makefile dnl + include/Makefile sql-bench/Makefile dnl server-tools/Makefile server-tools/instance-manager/Makefile dnl tests/Makefile Docs/Makefile support-files/Makefile dnl support-files/MacOSX/Makefile mysql-test/Makefile dnl diff --git a/extra/Makefile.am b/extra/Makefile.am index 457fddce673..c0ad75059df 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -23,11 +23,14 @@ BUILT_SOURCES= $(top_builddir)/include/mysqld_error.h \ $(top_builddir)/include/mysqld_ername.h pkginclude_HEADERS= $(BUILT_SOURCES) CLEANFILES = $(BUILT_SOURCES) +# We never use SUBDIRS here, but needed for automake 1.6.3 +# to generate code to handle DIST_SUBDIRS +SUBDIRS= DIST_SUBDIRS= yassl # This will build mysqld_error.h and sql_state.h -$(top_builddir)/include/mysqld_error.h: comp_err - $(top_builddir)/extra/comp_err \ +$(top_builddir)/include/mysqld_error.h: comp_err$(EXEEXT) + $(top_builddir)/extra/comp_err$(EXEEXT) \ --charset=$(top_srcdir)/sql/share/charsets \ --out-dir=$(top_builddir)/sql/share/ \ --header_file=$(top_builddir)/include/mysqld_error.h \ diff --git a/extra/innochecksum.c b/extra/innochecksum.c index 739953298af..eda5cef4647 100644 --- a/extra/innochecksum.c +++ b/extra/innochecksum.c @@ -28,6 +28,8 @@ #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE +#define _XOPEN_SOURCE 500 /* needed to include getopt.h on some platforms. */ + #include <stdio.h> #include <stdlib.h> #include <time.h> diff --git a/extra/yassl/Makefile.am b/extra/yassl/Makefile.am index 7c1f2ea5acb..41c4d84f24f 100644 --- a/extra/yassl/Makefile.am +++ b/extra/yassl/Makefile.am @@ -1,2 +1,2 @@ SUBDIRS = taocrypt src -EXTRA_DIST = yassl.dsp yassl.dsw mySTL/*.hpp +EXTRA_DIST = yassl.dsp yassl.dsw $(wildcard mySTL/*.hpp) diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 45e26fb56ee..1c8291c2f13 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -341,6 +341,7 @@ long SSL_CTX_sess_set_cache_size(SSL_CTX*, long); long SSL_CTX_set_tmp_dh(SSL_CTX*, DH*); void OpenSSL_add_all_algorithms(void); +void SSL_library_init(); void SSLeay_add_ssl_algorithms(void); diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am index 83397e24168..a852ca4019b 100644 --- a/extra/yassl/src/Makefile.am +++ b/extra/yassl/src/Makefile.am @@ -4,5 +4,5 @@ noinst_LTLIBRARIES = libyassl.la libyassl_la_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ handshake.cpp lock.cpp log.cpp socket_wrapper.cpp ssl.cpp \ template_instnt.cpp timer.cpp yassl_imp.cpp yassl_error.cpp yassl_int.cpp -EXTRA_DIST = ../include/*.hpp ../include/openssl/*.h +EXTRA_DIST = $(wildcard ../include/*.hpp) $(wildcard ../include/openssl/*.h) AM_CXXFLAGS = -DYASSL_PURE_C diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index 45dfb6fa032..d7df438b8df 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -656,7 +656,11 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered) { ssl.getSocket().wait(); // wait for input if blocking uint ready = ssl.getSocket().get_ready(); - if (!ready) return buffered; + if (!ready) { + // Nothing to receive after blocking wait => error + ssl.SetError(receive_error); + return buffered= null_buffer; + } // add buffered data if its there uint buffSz = buffered.get() ? buffered.get()->get_size() : 0; diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp index 91cea1f9753..285e0dee2e5 100644 --- a/extra/yassl/src/socket_wrapper.cpp +++ b/extra/yassl/src/socket_wrapper.cpp @@ -39,7 +39,7 @@ #include <string.h> #endif // _WIN32 -#ifdef __sun +#if defined(__sun) || defined(__SCO_VERSION__) #include <sys/filio.h> #endif diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 8cea205377e..94e783167b3 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -648,6 +648,10 @@ void OpenSSL_add_all_algorithms() // compatibility only {} +void SSL_library_init() // compatibility only +{} + + DH* DH_new(void) { DH* dh = new (ys) DH; diff --git a/extra/yassl/src/timer.cpp b/extra/yassl/src/timer.cpp index 4fe0d3aa4f9..8b7d2d17a84 100644 --- a/extra/yassl/src/timer.cpp +++ b/extra/yassl/src/timer.cpp @@ -26,13 +26,17 @@ #include "runtime.hpp" #include "timer.hpp" +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#else +#include <sys/time.h> +#endif + namespace yaSSL { #ifdef _WIN32 - #define WIN32_LEAN_AND_MEAN - #include <windows.h> - timer_d timer() { static bool init(false); @@ -57,8 +61,6 @@ namespace yaSSL { #else // _WIN32 - #include <sys/time.h> - timer_d timer() { struct timeval tv; diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am index c4fc4607622..d89fa95a940 100644 --- a/extra/yassl/taocrypt/src/Makefile.am +++ b/extra/yassl/taocrypt/src/Makefile.am @@ -1,12 +1,11 @@ INCLUDES = -I../include -I../../mySTL -noinst_LTLIBRARIES = libtaocrypt.la libtaoint.la +noinst_LTLIBRARIES = libtaocrypt.la + libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \ coding.cpp dh.cpp des.cpp dsa.cpp file.cpp hash.cpp \ md2.cpp md5.cpp misc.cpp random.cpp ripemd.cpp rsa.cpp sha.cpp \ - template_instnt.cpp -libtaocrypt_la_LIBADD = libtaoint.la -libtaoint_la_SOURCES = integer.cpp -libtaoint_la_CXXFLAGS = @yassl_integer_extra_cxxflags@ -EXTRA_DIST = ../include/*.hpp -AM_CXXFLAGS = -DYASSL_PURE_C + template_instnt.cpp integer.cpp +libtaocrypt_la_CXXFLAGS = @yassl_taocrypt_extra_cxxflags@ -DYASSL_PURE_C + +EXTRA_DIST = $(wildcard ../include/*.hpp) diff --git a/heap/_check.c b/heap/_check.c index 4316a9926f7..cc832f8ed5b 100644 --- a/heap/_check.c +++ b/heap/_check.c @@ -167,7 +167,7 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records, ulong found= 0; byte *key, *recpos; uint key_length; - uint not_used; + uint not_used[2]; if ((key= tree_search_edge(&keydef->rb_tree, info->parents, &info->last_pos, offsetof(TREE_ELEMENT, left)))) @@ -177,7 +177,7 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records, memcpy(&recpos, key + (*keydef->get_key_length)(keydef,key), sizeof(byte*)); key_length= hp_rb_make_key(keydef, info->recbuf, recpos, 0); if (ha_key_cmp(keydef->seg, (uchar*) info->recbuf, (uchar*) key, - key_length, SEARCH_FIND | SEARCH_SAME, ¬_used)) + key_length, SEARCH_FIND | SEARCH_SAME, not_used)) { error= 1; DBUG_PRINT("error",("Record in wrong link: key: %d Record: 0x%lx\n", diff --git a/heap/hp_create.c b/heap/hp_create.c index 8fcf7dde000..47dcb00278a 100644 --- a/heap/hp_create.c +++ b/heap/hp_create.c @@ -203,9 +203,9 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2) { - uint not_used; + uint not_used[2]; return ha_key_cmp(param->keyseg, key1, key2, param->key_length, - param->search_flag, ¬_used); + param->search_flag, not_used); } static void init_block(HP_BLOCK *block, uint reclength, ulong min_records, diff --git a/include/Makefile.am b/include/Makefile.am index 5f426843950..8ad63f088ac 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -29,7 +29,7 @@ noinst_HEADERS = config-win.h config-os2.h config-netware.h \ mysys_err.h my_base.h help_start.h help_end.h \ my_nosys.h my_alarm.h queues.h rijndael.h sha1.h \ my_aes.h my_tree.h hash.h thr_alarm.h \ - thr_lock.h t_ctype.h violite.h md5.h \ + thr_lock.h t_ctype.h violite.h md5.h base64.h \ mysql_version.h.in my_handler.h my_time.h decimal.h # mysql_version.h are generated @@ -38,20 +38,12 @@ CLEANFILES = mysql_version.h my_config.h readline # Some include files that may be moved and patched by configure DISTCLEANFILES = sched.h $(CLEANFILES) -all-local: my_config.h - -# Since we include my_config.h it better exist from the beginning link_sources: - $(CP) ../config.h my_config.h -$(RM) -fr readline @readline_h_ln_cmd@ -# Keep automake happy - my_config.h: ../config.h $(CP) ../config.h my_config.h - -$(RM) -fr readline - @readline_h_ln_cmd@ # These files should not be included in distributions since they are # generated by configure from the .h.in files diff --git a/include/config-netware.h b/include/config-netware.h index 4c46ccd3ec7..f517e3c34d3 100644 --- a/include/config-netware.h +++ b/include/config-netware.h @@ -72,9 +72,10 @@ extern "C" { #undef HAVE_CRYPT #endif /* HAVE_OPENSSL */ -/* Configure can't detect this because it uses AC_TRY_RUN */ +/* Netware has an ancient zlib */ #undef HAVE_COMPRESS #define HAVE_COMPRESS +#undef HAVE_ARCHIVE_DB /* include the old function apis */ #define USE_OLD_FUNCTIONS 1 @@ -118,15 +119,12 @@ extern "C" { /* do not use the extended time in LibC sys\stat.h */ #define _POSIX_SOURCE -/* Kernel call on NetWare that will only yield if our time slice is up */ -void kYieldIfTimeSliceUp(void); - /* Some macros for portability */ #define set_timespec(ABSTIME,SEC) { (ABSTIME).tv_sec=time(NULL)+(SEC); (ABSTIME).tv_nsec=0; } /* extra protection against CPU Hogs on NetWare */ -#define NETWARE_YIELD kYieldIfTimeSliceUp() +#define NETWARE_YIELD pthread_yield() /* Screen mode for help texts */ #define NETWARE_SET_SCREEN_MODE(A) setscreenmode(A) diff --git a/include/config-win.h b/include/config-win.h index fe099c11a2f..53483f3f39d 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -22,6 +22,11 @@ functions */ #define _WIN32_WINNT 0x0500 #endif +#if defined(_MSC_VER) && _MSC_VER >= 1400 +/* Avoid endless warnings about sprintf() etc. being unsafe. */ +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + #include <sys/locking.h> #include <windows.h> #include <math.h> /* Because of rint() */ @@ -61,6 +66,10 @@ functions */ #define __WIN__ /* To make it easier in VC++ */ #endif +#ifndef MAX_INDEXES +#define MAX_INDEXES 64 +#endif + /* File and lock constants */ #define O_SHARE 0x1000 /* Open file in sharing mode */ #ifdef __BORLANDC__ @@ -279,10 +288,10 @@ inline double ulonglong2double(ulonglong value) *((T)+4)=(uchar) (((A) >> 32)); } #define int8store(T,A) *((ulonglong *) (T))= (ulonglong) (A) -#define doubleget(V,M) { *((long *) &V) = *((long*) M); \ - *(((long *) &V)+1) = *(((long*) M)+1); } -#define doublestore(T,V) { *((long *) T) = *((long*) &V); \ - *(((long *) T)+1) = *(((long*) &V)+1); } +#define doubleget(V,M) do { *((long *) &V) = *((long*) M); \ + *(((long *) &V)+1) = *(((long*) M)+1); } while(0) +#define doublestore(T,V) do { *((long *) T) = *((long*) &V); \ + *(((long *) T)+1) = *(((long*) &V)+1); } while(0) #define float4get(V,M) { *((long *) &(V)) = *((long*) (M)); } #define floatstore(T,V) memcpy((byte*)(T), (byte*)(&V), sizeof(float)) #define floatget(V,M) memcpy((byte*)(&V), (byte*)(M), sizeof(float)) @@ -325,6 +334,16 @@ inline double ulonglong2double(ulonglong value) #define HAVE_SETFILEPOINTER #define HAVE_VIO_READ_BUFF +#if defined(_WIN64) && defined(_M_X64) +/* Avoid type conflicts with built-in functions. */ +#define HAVE_STRNLEN +#endif + +#ifndef __NT__ +#undef FILE_SHARE_DELETE +#define FILE_SHARE_DELETE 0 /* Not implemented on Win 98/ME */ +#endif + #ifdef NOT_USED #define HAVE_SNPRINTF /* Gave link error */ #define _snprintf snprintf @@ -392,8 +411,8 @@ inline double ulonglong2double(ulonglong value) #define HAVE_SPATIAL 1 #define HAVE_RTREE_KEYS 1 -#define HAVE_OPENSSL 1 -#define HAVE_YASSL 1 +/* #undef HAVE_OPENSSL */ +/* #undef HAVE_YASSL */ /* Define charsets you want */ /* #undef HAVE_CHARSET_armscii8 */ diff --git a/include/hash.h b/include/hash.h index 9a6d91036e1..8f5ff21ae5e 100644 --- a/include/hash.h +++ b/include/hash.h @@ -33,7 +33,7 @@ typedef void (*hash_free_key)(void *); typedef struct st_hash { uint key_offset,key_length; /* Length of key if const length */ - uint records,blength,current_record; + uint records, blength; uint flags; DYNAMIC_ARRAY array; /* Place for hash_keys */ hash_get_key get_key; @@ -41,6 +41,9 @@ typedef struct st_hash { CHARSET_INFO *charset; } HASH; +/* A search iterator state */ +typedef uint HASH_SEARCH_STATE; + #define hash_init(A,B,C,D,E,F,G,H) _hash_init(A,B,C,D,E,F,G, H CALLER_INFO) my_bool _hash_init(HASH *hash, CHARSET_INFO *charset, uint default_array_elements, uint key_offset, @@ -49,12 +52,15 @@ my_bool _hash_init(HASH *hash, CHARSET_INFO *charset, void hash_free(HASH *tree); void my_hash_reset(HASH *hash); byte *hash_element(HASH *hash,uint idx); -gptr hash_search(HASH *info,const byte *key,uint length); -gptr hash_next(HASH *info,const byte *key,uint length); +gptr hash_search(const HASH *info, const byte *key, uint length); +gptr hash_first(const HASH *info, const byte *key, uint length, + HASH_SEARCH_STATE *state); +gptr hash_next(const HASH *info, const byte *key, uint length, + HASH_SEARCH_STATE *state); my_bool my_hash_insert(HASH *info,const byte *data); my_bool hash_delete(HASH *hash,byte *record); my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length); -void hash_replace(HASH *hash, uint idx, byte *new_row); +void hash_replace(HASH *hash, HASH_SEARCH_STATE *state, byte *new_row); my_bool hash_check(HASH *hash); /* Only in debug library */ #define hash_clear(H) bzero((char*) (H),sizeof(*(H))) diff --git a/include/my_base.h b/include/my_base.h index c76cf8c604e..8eab79a96fd 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -248,6 +248,7 @@ enum ha_base_keytype { #define HA_OPTION_CHECKSUM 32 #define HA_OPTION_DELAY_KEY_WRITE 64 #define HA_OPTION_NO_PACK_KEYS 128 /* Reserved for MySQL */ +#define HA_OPTION_CREATE_FROM_ENGINE 256 #define HA_OPTION_TEMP_COMPRESS_RECORD ((uint) 16384) /* set by isamchk */ #define HA_OPTION_READ_ONLY_DATA ((uint) 32768) /* Set by isamchk */ @@ -258,17 +259,49 @@ enum ha_base_keytype { #define HA_CREATE_TMP_TABLE 4 #define HA_CREATE_CHECKSUM 8 #define HA_CREATE_DELAY_KEY_WRITE 64 -#define HA_CREATE_FROM_ENGINE 128 - /* Bits in flag to _status */ +/* + The following flags (OR-ed) are passed to handler::info() method. + The method copies misc handler information out of the storage engine + to data structures accessible from MySQL + + Same flags are also passed down to mi_status, myrg_status, etc. +*/ -#define HA_STATUS_POS 1 /* Return position */ -#define HA_STATUS_NO_LOCK 2 /* Don't use external lock */ -#define HA_STATUS_TIME 4 /* Return update time */ -#define HA_STATUS_CONST 8 /* Return constants values */ -#define HA_STATUS_VARIABLE 16 -#define HA_STATUS_ERRKEY 32 -#define HA_STATUS_AUTO 64 +/* this one is not used */ +#define HA_STATUS_POS 1 +/* + assuming the table keeps shared actual copy of the 'info' and + local, possibly outdated copy, the following flag means that + it should not try to get the actual data (locking the shared structure) + slightly outdated version will suffice +*/ +#define HA_STATUS_NO_LOCK 2 +/* update the time of the last modification (in handler::update_time) */ +#define HA_STATUS_TIME 4 +/* + update the 'constant' part of the info: + handler::max_data_file_length, max_index_file_length, create_time + sortkey, ref_length, block_size, data_file_name, index_file_name. + handler::table->s->keys_in_use, keys_for_keyread, rec_per_key +*/ +#define HA_STATUS_CONST 8 +/* + update the 'variable' part of the info: + handler::records, deleted, data_file_length, index_file_length, + delete_length, check_time, mean_rec_length +*/ +#define HA_STATUS_VARIABLE 16 +/* + get the information about the key that caused last duplicate value error + update handler::errkey and handler::dupp_ref + see handler::get_dup_key() +*/ +#define HA_STATUS_ERRKEY 32 +/* + update handler::auto_increment_value +*/ +#define HA_STATUS_AUTO 64 /* Errorcodes given by functions */ diff --git a/include/my_global.h b/include/my_global.h index b32a8fe6baa..0df9ac78eb2 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -453,6 +453,17 @@ typedef unsigned short ushort; #define __attribute__(A) #endif +/* + Wen using the embedded library, users might run into link problems, + dupicate declaration of __cxa_pure_virtual, solved by declaring it a + weak symbol. +*/ +#ifdef USE_MYSYS_NEW +C_MODE_START +int __cxa_pure_virtual () __attribute__ ((weak)); +C_MODE_END +#endif + /* From old s-system.h */ /* @@ -553,6 +564,15 @@ typedef SOCKET_SIZE_TYPE size_socket; #define O_NOFOLLOW 0 #endif +/* additional file share flags for win32 */ +#ifdef __WIN__ +#define _SH_DENYRWD 0x110 /* deny read/write mode & delete */ +#define _SH_DENYWRD 0x120 /* deny write mode & delete */ +#define _SH_DENYRDD 0x130 /* deny read mode & delete */ +#define _SH_DENYDEL 0x140 /* deny delete only */ +#endif /* __WIN__ */ + + /* #define USE_RECORD_LOCK */ /* Unsigned types supported by the compiler */ @@ -565,11 +585,7 @@ typedef SOCKET_SIZE_TYPE size_socket; #define FN_LEN 256 /* Max file name len */ #define FN_HEADLEN 253 /* Max length of filepart of file name */ #define FN_EXTLEN 20 /* Max length of extension (part of FN_LEN) */ -#ifdef PATH_MAX -#define FN_REFLEN PATH_MAX/* Max length of full path-name */ -#else #define FN_REFLEN 512 /* Max length of full path-name */ -#endif #define FN_EXTCHAR '.' #define FN_HOMELIB '~' /* ~/ is used as abbrev for home dir */ #define FN_CURLIB '.' /* ./ is used as abbrev for current dir */ @@ -846,6 +862,7 @@ typedef off_t os_off_t; #define SOCKET_EAGAIN WSAEINPROGRESS #define SOCKET_ETIMEDOUT WSAETIMEDOUT #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK +#define SOCKET_EADDRINUSE WSAEADDRINUSE #define SOCKET_ENFILE ENFILE #define SOCKET_EMFILE EMFILE #elif defined(OS2) @@ -854,6 +871,7 @@ typedef off_t os_off_t; #define SOCKET_EAGAIN SOCEINPROGRESS #define SOCKET_ETIMEDOUT SOCKET_EINTR #define SOCKET_EWOULDBLOCK SOCEWOULDBLOCK +#define SOCKET_EADDRINUSE SOCEADDRINUSE #define SOCKET_ENFILE SOCENFILE #define SOCKET_EMFILE SOCEMFILE #define closesocket(A) soclose(A) @@ -864,6 +882,7 @@ typedef off_t os_off_t; #define SOCKET_EAGAIN EAGAIN #define SOCKET_ETIMEDOUT SOCKET_EINTR #define SOCKET_EWOULDBLOCK EWOULDBLOCK +#define SOCKET_EADDRINUSE EADDRINUSE #define SOCKET_ENFILE ENFILE #define SOCKET_EMFILE EMFILE #endif diff --git a/include/my_handler.h b/include/my_handler.h index c076ba0c2c9..d531e0fb3e1 100644 --- a/include/my_handler.h +++ b/include/my_handler.h @@ -88,4 +88,6 @@ extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, register uchar *b, uint key_length, uint nextflag, uint *diff_pos); +extern HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a); + #endif /* _my_handler_h */ diff --git a/include/my_pthread.h b/include/my_pthread.h index 3d9056541d7..202e047dc4e 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -25,10 +25,10 @@ #endif #ifdef __cplusplus -#define EXTERN_C extern "C" +#define EXTERNC extern "C" extern "C" { #else -#define EXTERN_C +#define EXTERNC #endif /* __cplusplus */ #if defined(__WIN__) || defined(OS2) @@ -80,10 +80,10 @@ struct timespec { /* For pthread_cond_timedwait() */ typedef int pthread_mutexattr_t; #define win_pthread_self my_thread_var->pthread_self #ifdef OS2 -#define pthread_handler_t EXTERN_C void * _Optlink +#define pthread_handler_t EXTERNC void * _Optlink typedef void * (_Optlink *pthread_handler)(void *); #else -#define pthread_handler_t EXTERN_C void * __cdecl +#define pthread_handler_t EXTERNC void * __cdecl typedef void * (__cdecl *pthread_handler)(void *); #endif @@ -187,7 +187,7 @@ typedef int pthread_attr_t; /* Needed by Unixware 7.0.0 */ #define pthread_key_create(A,B) thr_keycreate((A),(B)) #define pthread_key_delete(A) thr_keydelete(A) -#define pthread_handler_t EXTERN_C void * +#define pthread_handler_t EXTERNC void * #define pthread_key(T,V) pthread_key_t V void * my_pthread_getspecific_imp(pthread_key_t key); @@ -265,7 +265,7 @@ extern int my_pthread_getprio(pthread_t thread_id); #define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V)) #define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V)) #define pthread_detach_this_thread() -#define pthread_handler_t EXTERN_C void * +#define pthread_handler_t EXTERNC void * typedef void *(* pthread_handler)(void *); /* Test first for RTS or FSU threads */ @@ -536,9 +536,15 @@ void safe_mutex_end(FILE *file); #define pthread_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__) #define pthread_mutex_trylock(A) pthread_mutex_lock(A) #define pthread_mutex_t safe_mutex_t -#define safe_mutex_assert_owner(mp) DBUG_ASSERT((mp)->count > 0 && pthread_equal(pthread_self(),(mp)->thread)) +#define safe_mutex_assert_owner(mp) \ + DBUG_ASSERT((mp)->count > 0 && \ + pthread_equal(pthread_self(), (mp)->thread)) +#define safe_mutex_assert_not_owner(mp) \ + DBUG_ASSERT(! (mp)->count || \ + ! pthread_equal(pthread_self(), (mp)->thread)) #else #define safe_mutex_assert_owner(mp) +#define safe_mutex_assert_not_owner(mp) #endif /* SAFE_MUTEX */ /* READ-WRITE thread locking */ @@ -637,10 +643,10 @@ extern int pthread_dummy(int); #define THREAD_NAME_SIZE 10 #ifndef DEFAULT_THREAD_STACK -#if defined(__ia64__) +#if SIZEOF_CHARP > 4 /* MySQL can survive with 32K, but some glibc libraries require > 128K stack - To resolve hostnames + To resolve hostnames. Also recursive stored procedures needs stack. */ #define DEFAULT_THREAD_STACK (256*1024L) #else diff --git a/include/my_sys.h b/include/my_sys.h index 76031806b82..44fe383bf4f 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -601,6 +601,7 @@ extern char *_my_strdup_with_length(const byte *from, uint length, #ifdef __WIN__ extern int my_access(const char *path, int amode); +extern File my_sopen(const char *path, int oflag, int shflag, int pmode); #else #define my_access access #endif diff --git a/include/myisam.h b/include/myisam.h index 39cc61ad204..96c1e7e192e 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -33,8 +33,6 @@ extern "C" { #endif #include "my_handler.h" - /* defines used by myisam-funktions */ - /* There is a hard limit for the maximum number of keys as there are only 8 bits in the index file header for the number of keys in a table. @@ -45,14 +43,19 @@ extern "C" { running myisamchk compiled for 128 keys on a table with 255 keys. */ #define MI_MAX_POSSIBLE_KEY 255 /* For myisam_chk */ +#if MAX_INDEXES > MI_MAX_POSSIBLE_KEY +#define MI_MAX_KEY MI_MAX_POSSIBLE_KEY /* Max allowed keys */ +#else +#define MI_MAX_KEY MAX_INDEXES /* Max allowed keys */ +#endif + #define MI_MAX_POSSIBLE_KEY_BUFF (1024+6+6) /* For myisam_chk */ /* The following defines can be increased if necessary. - BUT: MI_MAX_KEY must be <= MI_MAX_POSSIBLE_KEY. + But beware the dependency of MI_MAX_POSSIBLE_KEY_BUFF and MI_MAX_KEY_LENGTH. */ -#define MI_MAX_KEY 64 /* Max allowed keys */ +#define MI_MAX_KEY_LENGTH 1000 /* Max length in bytes */ #define MI_MAX_KEY_SEG 16 /* Max segments for key */ -#define MI_MAX_KEY_LENGTH 1000 #define MI_MAX_KEY_BUFF (MI_MAX_KEY_LENGTH+MI_MAX_KEY_SEG*6+8+8) #define MI_MAX_MSG_BUF 1024 /* used in CHECK TABLE, REPAIR TABLE */ @@ -392,7 +395,9 @@ typedef enum /* Treat NULLs as inequal when collecting statistics (default for 4.1/5.0) */ MI_STATS_METHOD_NULLS_NOT_EQUAL, /* Treat NULLs as equal when collecting statistics (like 4.0 did) */ - MI_STATS_METHOD_NULLS_EQUAL + MI_STATS_METHOD_NULLS_EQUAL, + /* Ignore NULLs - count only tuples without NULLs in the index components */ + MI_STATS_METHOD_IGNORE_NULLS } enum_mi_stats_method; typedef struct st_mi_check_param @@ -419,7 +424,14 @@ typedef struct st_mi_check_param int tmpfile_createflag; myf myf_rw; IO_CACHE read_cache; + + /* + The next two are used to collect statistics, see update_key_parts for + description. + */ ulonglong unique_count[MI_MAX_KEY_SEG+1]; + ulonglong notnull_count[MI_MAX_KEY_SEG+1]; + ha_checksum key_crc[MI_MAX_POSSIBLE_KEY]; ulong rec_per_key_part[MI_MAX_KEY_SEG*MI_MAX_POSSIBLE_KEY]; void *thd; @@ -479,7 +491,8 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info, my_bool repair); int update_state_info(MI_CHECK *param, MI_INFO *info,uint update); void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part, - ulonglong *unique, ulonglong records); + ulonglong *unique, ulonglong *notnull, + ulonglong records); int filecopy(MI_CHECK *param, File to,File from,my_off_t start, my_off_t length, const char *type); int movepoint(MI_INFO *info,byte *record,my_off_t oldpos, diff --git a/include/mysql.h b/include/mysql.h index c4b4e026e5b..f3244d4ba36 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -117,6 +117,9 @@ typedef unsigned long long my_ulonglong; #define MYSQL_COUNT_ERROR (~(my_ulonglong) 0) +/* backward compatibility define - to be removed eventually */ +#define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED + typedef struct st_mysql_rows { struct st_mysql_rows *next; /* list of rows */ MYSQL_ROW data; diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 7a4e92a672a..81f23cfa99c 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -889,7 +889,8 @@ Drops a page hash index. */ void btr_search_drop_page_hash_index( /*============================*/ - page_t* page) /* in: index page, s- or x-latched */ + page_t* page) /* in: index page, s- or x-latched, or an index page + for which we know that block->buf_fix_count == 0 */ { hash_table_t* table; buf_block_t* block; @@ -904,6 +905,7 @@ btr_search_drop_page_hash_index( ulint* folds; ulint i; mem_heap_t* heap; + dict_index_t* index; ulint* offsets; #ifdef UNIV_SYNC_DEBUG @@ -932,11 +934,16 @@ btr_search_drop_page_hash_index( n_fields = block->curr_n_fields; n_bytes = block->curr_n_bytes; + index = block->index; - ut_a(n_fields + n_bytes > 0); + /* NOTE: The fields of block must not be accessed after + releasing btr_search_latch, as the index page might only + be s-latched! */ rw_lock_s_unlock(&btr_search_latch); + ut_a(n_fields + n_bytes > 0); + n_recs = page_get_n_recs(page); /* Calculate and cache fold values into an array for fast deletion @@ -949,14 +956,6 @@ btr_search_drop_page_hash_index( rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); - if (!page_rec_is_supremum(rec)) { - ut_a(n_fields <= rec_get_n_fields(rec, block->index)); - - if (n_bytes > 0) { - ut_a(n_fields < rec_get_n_fields(rec, block->index)); - } - } - tree_id = btr_page_get_index_id(page); prev_fold = 0; @@ -964,18 +963,12 @@ btr_search_drop_page_hash_index( heap = NULL; offsets = NULL; - if (block->index == NULL) { - - mem_analyze_corruption((byte*)block); - - ut_a(block->index != NULL); - } - while (!page_rec_is_supremum(rec)) { /* FIXME: in a mixed tree, not all records may have enough ordering fields: */ - offsets = rec_get_offsets(rec, block->index, - offsets, n_fields + (n_bytes > 0), &heap); + offsets = rec_get_offsets(rec, index, offsets, + n_fields + (n_bytes > 0), &heap); + ut_a(rec_offs_n_fields(offsets) == n_fields + (n_bytes > 0)); fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id); if (fold == prev_fold && prev_fold != 0) { diff --git a/innobase/btr/makefilewin b/innobase/btr/makefilewin deleted file mode 100644 index a5806b74a51..00000000000 --- a/innobase/btr/makefilewin +++ /dev/null @@ -1,16 +0,0 @@ -include ..\include\makefile.i - -btr.lib: btr0cur.obj btr0btr.obj btr0pcur.obj btr0sea.obj - lib -out:..\libs\btr.lib btr0cur.obj btr0btr.obj btr0pcur.obj btr0sea.obj - -btr0cur.obj: btr0cur.c - $(CCOM) $(CFL) -c btr0cur.c - -btr0btr.obj: btr0btr.c - $(CCOM) $(CFL) -c btr0btr.c - -btr0sea.obj: btr0sea.c - $(CCOM) $(CFL) -c btr0sea.c - -btr0pcur.obj: btr0pcur.c - $(CCOM) $(CFL) -c btr0pcur.c diff --git a/innobase/buf/makefilewin b/innobase/buf/makefilewin deleted file mode 100644 index ce62cb95958..00000000000 --- a/innobase/buf/makefilewin +++ /dev/null @@ -1,20 +0,0 @@ -include ..\include\makefile.i - -buf.lib: buf0buf.obj buf0lru.obj buf0flu.obj buf0rea.obj - lib -out:..\libs\buf.lib buf0buf.obj buf0lru.obj buf0flu.obj buf0rea.obj - -buf0buf.obj: buf0buf.c - $(CCOM) $(CFL) -c buf0buf.c - -buf0lru.obj: buf0lru.c - $(CCOM) $(CFL) -c buf0lru.c - -buf0flu.obj: buf0flu.c - $(CCOM) $(CFL) -c buf0flu.c - -buf0rea.obj: buf0rea.c - $(CCOM) $(CFL) -c buf0rea.c - - - - diff --git a/innobase/data/makefilewin b/innobase/data/makefilewin deleted file mode 100644 index 785b75fbb2b..00000000000 --- a/innobase/data/makefilewin +++ /dev/null @@ -1,11 +0,0 @@ -include ..\include\makefile.i - -data.lib: data0type.obj data0data.obj - lib -out:..\libs\data.lib data0type.obj data0data.obj - -data0type.obj: data0type.c - $(CCOM) $(CFL) -c data0type.c - -data0data.obj: data0data.c - $(CCOM) $(CFL) -c data0data.c - diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index fb95ffbd80c..8050eebddd8 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -2104,8 +2104,11 @@ dict_foreign_find_index( dict_table_t* table, /* in: table */ const char** columns,/* in: array of column names */ ulint n_cols, /* in: number of columns */ - dict_index_t* types_idx)/* in: NULL or an index to whose types the - column types must match */ + dict_index_t* types_idx, /* in: NULL or an index to whose types the + column types must match */ + ibool check_charsets) /* in: whether to check charsets. + only has an effect if types_idx != + NULL. */ { #ifndef UNIV_HOTBACKUP dict_index_t* index; @@ -2135,7 +2138,8 @@ dict_foreign_find_index( if (types_idx && !cmp_types_are_equal( dict_index_get_nth_type(index, i), - dict_index_get_nth_type(types_idx, i))) { + dict_index_get_nth_type(types_idx, i), + check_charsets)) { break; } @@ -2212,7 +2216,8 @@ dict_foreign_add_to_cache( /*======================*/ /* out: DB_SUCCESS or error code */ dict_foreign_t* foreign, /* in, own: foreign key constraint */ - ibool check_types) /* in: TRUE=check type compatibility */ + ibool check_charsets) /* in: TRUE=check charset + compatibility */ { dict_table_t* for_table; dict_table_t* ref_table; @@ -2248,16 +2253,10 @@ dict_foreign_add_to_cache( } if (for_in_cache->referenced_table == NULL && ref_table) { - dict_index_t* types_idx; - if (check_types) { - types_idx = for_in_cache->foreign_index; - } else { - types_idx = NULL; - } index = dict_foreign_find_index(ref_table, (const char**) for_in_cache->referenced_col_names, for_in_cache->n_fields, - types_idx); + for_in_cache->foreign_index, check_charsets); if (index == NULL) { dict_foreign_error_report(ef, for_in_cache, @@ -2281,16 +2280,10 @@ dict_foreign_add_to_cache( } if (for_in_cache->foreign_table == NULL && for_table) { - dict_index_t* types_idx; - if (check_types) { - types_idx = for_in_cache->referenced_index; - } else { - types_idx = NULL; - } index = dict_foreign_find_index(for_table, (const char**) for_in_cache->foreign_col_names, for_in_cache->n_fields, - types_idx); + for_in_cache->referenced_index, check_charsets); if (index == NULL) { dict_foreign_error_report(ef, for_in_cache, @@ -3097,7 +3090,7 @@ col_loop1: /* Try to find an index which contains the columns as the first fields and in the right order */ - index = dict_foreign_find_index(table, column_names, i, NULL); + index = dict_foreign_find_index(table, column_names, i, NULL, TRUE); if (!index) { mutex_enter(&dict_foreign_err_mutex); @@ -3362,8 +3355,7 @@ try_find_index: if (referenced_table) { index = dict_foreign_find_index(referenced_table, - column_names, i, - foreign->foreign_index); + column_names, i, foreign->foreign_index, TRUE); if (!index) { dict_foreign_free(foreign); mutex_enter(&dict_foreign_err_mutex); diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index 9bafcf33553..3281f9926f9 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -1091,7 +1091,7 @@ dict_load_foreign( /* out: DB_SUCCESS or error code */ const char* id, /* in: foreign constraint id as a null-terminated string */ - ibool check_types)/* in: TRUE=check type compatibility */ + ibool check_charsets)/* in: TRUE=check charset compatibility */ { dict_foreign_t* foreign; dict_table_t* sys_foreign; @@ -1204,7 +1204,7 @@ dict_load_foreign( a new foreign key constraint but loading one from the data dictionary. */ - return(dict_foreign_add_to_cache(foreign, check_types)); + return(dict_foreign_add_to_cache(foreign, check_charsets)); } /*************************************************************************** @@ -1219,7 +1219,8 @@ dict_load_foreigns( /*===============*/ /* out: DB_SUCCESS or error code */ const char* table_name, /* in: table name */ - ibool check_types) /* in: TRUE=check type compatibility */ + ibool check_charsets) /* in: TRUE=check charset + compatibility */ { btr_pcur_t pcur; mem_heap_t* heap; @@ -1319,7 +1320,7 @@ loop: /* Load the foreign constraint definition to the dictionary cache */ - err = dict_load_foreign(id, check_types); + err = dict_load_foreign(id, check_charsets); if (err != DB_SUCCESS) { btr_pcur_close(&pcur); diff --git a/innobase/dict/makefilewin b/innobase/dict/makefilewin deleted file mode 100644 index e828d06943c..00000000000 --- a/innobase/dict/makefilewin +++ /dev/null @@ -1,21 +0,0 @@ -include ..\include\makefile.i - -dict.lib: dict0dict.obj dict0boot.obj dict0load.obj dict0mem.obj dict0crea.obj - lib -out:..\libs\dict.lib dict0dict.obj dict0boot.obj dict0load.obj dict0mem.obj dict0crea.obj - -dict0dict.obj: dict0dict.c - $(CCOM) $(CFL) -c dict0dict.c - -dict0boot.obj: dict0boot.c - $(CCOM) $(CFL) -c dict0boot.c - -dict0mem.obj: dict0mem.c - $(CCOM) $(CFL) -c dict0mem.c - -dict0crea.obj: dict0crea.c - $(CCOM) $(CFL) -c dict0crea.c - -dict0load.obj: dict0load.c - $(CCOM) $(CFL) -c dict0load.c - - diff --git a/innobase/dyn/makefilewin b/innobase/dyn/makefilewin deleted file mode 100644 index 71a58a756c1..00000000000 --- a/innobase/dyn/makefilewin +++ /dev/null @@ -1,9 +0,0 @@ -include ..\include\makefile.i - -dyn.lib: dyn0dyn.obj makefile - lib -out:..\libs\dyn.lib dyn0dyn.obj - -dyn0dyn.obj: dyn0dyn.c - $(CCOM) $(CFL) -c dyn0dyn.c - - diff --git a/innobase/eval/makefilewin b/innobase/eval/makefilewin deleted file mode 100644 index f587f2a05a6..00000000000 --- a/innobase/eval/makefilewin +++ /dev/null @@ -1,10 +0,0 @@ -include ..\include\makefile.i - -eval.lib: eval0eval.obj eval0proc.obj - lib -out:..\libs\eval.lib eval0eval.obj eval0proc.obj - -eval0eval.obj: eval0eval.c - $(CCOM) $(CFL) -c eval0eval.c - -eval0proc.obj: eval0proc.c - $(CCOM) $(CFL) -c eval0proc.c diff --git a/innobase/fil/makefilewin b/innobase/fil/makefilewin deleted file mode 100644 index 1b2d6ab2dbb..00000000000 --- a/innobase/fil/makefilewin +++ /dev/null @@ -1,10 +0,0 @@ -include ..\include\makefile.i - -fil.lib: fil0fil.obj - lib -out:..\libs\fil.lib fil0fil.obj - -fil0fil.obj: fil0fil.c - $(CCOM) $(CFL) -c fil0fil.c - - - diff --git a/innobase/fsp/makefilewin b/innobase/fsp/makefilewin deleted file mode 100644 index 503cf27f490..00000000000 --- a/innobase/fsp/makefilewin +++ /dev/null @@ -1,9 +0,0 @@ -include ..\include\makefile.i - -fsp.lib: fsp0fsp.obj - lib -out:..\libs\fsp.lib fsp0fsp.obj - -fsp0fsp.obj: fsp0fsp.c - $(CCOM) $(CFL) -c fsp0fsp.c - - diff --git a/innobase/fut/makefilewin b/innobase/fut/makefilewin deleted file mode 100644 index 40f3161015c..00000000000 --- a/innobase/fut/makefilewin +++ /dev/null @@ -1,12 +0,0 @@ -include ..\include\makefile.i - -fut.lib: fut0lst.obj fut0fut.obj - lib -out:..\libs\fut.lib fut0lst.obj fut0fut.obj - -fut0lst.obj: fut0lst.c - $(CCOM) $(CFL) -c fut0lst.c - -fut0fut.obj: fut0fut.c - $(CCOM) $(CFL) -c fut0fut.c - - diff --git a/innobase/ha/makefilewin b/innobase/ha/makefilewin deleted file mode 100644 index c7cd130ceea..00000000000 --- a/innobase/ha/makefilewin +++ /dev/null @@ -1,10 +0,0 @@ -include ..\include\makefile.i - -ha.lib: ha0ha.obj hash0hash.obj - lib -out:..\libs\ha.lib ha0ha.obj hash0hash.obj - -ha0ha.obj: ha0ha.c - $(CCOM) $(CFL) -c ha0ha.c - -hash0hash.obj: hash0hash.c - $(CCOM) $(CFL) -c hash0hash.c diff --git a/innobase/ibuf/makefilewin b/innobase/ibuf/makefilewin deleted file mode 100644 index 86bf9794520..00000000000 --- a/innobase/ibuf/makefilewin +++ /dev/null @@ -1,7 +0,0 @@ -include ..\include\makefile.i - -ibuf.lib: ibuf0ibuf.obj - lib -out:..\libs\ibuf.lib ibuf0ibuf.obj - -ibuf0ibuf.obj: ibuf0ibuf.c - $(CCOM) $(CFL) -c ibuf0ibuf.c diff --git a/innobase/include/Makefile.am b/innobase/include/Makefile.am index eb1e3b72877..b83aee06680 100644 --- a/innobase/include/Makefile.am +++ b/innobase/include/Makefile.am @@ -28,7 +28,7 @@ noinst_HEADERS = btr0btr.h btr0btr.ic btr0cur.h btr0cur.ic \ ha0ha.h ha0ha.ic hash0hash.h hash0hash.ic \ ibuf0ibuf.h ibuf0ibuf.ic ibuf0types.h lock0lock.h \ lock0lock.ic lock0types.h log0log.h log0log.ic log0recv.h \ - log0recv.ic mach0data.h mach0data.ic makefilewin.i \ + log0recv.ic mach0data.h mach0data.ic \ mem0dbg.h mem0dbg.ic mem0mem.h mem0mem.ic mem0pool.h \ mem0pool.ic mtr0log.h mtr0log.ic mtr0mtr.h mtr0mtr.ic \ mtr0types.h os0file.h os0proc.h os0proc.ic \ diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index ae8d0411c12..fc1d9a64c7f 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -745,8 +745,6 @@ struct buf_block_struct{ buffer pool which are index pages, but this flag is not set because we do not keep track of all pages */ - dict_index_t* index; /* index for which the adaptive - hash index has been created */ /* 2. Page flushing fields */ UT_LIST_NODE_T(buf_block_t) flush_list; @@ -833,7 +831,13 @@ struct buf_block_struct{ records with the same prefix should be indexed in the hash index */ - /* The following 4 fields are protected by btr_search_latch: */ + /* These 6 fields may only be modified when we have + an x-latch on btr_search_latch AND + a) we are holding an s-latch or x-latch on block->lock or + b) we know that block->buf_fix_count == 0. + + An exception to this is when we init or create a page + in the buffer pool in buf0buf.c. */ ibool is_hashed; /* TRUE if hash index has already been built on this page; note that it does @@ -850,6 +854,8 @@ struct buf_block_struct{ ulint curr_side; /* BTR_SEARCH_LEFT_SIDE or BTR_SEARCH_RIGHT_SIDE in hash indexing */ + dict_index_t* index; /* Index for which the adaptive + hash index has been created. */ /* 6. Debug fields */ #ifdef UNIV_SYNC_DEBUG rw_lock_t debug_latch; /* in the debug version, each thread diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h index 5215d51cabe..4396611e529 100644 --- a/innobase/include/dict0dict.h +++ b/innobase/include/dict0dict.h @@ -197,7 +197,8 @@ dict_foreign_add_to_cache( /*======================*/ /* out: DB_SUCCESS or error code */ dict_foreign_t* foreign, /* in, own: foreign key constraint */ - ibool check_types); /* in: TRUE=check type compatibility */ + ibool check_charsets);/* in: TRUE=check charset + compatibility */ /************************************************************************* Checks if a table is referenced by foreign keys. */ diff --git a/innobase/include/dict0load.h b/innobase/include/dict0load.h index f13620bc6e8..741123614ab 100644 --- a/innobase/include/dict0load.h +++ b/innobase/include/dict0load.h @@ -82,7 +82,8 @@ dict_load_foreigns( /*===============*/ /* out: DB_SUCCESS or error code */ const char* table_name, /* in: table name */ - ibool check_types); /* in: TRUE=check type compatibility */ + ibool check_charsets);/* in: TRUE=check charsets + compatibility */ /************************************************************************ Prints to the standard output information on all tables found in the data dictionary system table. */ diff --git a/innobase/include/makefilewin.i b/innobase/include/makefilewin.i deleted file mode 100644 index f756cf2ea3a..00000000000 --- a/innobase/include/makefilewin.i +++ /dev/null @@ -1,34 +0,0 @@ -# File included in all makefiles of the database -# (c) Innobase Oy 1995 - 2000 - -CCOM=cl - -# Flags for the debug version -#CFL= -MTd -Za -Zi -W4 -WX -F8192 -D "WIN32" -#CFLN = -MTd -Zi -W4 -F8192 -D "WIN32" -#CFLW = -MTd -Zi -W3 -WX -F8192 -D "WIN32" -#LFL = - -# Flags for the fast version -#CFL= -MT -Zi -Og -O2 -W3 -WX -D "WIN32" -#CFLN = -MT -Zi -Og -O2 -W3 -D "WIN32" -#CFLW = -MT -Zi -Og -O2 -W3 -WX -D "WIN32" -#LFL = - -# Flags for the fast debug version -CFL= -MTd -Zi -W3 -WX -F8192 -D "WIN32" -CFLN = -MTd -Zi -W3 -F8192 -D "WIN32" -CFLW = -MTd -Zi -W3 -WX -F8192 -D "WIN32" -LFL = /link/NODEFAULTLIB:LIBCMT - -# Flags for the profiler version -#CFL= -MT -Zi -Og -O2 -W3 -WX -D "WIN32" -#CFLN = -MT -Zi -Og -O2 -WX -D "WIN32" -#CFLW = -MT -Zi -Og -O2 -W3 -WX -D "WIN32" -#LFL= -link -PROFILE - -# Flags for the fast version without debug info (= the production version) -#CFL= -MT -Og -O2 -G6 -W3 -WX -D "WIN32" -#CFLN = -MT -Og -O2 -G6 -W3 -D "WIN32" -#CFLW = -MT -Og -O2 -G6 -W3 -WX -D "WIN32" -#LFL = diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index 224fd59a76b..02a38dd49ef 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -187,7 +187,7 @@ Creates a temporary file. */ FILE* os_file_create_tmpfile(void); /*========================*/ - /* out: temporary file handle (never NULL) */ + /* out: temporary file handle, or NULL on error */ /*************************************************************************** The os_file_opendir() function opens a directory stream corresponding to the directory named by the dirname argument. The directory stream is positioned diff --git a/innobase/include/rem0cmp.h b/innobase/include/rem0cmp.h index 1b1ee26b809..f6762078cbc 100644 --- a/innobase/include/rem0cmp.h +++ b/innobase/include/rem0cmp.h @@ -24,7 +24,8 @@ cmp_types_are_equal( /* out: TRUE if the types are considered equal in comparisons */ dtype_t* type1, /* in: type 1 */ - dtype_t* type2); /* in: type 2 */ + dtype_t* type2, /* in: type 2 */ + ibool check_charsets); /* in: whether to check charsets */ /***************************************************************** This function is used to compare two data fields for which we know the data type. */ diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 11347f430d4..99ea4f2de27 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -34,6 +34,18 @@ extern ibool srv_lower_case_table_names; extern mutex_t srv_monitor_file_mutex; /* Temporary file for innodb monitor output */ extern FILE* srv_monitor_file; +/* Mutex for locking srv_dict_tmpfile. +This mutex has a very high rank; threads reserving it should not +be holding any InnoDB latches. */ +extern mutex_t srv_dict_tmpfile_mutex; +/* Temporary file for output from the data dictionary */ +extern FILE* srv_dict_tmpfile; +/* Mutex for locking srv_misc_tmpfile. +This mutex has a very low rank; threads reserving it should not +acquire any further latches or sleep before releasing this one. */ +extern mutex_t srv_misc_tmpfile_mutex; +/* Temporary file for miscellanous diagnostic output */ +extern FILE* srv_misc_tmpfile; /* Server parameters which are read from the initfile */ diff --git a/innobase/lock/makefilewin b/innobase/lock/makefilewin deleted file mode 100644 index 149b0a2fed6..00000000000 --- a/innobase/lock/makefilewin +++ /dev/null @@ -1,7 +0,0 @@ -include ..\include\makefile.i - -lock.lib: lock0lock.obj - lib -out:..\libs\lock.lib lock0lock.obj - -lock0lock.obj: lock0lock.c - $(CCOM) $(CFL) -c lock0lock.c diff --git a/innobase/log/makefilewin b/innobase/log/makefilewin deleted file mode 100644 index a690af3bb35..00000000000 --- a/innobase/log/makefilewin +++ /dev/null @@ -1,10 +0,0 @@ -include ..\include\makefile.i - -log.lib: log0log.obj log0recv.obj - lib -out:..\libs\log.lib log0log.obj log0recv.obj - -log0log.obj: log0log.c - $(CCOM) $(CFL) -c log0log.c - -log0recv.obj: log0recv.c - $(CCOM) $(CFL) -c log0recv.c diff --git a/innobase/mach/makefilewin b/innobase/mach/makefilewin deleted file mode 100644 index 5306b0fe14c..00000000000 --- a/innobase/mach/makefilewin +++ /dev/null @@ -1,9 +0,0 @@ -include ..\include\makefile.i - -mach.lib: mach0data.obj - lib -out:..\libs\mach.lib mach0data.obj - -mach0data.obj: mach0data.c - $(CCOM) $(CFLN) -c mach0data.c - - diff --git a/innobase/makefilewin b/innobase/makefilewin deleted file mode 100644 index 1bd8d96e5e7..00000000000 --- a/innobase/makefilewin +++ /dev/null @@ -1,164 +0,0 @@ -doall: del_libs pb_all os.lib ut.lib mach.lib sync.lib mem.lib dyn.lib ha.lib com.lib thr.lib srv.lib fil.lib buf.lib log.lib mtr.lib log.lib fut.lib fsp.lib dict.lib data.lib rem.lib page.lib btr.lib ibuf.lib usr.lib que.lib trx.lib lock.lib read.lib row.lib pars.lib eval.lib ib_odbc.lib - -del_libs: - cd libs - del *.lib - cd .. - -pb_all: - pb_all - -os.lib: - cd os - remake - cd .. - -ut.lib: - cd ut - remake - cd .. - -mach.lib: - cd mach - remake - cd .. - -sync.lib: - cd sync - remake - cd .. - -mem.lib: - cd mem - remake - cd .. - -dyn.lib: - cd dyn - remake - cd .. - -ha.lib: - cd ha - remake - cd .. - -com.lib: - cd com - remake - cd .. - -thr.lib: - cd thr - remake - cd .. - -srv.lib: - cd srv - remake - cd .. - -fil.lib: - cd fil - remake - cd .. - -buf.lib: - cd buf - remake - cd .. - -log.lib: - cd log - remake - cd .. - -mtr.lib: - cd mtr - remake - cd .. - -fut.lib: - cd fut - remake - cd .. - -fsp.lib: - cd fsp - remake - cd .. - -dict.lib: - cd dict - remake - cd .. - -data.lib: - cd data - remake - cd .. - -rem.lib: - cd rem - remake - cd .. - -page.lib: - cd page - remake - cd .. - -btr.lib: - cd btr - remake - cd .. - -ibuf.lib: - cd ibuf - remake - cd .. - -usr.lib: - cd usr - remake - cd .. - -que.lib: - cd que - remake - cd .. - -trx.lib: - cd trx - remake - cd .. - -lock.lib: - cd lock - remake - cd .. - -read.lib: - cd read - remake - cd .. - -row.lib: - cd row - remake - cd .. - -pars.lib: - cd pars - remake - cd .. - -eval.lib: - cd eval - remake - cd .. - -ib_odbc.lib: - cd odbc - remake - cd .. diff --git a/innobase/mem/makefilewin b/innobase/mem/makefilewin deleted file mode 100644 index 8a30f8a6e71..00000000000 --- a/innobase/mem/makefilewin +++ /dev/null @@ -1,10 +0,0 @@ -include ..\include\makefile.i - -mem.lib: mem0mem.obj mem0pool.obj makefile - lib -out:..\libs\mem.lib mem0mem.obj mem0pool.obj - -mem0mem.obj: mem0mem.c mem0dbg.c - $(CCOM) $(CFL) -c mem0mem.c - -mem0pool.obj: mem0pool.c - $(CCOM) $(CFL) -c mem0pool.c diff --git a/innobase/mtr/makefilewin b/innobase/mtr/makefilewin deleted file mode 100644 index 9da0863bd28..00000000000 --- a/innobase/mtr/makefilewin +++ /dev/null @@ -1,14 +0,0 @@ -include ..\include\makefile.i - -mtr.lib: mtr0mtr.obj mtr0log.obj - lib -out:..\libs\mtr.lib mtr0mtr.obj mtr0log.obj - -mtr0mtr.obj: mtr0mtr.c - $(CCOM) $(CFL) -c mtr0mtr.c - -mtr0log.obj: mtr0log.c - $(CCOM) $(CFL) -c mtr0log.c - - - - diff --git a/innobase/my_cnf b/innobase/my_cnf deleted file mode 100644 index 94365237841..00000000000 --- a/innobase/my_cnf +++ /dev/null @@ -1,63 +0,0 @@ -# Example mysql config file. -# Copy this file to c:\my.cnf to set global options -# -# One can use all long options that the program supports. -# Run the program with --help to get a list of available options - -# This will be passed to all mysql clients -[client] -#password=my_password -port=3306 -#socket=MySQL - -# Here is entries for some specific programs -# The following values assume you have at least 32M ram - -# The MySQL server -[mysqld] -port=3306 -#socket=MySQL -skip-locking -default-character-set=latin1 -set-variable = key_buffer=2M -set-variable = max_allowed_packet=1M -set-variable = thread_stack=128K -set-variable = flush_time=1800 - -innobase_data_home_dir = e:\ibdata\ -innobase_data_file_path = ibdata1:25M;ibdata2:37M;ibdata3:100M;ibdata4:300M -set-variable = innobase_mirrored_log_groups=1 -innobase_log_group_home_dir = e:\iblogs\ -set-variable = innobase_log_files_in_group=3 -set-variable = innobase_log_file_size=5M -set-variable = innobase_log_buffer_size=8M -innobase_flush_log_at_trx_commit=1 -innobase_log_arch_dir = e:\iblogs\ -innobase_log_archive=0 -set-variable = innobase_buffer_pool_size=16M -set-variable = innobase_additional_mem_pool_size=2M -set-variable = innobase_file_io_threads=4 -set-variable = innobase_lock_wait_timeout=50 - - -# Uncomment the following row if you move the MySQL distribution to another -# location -#basedir = d:/mysql/ - -[mysqldump] -quick -set-variable = max_allowed_packet=16M - -[mysql] -no-auto-rehash - -[isamchk] -set-variable= key=16M - -[client_fltk] -help_file= c:\mysql\sql_client\MySQL.help -client_file= c:\mysql\MySQL.options -history_length=20 -database = test -queries_root= c:\mysql\queries -last_database_file= c:\mysql\lastdb diff --git a/innobase/os/makefilewin b/innobase/os/makefilewin deleted file mode 100644 index 8bc8d08611b..00000000000 --- a/innobase/os/makefilewin +++ /dev/null @@ -1,17 +0,0 @@ -include ..\include\makefile.i - -os.lib: os0sync.obj os0thread.obj os0proc.obj os0file.obj - lib -out:..\libs\os.lib os0sync.obj os0thread.obj os0proc.obj os0file.obj - -os0sync.obj: os0sync.c - $(CCOM) $(CFLW) -c os0sync.c - -os0thread.obj: os0thread.c - $(CCOM) $(CFLW) -c os0thread.c - -os0proc.obj: os0proc.c - $(CCOM) $(CFLW) -c os0proc.c - -os0file.obj: os0file.c - $(CCOM) $(CFLW) -c os0file.c - diff --git a/innobase/page/makefilewin b/innobase/page/makefilewin deleted file mode 100644 index 4a132cf828c..00000000000 --- a/innobase/page/makefilewin +++ /dev/null @@ -1,12 +0,0 @@ -include ..\include\makefile.i - -page.lib: page0page.obj page0cur.obj - lib -out:..\libs\page.lib page0page.obj page0cur.obj - -page0page.obj: page0page.c - $(CCOM) $(CFL) -c page0page.c - -page0cur.obj: page0cur.c - $(CCOM) $(CFL) -c page0cur.c - - diff --git a/innobase/pars/makefilewin b/innobase/pars/makefilewin deleted file mode 100644 index f183d89cbe2..00000000000 --- a/innobase/pars/makefilewin +++ /dev/null @@ -1,26 +0,0 @@ -include ..\include\makefile.i - -pars.lib: pars0grm.obj lexyy.obj pars0pars.obj pars0opt.obj pars0sym.obj rename_and_copy - lib -out:..\libs\pars.lib pars0grm.obj lexyy.obj pars0pars.obj pars0opt.obj pars0sym.obj - -pars0grm.obj: pars0grm.y - bs pars0grm.y - $(CCOM) $(CFLW) -c pars0grm.c - -rename_and_copy: - ren pars0grm.h pars0grm.h - copy pars0grm.h ..\include - -lexyy.obj: pars0lex.l - fl pars0lex.l - $(CCOM) $(CFLN) -c lexyy.c - -pars0pars.obj: pars0pars.c - $(CCOM) $(CFL) -c pars0pars.c - -pars0opt.obj: pars0opt.c - $(CCOM) $(CFL) -c pars0opt.c - -pars0sym.obj: pars0sym.c - $(CCOM) $(CFL) -c pars0sym.c - diff --git a/innobase/que/makefilewin b/innobase/que/makefilewin deleted file mode 100644 index 9661c716551..00000000000 --- a/innobase/que/makefilewin +++ /dev/null @@ -1,7 +0,0 @@ -include ..\include\makefile.i - -que.lib: que0que.obj - lib -out:..\libs\que.lib que0que.obj - -que0que.obj: que0que.c - $(CCOM) $(CFL) -c que0que.c diff --git a/innobase/read/makefilewin b/innobase/read/makefilewin deleted file mode 100644 index 39593993a67..00000000000 --- a/innobase/read/makefilewin +++ /dev/null @@ -1,7 +0,0 @@ -include ..\include\makefile.i - -read.lib: read0read.obj - lib -out:..\libs\read.lib read0read.obj - -read0read.obj: read0read.c - $(CCOM) $(CFL) -c read0read.c diff --git a/innobase/rem/makefilewin b/innobase/rem/makefilewin deleted file mode 100644 index 51ca4a92012..00000000000 --- a/innobase/rem/makefilewin +++ /dev/null @@ -1,12 +0,0 @@ -include ..\include\makefile.i - -rem.lib: rem0rec.obj rem0cmp.obj - lib -out:..\libs\rem.lib rem0rec.obj rem0cmp.obj - -rem0rec.obj: rem0rec.c - $(CCOM) $(CFL) -c rem0rec.c - -rem0cmp.obj: rem0cmp.c - $(CCOM) $(CFL) -c rem0cmp.c - - diff --git a/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c index 7c33476fb9e..6a463b7d4cf 100644 --- a/innobase/rem/rem0cmp.c +++ b/innobase/rem/rem0cmp.c @@ -99,7 +99,8 @@ cmp_types_are_equal( /* out: TRUE if the types are considered equal in comparisons */ dtype_t* type1, /* in: type 1 */ - dtype_t* type2) /* in: type 2 */ + dtype_t* type2, /* in: type 2 */ + ibool check_charsets) /* in: whether to check charsets */ { if (dtype_is_non_binary_string_type(type1->mtype, type1->prtype) && dtype_is_non_binary_string_type(type2->mtype, type2->prtype)) { @@ -107,12 +108,12 @@ cmp_types_are_equal( /* Both are non-binary string types: they can be compared if and only if the charset-collation is the same */ - if (dtype_get_charset_coll(type1->prtype) - == dtype_get_charset_coll(type2->prtype)) { + if (check_charsets) { + return(dtype_get_charset_coll(type1->prtype) + == dtype_get_charset_coll(type2->prtype)); + } else { return(TRUE); } - - return(FALSE); } if (dtype_is_binary_string_type(type1->mtype, type1->prtype) diff --git a/innobase/row/makefilewin b/innobase/row/makefilewin deleted file mode 100644 index c17240c6119..00000000000 --- a/innobase/row/makefilewin +++ /dev/null @@ -1,34 +0,0 @@ -include ..\include\makefile.i - -row.lib: row0mysql.obj row0upd.obj row0sel.obj row0umod.obj row0uins.obj row0ins.obj row0upd.obj row0undo.obj row0purge.obj row0vers.obj row0row.obj - lib -out:..\libs\row.lib row0mysql.obj row0sel.obj row0umod.obj row0uins.obj row0ins.obj row0upd.obj row0undo.obj row0purge.obj row0vers.obj row0row.obj - -row0mysql.obj: row0mysql.c - $(CCOM) $(CFL) -c row0mysql.c - -row0ins.obj: row0ins.c - $(CCOM) $(CFL) -c row0ins.c - -row0sel.obj: row0sel.c - $(CCOM) $(CFL) -c row0sel.c - -row0upd.obj: row0upd.c - $(CCOM) $(CFL) -c row0upd.c - -row0undo.obj: row0undo.c - $(CCOM) $(CFL) -c row0undo.c - -row0purge.obj: row0purge.c - $(CCOM) $(CFL) -c row0purge.c - -row0row.obj: row0row.c - $(CCOM) $(CFL) -c row0row.c - -row0vers.obj: row0vers.c - $(CCOM) $(CFL) -c row0vers.c - -row0umod.obj: row0umod.c - $(CCOM) $(CFL) -c row0umod.c - -row0uins.obj: row0uins.c - $(CCOM) $(CFL) -c row0uins.c diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 5e833372299..32aa0385596 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -588,20 +588,21 @@ row_ins_set_detailed( trx_t* trx, /* in: transaction */ dict_foreign_t* foreign) /* in: foreign key constraint */ { - - FILE* tf = os_file_create_tmpfile(); - - if (tf) { - ut_print_name(tf, trx, foreign->foreign_table_name); - dict_print_info_on_foreign_key_in_create_format(tf, trx, - foreign, FALSE); - - trx_set_detailed_error_from_file(trx, tf); - - fclose(tf); + mutex_enter(&srv_misc_tmpfile_mutex); + rewind(srv_misc_tmpfile); + + if (os_file_set_eof(srv_misc_tmpfile)) { + ut_print_name(srv_misc_tmpfile, trx, + foreign->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format( + srv_misc_tmpfile, + trx, foreign, FALSE); + trx_set_detailed_error_from_file(trx, srv_misc_tmpfile); } else { - trx_set_detailed_error(trx, "temp file creation failed"); + trx_set_detailed_error(trx, "temp file operation failed"); } + + mutex_exit(&srv_misc_tmpfile_mutex); } /************************************************************************* @@ -709,7 +710,7 @@ row_ins_foreign_report_add_err( } if (rec) { - rec_print(ef, rec, foreign->foreign_index); + rec_print(ef, rec, foreign->referenced_index); } putc('\n', ef); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 82f7daf2ed8..723e305b2ab 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -2132,7 +2132,7 @@ row_table_add_foreign_constraints( if (err == DB_SUCCESS) { /* Check that also referencing constraints are ok */ - err = dict_load_foreigns(name, trx->check_foreigns); + err = dict_load_foreigns(name, TRUE); } if (err != DB_SUCCESS) { @@ -3590,7 +3590,8 @@ row_rename_table_for_mysql( mem_heap_t* heap = NULL; const char** constraints_to_drop = NULL; ulint n_constraints_to_drop = 0; - ibool recovering_temp_table = FALSE; + ibool recovering_temp_table = FALSE; + ibool old_is_tmp, new_is_tmp; ulint len; ulint i; ibool success; @@ -3630,6 +3631,9 @@ row_rename_table_for_mysql( trx->op_info = "renaming table"; trx_start_if_not_started(trx); + old_is_tmp = row_is_mysql_tmp_table_name(old_name); + new_is_tmp = row_is_mysql_tmp_table_name(new_name); + if (row_mysql_is_recovered_tmp_table(new_name)) { recovering_temp_table = TRUE; @@ -3676,7 +3680,7 @@ row_rename_table_for_mysql( len = (sizeof str1) + (sizeof str2) + (sizeof str3) + (sizeof str5) - 4 + ut_strlenq(new_name, '\'') + ut_strlenq(old_name, '\''); - if (row_is_mysql_tmp_table_name(new_name)) { + if (new_is_tmp) { db_name_len = dict_get_db_name_len(old_name) + 1; /* MySQL is doing an ALTER TABLE command and it renames the @@ -3829,7 +3833,7 @@ row_rename_table_for_mysql( the table is stored in a single-table tablespace */ success = dict_table_rename_in_cache(table, new_name, - !row_is_mysql_tmp_table_name(new_name)); + !new_is_tmp); if (!success) { trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, FALSE, NULL); @@ -3846,19 +3850,16 @@ row_rename_table_for_mysql( goto funct_exit; } - err = dict_load_foreigns(new_name, trx->check_foreigns); - - if (row_is_mysql_tmp_table_name(old_name)) { + /* We only want to switch off some of the type checking in + an ALTER, not in a RENAME. */ + + err = dict_load_foreigns(new_name, + old_is_tmp ? trx->check_foreigns : TRUE); - /* MySQL is doing an ALTER TABLE command and it - renames the created temporary table to the name - of the original table. In the ALTER TABLE we maybe - created some FOREIGN KEY constraints for the temporary - table. But we want to load also the foreign key - constraint definitions for the original table name. */ + if (err != DB_SUCCESS) { + ut_print_timestamp(stderr); - if (err != DB_SUCCESS) { - ut_print_timestamp(stderr); + if (old_is_tmp) { fputs(" InnoDB: Error: in ALTER TABLE ", stderr); ut_print_name(stderr, trx, new_name); @@ -3866,36 +3867,23 @@ row_rename_table_for_mysql( "InnoDB: has or is referenced in foreign key constraints\n" "InnoDB: which are not compatible with the new table definition.\n", stderr); - - ut_a(dict_table_rename_in_cache(table, - old_name, FALSE)); - trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, - NULL); - trx->error_state = DB_SUCCESS; - } - } else { - if (err != DB_SUCCESS) { - - ut_print_timestamp(stderr); - + } else { fputs( " InnoDB: Error: in RENAME TABLE table ", stderr); ut_print_name(stderr, trx, new_name); fputs("\n" - "InnoDB: is referenced in foreign key constraints\n" - "InnoDB: which are not compatible with the new table definition.\n", + "InnoDB: is referenced in foreign key constraints\n" + "InnoDB: which are not compatible with the new table definition.\n", stderr); - - ut_a(dict_table_rename_in_cache(table, - old_name, FALSE)); - - trx->error_state = DB_SUCCESS; - trx_general_rollback_for_mysql(trx, FALSE, - NULL); - trx->error_state = DB_SUCCESS; } + + ut_a(dict_table_rename_in_cache(table, + old_name, FALSE)); + trx->error_state = DB_SUCCESS; + trx_general_rollback_for_mysql(trx, FALSE, + NULL); + trx->error_state = DB_SUCCESS; } } funct_exit: diff --git a/innobase/srv/makefilewin b/innobase/srv/makefilewin deleted file mode 100644 index 129c65ec220..00000000000 --- a/innobase/srv/makefilewin +++ /dev/null @@ -1,15 +0,0 @@ -include ..\include\makefile.i - -srv.lib: srv0srv.obj srv0que.obj srv0start.obj - lib -out:..\libs\srv.lib srv0srv.obj srv0que.obj srv0start.obj - -srv0srv.obj: srv0srv.c - $(CCOM) $(CFL) -c srv0srv.c - -srv0que.obj: srv0que.c - $(CCOM) $(CFL) -c srv0que.c - -srv0start.obj: srv0start.c - $(CCOM) $(CFL) -c srv0start.c - - diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index c585536baee..6e0b9b23266 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -397,6 +397,18 @@ mutex_t srv_innodb_monitor_mutex; mutex_t srv_monitor_file_mutex; /* Temporary file for innodb monitor output */ FILE* srv_monitor_file; +/* Mutex for locking srv_dict_tmpfile. +This mutex has a very high rank; threads reserving it should not +be holding any InnoDB latches. */ +mutex_t srv_dict_tmpfile_mutex; +/* Temporary file for output from the data dictionary */ +FILE* srv_dict_tmpfile; +/* Mutex for locking srv_misc_tmpfile. +This mutex has a very low rank; threads reserving it should not +acquire any further latches or sleep before releasing this one. */ +mutex_t srv_misc_tmpfile_mutex; +/* Temporary file for miscellanous diagnostic output */ +FILE* srv_misc_tmpfile; ulint srv_main_thread_process_no = 0; ulint srv_main_thread_id = 0; diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index e5151ebf631..4f99f340e1c 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1180,6 +1180,20 @@ NetWare. */ } } + mutex_create(&srv_dict_tmpfile_mutex); + mutex_set_level(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION); + srv_dict_tmpfile = os_file_create_tmpfile(); + if (!srv_dict_tmpfile) { + return(DB_ERROR); + } + + mutex_create(&srv_misc_tmpfile_mutex); + mutex_set_level(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH); + srv_misc_tmpfile = os_file_create_tmpfile(); + if (!srv_misc_tmpfile) { + return(DB_ERROR); + } + /* Restrict the maximum number of file i/o threads */ if (srv_n_file_io_threads > SRV_MAX_N_IO_THREADS) { @@ -1822,8 +1836,19 @@ innobase_shutdown_for_mysql(void) mem_free(srv_monitor_file_name); } } - + if (srv_dict_tmpfile) { + fclose(srv_dict_tmpfile); + srv_dict_tmpfile = 0; + } + + if (srv_misc_tmpfile) { + fclose(srv_misc_tmpfile); + srv_misc_tmpfile = 0; + } + mutex_free(&srv_monitor_file_mutex); + mutex_free(&srv_dict_tmpfile_mutex); + mutex_free(&srv_misc_tmpfile_mutex); /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside them */ diff --git a/innobase/sync/makefilewin b/innobase/sync/makefilewin deleted file mode 100644 index 73cff40405a..00000000000 --- a/innobase/sync/makefilewin +++ /dev/null @@ -1,14 +0,0 @@ -include ..\include\makefile.i - -sync.lib: sync0sync.obj sync0rw.obj sync0arr.obj - lib -out:..\libs\sync.lib sync0sync.obj sync0rw.obj sync0arr.obj - -sync0sync.obj: sync0sync.c - $(CCOM) $(CFLN) -c sync0sync.c - -sync0rw.obj: sync0rw.c - $(CCOM) $(CFL) -c sync0rw.c - -sync0arr.obj: sync0arr.c - $(CCOM) $(CFL) -c sync0arr.c - diff --git a/innobase/thr/makefilewin b/innobase/thr/makefilewin deleted file mode 100644 index 3f29ea1d3e3..00000000000 --- a/innobase/thr/makefilewin +++ /dev/null @@ -1,9 +0,0 @@ -include ..\include\makefile.i - -thr.lib: thr0loc.obj - lib -out:..\libs\thr.lib thr0loc.obj - -thr0loc.obj: thr0loc.c - $(CCOM) $(CFL) -c thr0loc.c - - diff --git a/innobase/trx/makefilewin b/innobase/trx/makefilewin deleted file mode 100644 index 35588779d66..00000000000 --- a/innobase/trx/makefilewin +++ /dev/null @@ -1,26 +0,0 @@ -include ..\include\makefile.i - -trx.lib: trx0sys.obj trx0trx.obj trx0rseg.obj trx0undo.obj trx0rec.obj trx0roll.obj trx0purge.obj - lib -out:..\libs\trx.lib trx0sys.obj trx0trx.obj trx0rseg.obj trx0undo.obj trx0rec.obj trx0roll.obj trx0purge.obj - -trx0trx.obj: trx0trx.c - $(CCOM) $(CFL) -c -I.. trx0trx.c - -trx0sys.obj: trx0sys.c - $(CCOM) $(CFL) -c -I.. trx0sys.c - -trx0rseg.obj: trx0rseg.c - $(CCOM) $(CFL) -c -I.. trx0rseg.c - -trx0undo.obj: trx0undo.c - $(CCOM) $(CFL) -c -I.. trx0undo.c - -trx0rec.obj: trx0rec.c - $(CCOM) $(CFL) -c -I.. trx0rec.c - -trx0roll.obj: trx0roll.c - $(CCOM) $(CFL) -c -I.. trx0roll.c - -trx0purge.obj: trx0purge.c - $(CCOM) $(CFL) -c -I.. trx0purge.c - diff --git a/innobase/usr/makefilewin b/innobase/usr/makefilewin deleted file mode 100644 index 66a77275e9b..00000000000 --- a/innobase/usr/makefilewin +++ /dev/null @@ -1,7 +0,0 @@ -include ..\include\makefile.i - -usr.lib: usr0sess.obj - lib -out:..\libs\usr.lib usr0sess.obj - -usr0sess.obj: usr0sess.c - $(CCOM) $(CFL) -c usr0sess.c diff --git a/innobase/ut/makefilewin b/innobase/ut/makefilewin deleted file mode 100644 index 2fda190773b..00000000000 --- a/innobase/ut/makefilewin +++ /dev/null @@ -1,21 +0,0 @@ -include ..\include\makefile.i - -ut.lib: ut0ut.obj ut0mem.obj ut0byte.obj ut0dbg.obj ut0rnd.obj - lib -out:..\libs\ut.lib ut0ut.obj ut0mem.obj ut0byte.obj ut0dbg.obj ut0rnd.obj - -ut0ut.obj: ut0ut.c - $(CCOM) $(CFL) -c ut0ut.c - -ut0mem.obj: ut0mem.c - $(CCOM) $(CFL) -c ut0mem.c - -ut0byte.obj: ut0byte.c - $(CCOM) $(CFL) -c ut0byte.c - -ut0dbg.obj: ut0dbg.c - $(CCOM) $(CFL) -c ut0dbg.c - -ut0rnd.obj: ut0rnd.c - $(CCOM) $(CFL) -c ut0rnd.c - - diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index 4bd9eddafb0..a3e16b521a9 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -22,14 +22,14 @@ target = libmysqlclient.la target_defs = -DUNDEF_THREADS_HACK -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ -LIBS = @CLIENT_LIBS@ +LIBS = @CLIENT_LIBS@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ - $(openssl_includes) @ZLIB_INCLUDES@ + $(openssl_includes) $(yassl_includes) @ZLIB_INCLUDES@ include $(srcdir)/Makefile.shared libmysqlclient_la_SOURCES = $(target_sources) -libmysqlclient_la_LIBADD = $(target_libadd) +libmysqlclient_la_LIBADD = $(target_libadd) $(yassl_libs_with_path) libmysqlclient_la_LDFLAGS = $(target_ldflags) EXTRA_DIST = Makefile.shared libmysql.def noinst_HEADERS = client_settings.h @@ -43,33 +43,33 @@ link_sources: vs=`echo $(vio_objects) | sed "s;\.lo;.c;g"`; \ scs=`echo $(sql_cmn_objects) | sed "s;\.lo;.c;g"`; \ for f in $$ss; do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \ + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \ done; \ for f in $$vs $(vioheaders); do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(srcdir)/../vio/$$f $(srcdir)/$$f; \ + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/vio/$$f $$f; \ done; \ for f in $$scs; do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(srcdir)/../sql-common/$$f $(srcdir)/$$f; \ + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/sql-common/$$f $$f; \ done; \ for f in $(mystringsextra); do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \ + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \ done; \ for f in $$ds; do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(srcdir)/../dbug/$$f $(srcdir)/$$f; \ + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/dbug/$$f $$f; \ done; \ for f in $$ms $(mysysheaders); do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(srcdir)/../mysys/$$f $(srcdir)/$$f; \ + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/mysys/$$f $$f; \ done; \ - rm -f $(srcdir)/net.c; \ - @LN_CP_F@ $(srcdir)/../sql/net_serv.cc $(srcdir)/net.c ; \ - rm -f $(srcdir)/password.c; \ - @LN_CP_F@ $(srcdir)/../sql/password.c $(srcdir)/password.c + rm -f net.c; \ + @LN_CP_F@ $(top_srcdir)/sql/net_serv.cc net.c ; \ + rm -f password.c; \ + @LN_CP_F@ $(top_srcdir)/sql/password.c password.c # This part requires GNUmake # diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am index 65255066d45..ee6dd4cfded 100644 --- a/libmysql_r/Makefile.am +++ b/libmysql_r/Makefile.am @@ -22,10 +22,10 @@ target = libmysqlclient_r.la target_defs = -DDONT_USE_RAID -DMYSQL_CLIENT @LIB_EXTRA_CCFLAGS@ -LIBS = @LIBS@ @ZLIB_LIBS@ @openssl_libs@ +LIBS = @LIBS@ @ZLIB_LIBS@ @openssl_libs@ @yassl_libs@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ - $(openssl_includes) @ZLIB_INCLUDES@ + $(openssl_includes) $(yassl_includes) @ZLIB_INCLUDES@ ## automake barfs if you don't use $(srcdir) or $(top_srcdir) in include include $(top_srcdir)/libmysql/Makefile.shared @@ -39,6 +39,6 @@ libmysqlclient_r_la_LDFLAGS = $(target_ldflags) link_sources: set -x; \ for f in `cd $(libmysql_dir) && echo *.[ch]`; do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(libmysql_dir)/$$f $(srcdir)/$$f; \ + rm -f $$f; \ + @LN_CP_F@ $(libmysql_dir)/$$f $$f; \ done diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 943b75f9973..f07bbacba02 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -29,7 +29,7 @@ INCLUDES= @bdb_includes@ \ -I$(top_builddir)/include -I$(top_srcdir)/include \ -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples \ -I$(top_srcdir)/regex \ - $(openssl_includes) @ZLIB_INCLUDES@ + $(openssl_includes) $(yassl_includes) @ZLIB_INCLUDES@ noinst_LIBRARIES = libmysqld_int.a pkglib_LIBRARIES = libmysqld.a @@ -81,6 +81,7 @@ INC_LIB= $(top_builddir)/regex/libregex.a \ $(top_builddir)/strings/libmystrings.a \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/vio/libvio.a + # # To make it easy for the end user to use the embedded library we @@ -121,19 +122,19 @@ endif link_sources: set -x; \ for f in $(sqlsources); do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \ + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \ done; \ for f in $(libmysqlsources); do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(srcdir)/../libmysql/$$f $(srcdir)/$$f; \ + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/libmysql/$$f $$f; \ done; \ for f in $(sqlexamplessources); do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(srcdir)/../sql/examples/$$f $(srcdir)/$$f; \ + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/sql/examples/$$f $$f; \ done; \ - rm -f $(srcdir)/client_settings.h; \ - @LN_CP_F@ $(srcdir)/../libmysql/client_settings.h $(srcdir)/client_settings.h; + rm -f client_settings.h; \ + @LN_CP_F@ $(top_srcdir)/libmysql/client_settings.h client_settings.h clean-local: diff --git a/libmysqld/examples/Makefile.am b/libmysqld/examples/Makefile.am index 476f297fe0d..414cf63b003 100644 --- a/libmysqld/examples/Makefile.am +++ b/libmysqld/examples/Makefile.am @@ -21,20 +21,21 @@ tests_sources = $(mysql_client_test_embedded_SOURCES) CLEANFILES = $(client_sources) $(tests_sources) link_sources: + set -x; \ for f in $(client_sources); do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(srcdir)/../../client/$$f $(srcdir)/$$f; \ - done; + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/client/$$f $$f; \ + done; \ for f in $(tests_sources); do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(srcdir)/../../tests/$$f $(srcdir)/$$f; \ - done; + rm -f $$f; \ + @LN_CP_F@ $(top_srcdir)/tests/$$f $$f; \ + done DEFS = -DEMBEDDED_LIBRARY INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir) \ -I$(top_srcdir) -I$(top_srcdir)/client -I$(top_srcdir)/regex \ - $(openssl_includes) -LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@ + $(openssl_includes) $(yassl_includes) +LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@ $(yassl_libs) LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysqld.a @innodb_system_libs@ @LIBDL@ $(CXXLDFLAGS) mysqltest_embedded_LINK = $(CXXLINK) diff --git a/man/Makefile.am b/man/Makefile.am index 8d18165191a..9702c4b2ace 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -17,30 +17,8 @@ ## Process this file with automake to create Makefile.in -man_MANS = mysql.1 mysql_zap.1 mysqlaccess.1 \ - mysqladmin.1 mysqld.1 mysqld_multi.1 mysqldump.1 mysqlshow.1 \ - perror.1 replace.1 mysqld_safe.1 mysql_fix_privilege_tables.1 - -EXTRA_DIST = mysql.1.in mysql_zap.1.in \ - mysqlaccess.1.in mysqladmin.1.in mysqld.1.in mysqld_multi.1.in \ - mysqldump.1.in mysqlshow.1.in perror.1.in replace.1.in mysqlman.1.in \ - mysqld_safe.1.in mysql_fix_privilege_tables.1.in - -CLEANFILES = $(man_MANS) - -SUFFIXES = .in - -.in: - @RM@ -f $@ $@-t - @SED@ \ - -e 's!@''MYSQL_BASE_VERSION''@!@MYSQL_BASE_VERSION@!' \ - -e 's!@''sysconfdir''@!@sysconfdir@!' \ - -e 's!@''bindir''@!$(bindir)!g' \ - -e 's!@''libexecdir''@!$(libexecdir)!g' \ - -e 's!@''localstatedir''@!$(localstatedir)!g' \ - -e 's!@''MYSQL_NO_DASH_VERSION''@!@MYSQL_NO_DASH_VERSION@!' \ - $< > $@-t - @MV@ $@-t $@ +man1_MANS = @man1_files@ +EXTRA_DIST = $(man1_MANS) # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/man/mysql.1.in b/man/mysql.1.in deleted file mode 100644 index c4463aa658b..00000000000 --- a/man/mysql.1.in +++ /dev/null @@ -1,160 +0,0 @@ -.TH mysql 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -mysql \- text-based client for mysqld, a SQL-based relational database daemon -.SH USAGE -mysql [OPTIONS] [Database] -.SH SYNOPSIS -.B mysql -.RB [ \-B | \-\-batch ] -.RB [ \-# | \-\-debug= -.IR logfile ] -.RB [ \-T | \-\-debug-info ] -.RB [ \-e | \-\-exec= -.IR command ] -.RB [ \-f | \-\-force ] -.RB [ \-? | \-\-help ] -.RB [ \-h | \-\-host= -.IR hostname ] -.RB [ \-n | \-\-unbuffered ] -.RB [ \-p[pwd] ] -.RI [ \-\-password=[pwd] ] -.RB [ \-P | \-\-port= -.IR pnum ] -.RB [ \-q | \-\-quick ] -.RB [ \-r | \-\-raw ] -.RB [ \-s | \-\-silent ] -.RB [ \-S | \-\-socket= -.IR snum ] -.RB [ \-u | \-\-user= -.IR uname ] -.RB [ \-v | \-\-verbose ] -.RB [ \-V | \-\-version ] -.RB [ \-w | \-\-wait ] -.SH DESCRIPTION -The -.IR mysql -program provides a curses-based interface to the SQL-based database -server daemon, -.IR mysqld (1). -Full fuller documentation, refer to the HTML documents installed with -the package. -.SH OPTIONS -.TP -.BR \-B | \-\-batch -Print results with a tab as separator, -each row on a new line. -.TP -\fB\-#\fP|\fB\-\-debug=\fP\fIlogfile\fP -Employ the specified debug log. -.TP -.BR \-T | \-\-debug-info -Print debug information upon exiting. -.TP -\fB\-e | \-\-exec=\fP\fPcommand\fP -Execute the specified command and quit -.BR ( \-\-batch -is implicit). -.TP -.BR \-f | \-\-force -Continue even if the face of a SQL error. -.TP -.BR \-? | \-\-help -Display a help message and exit. -.TP -\fB\-h\fP|\fP\-\-host=\fP\fIhostname\fP -Connect to the specified host. -.TP -.BR \-n | \-\-unbuffered -Flush the buffer after each query. -.TP -\fB\-p\fP|\fB\-\-password\fP[\fB=\fP\fIpwd\fP] -Employ the specified password when connecting to the database server. -If a password is not supplied, it will be requested interactively. -.TP -\fB\-P\fR|\fB\-\-port=\fP\fIpnum\fP -Employ the specified port number for connecting to the database server. -.TP -.BR \-q | \-\-quick -Do not cache the result; print it row by row. -This may slow down the server if the output is suspended. -.TP -.BR \-r | \-\-raw -Write fields without conversion. -(used with -.BR \-\-batch ). -.TP -.BR \-s | \-\-silent -Silent mode: reduce the amount of output. -.TP -\fB\-S\fP|\fB\-\-socket=\fP\fIsnum\fP -Employ the specified socket file for connecting to the database server. -.TP -\fB\-u\fP|\fB\-\-user=\fP\fIuname\fP -Employ the specified user name for logging in to the server. -.TP -.BR \-v | \-\-verbose -Verbose mode: write more -Specifying this option -.I twice -produces a tabular output format. -.TP -.BR \-V | \-\-version -Print the -.I mysql -version number and exit. -.TP -.BR \-w | \-\-wait -Wait and retry if the database server connection is down. -.SH FILES -.TP 2.2i -.I /etc/my.cnf -MySQL configuration file -.TP -.I @bindir@/mysql -Client executable -.TP -.I @libexecdir@/mysqld -Server executable -.TP -.I @bindir@/mysqld_safe -executable shell script for starting mysqld safely -.TP -.I @localstatedir@ -location of database files -.SH EXAMPLE -You can also read a backup dump file back into MySQL with: -.TP -.BR mysql -\fP\fIdatabase\fP -.BR < -backup-file.sql -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysqlaccess(1), -mysqladmin(1), -mysqld(1), -mysqld_multi(1), -mysqld_safe(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -mysql_zap(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -Ver 6.3, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com/) -This software comes with no warranty. -Manual page by R. P. C. Rodgers, -Lister Hill National Center for Biomedical Communication, -U.S. National Library of Medicine -(rodgers@nlm.nih.gov). -.\" end of man page diff --git a/man/mysql_fix_privilege_tables.1.in b/man/mysql_fix_privilege_tables.1.in deleted file mode 100644 index fe1016e8d98..00000000000 --- a/man/mysql_fix_privilege_tables.1.in +++ /dev/null @@ -1,40 +0,0 @@ -.TH mysql 1 "17 March 2003" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -mysql_fix_privilege_tables \- Fixes MySQL privilege tables. -.SH SYNOPSIS -mysql_fix_privilege_tables [mysql_root_password] -.SH DESCRIPTION -This scripts updates the mysql.user, mysql.db, mysql.host and the -mysql.func tables to MySQL 3.22.14 and above. - -This is needed if you want to use the new GRANT functions, -CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23 - -If you get 'Access denied' errors, run the script again -and give the MySQL root user password as an argument. - -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysql(1), -mysqlaccess(1), -mysqladmin(1), -mysqld(1), -mysqld_multi(1), -mysqld_safe(1), -mysqldump(1), -mysqlshow(1), -mysql_zap(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -This manpage was written by Christian Hammers <ch@debian.org>. - -MySQL is available at http://www.mysql.com/. -.\" end of man page diff --git a/man/mysql_zap.1.in b/man/mysql_zap.1.in deleted file mode 100644 index fb030427dc2..00000000000 --- a/man/mysql_zap.1.in +++ /dev/null @@ -1,52 +0,0 @@ -.TH zap 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -zap - a perl script used to kill processes -.SH USAGE -/usr/bin/mysql_zap [-signal] [-?Ift] pattern -.SH SYNOPSIS -.B zap -.RB [ \-I | \-? ] -.RB [ \-f ] -.RB [ \-t ] -.SH DESCRIPTION -.TP -.BR zap -supports by executing -.TP -.BR \-I | \-? -info -.TP -.BR \-f -force -.TP -.BR \-t -test -.SH NOTE -If -.BR -f -isn't given, ask user for confirmation for each process to kill. If signal isn't given, try first with signal 15 and after that with signal 9. If -.BR -t -is given the processes is only shown on stdout. -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysql(1), -mysqlaccess(1), -mysqladmin(1), -mysqld(1), -mysqld_multi(1), -mysqld_safe(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ Michael (Monty) Widenius (monty@mysql.com), MySQL AB (http://www.mysql.com/). This software comes with no warranty. Manual page by L. (Kill-9) Pedersen (kill-9@kill-9.dk), Mercurmedia Data Model Architect / system developer (http://www.mercurmedia.com) -.\" end of man page diff --git a/man/mysqlaccess.1.in b/man/mysqlaccess.1.in deleted file mode 100644 index e0b3d314a10..00000000000 --- a/man/mysqlaccess.1.in +++ /dev/null @@ -1,125 +0,0 @@ -.TH mysqlaccess 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -.BR mysqlaccess \- Create new users to mysql. -.SH USAGE -mysqlaccess [host [user [db]]] OPTIONS -.SH SYNOPSIS -.B mysqlaccess -.RB [ \-? | \-\-help ] -.RB [ \-v | \-\-version ] -.RB [ \-p | \-\-password=# ] -.RB [ \-h | \-\-host=# ] -.RB [ \-d | \-\-db=# ] -.RB [ \-U | \-\-superuser=# ] -.RB [ \-P | \-\-spassword=# ] -.RB [ \-H | \-\-rhost=# ] -.RB [ \-\-old_server ] -.RB [ \-b | \-\-brief ] -.RB [ \-t | \-\-table ] -.RB [ \-\-relnotes] -.RB [ \-\-plan ] -.RB [ \-\-howto ] -.RB [ \-\-debug=N ] -.RB [ \-\-copy ] -.RB [ \-\-preview ] -.RB [ \-\-commit ] -.RB [ \-\-rollback ] -.SH DESCRIPTION -.TP -.BR \-? | \-\-help -display this helpscreen and exit -.TP -.BR \-v | \-\-version -print information on the program `mysqlaccess' -.TP -.BR \-u | \-\-user=# -username for logging in to the db -.TP -.BR \-p | \-\-password=# -validate password for user -.TP -.BR \-h | \-\-host=# -name or IP\-number of the host -.TP -.BR \-d | \-\-db=# -name of the database -.TP -.BR \-U | \-\-superuser=# -connect as superuser -.TP -.BR \-P | \-\-spassword=# -password for superuser -.TP -.BR \-H | \-\-rhost=# -remote MySQL\-server to connect to -.TP -.BR \-\-old_server -connect to old MySQL\-server (before v3.21) which -does not yet know how to handle full where clauses. -.TP -.BR \-b | \-\-brief -single\-line tabular report -.TP -.BR \-t | \-\-table -report in table\-format -.TP -.BR \-\-relnotes -print release\-notes -.TP -.BR \-\-plan -print suggestions/ideas for future releases -.TP -.BR \-\-howto -some examples of how to run `mysqlaccess' -.TP -.BR \-\-debug=N -enter debuglevel N (0..3) -.TP -.BR \-\-copy -reload temporary grant\-tables from original ones -.TP -.BR \-\-preview -show differences in privileges after making -changes in (temporary) grant\-tables -.TP -.BR \-\-commit -copy grant\-rules from temporary tables to grant\-tables -(!don't forget to do an mysqladmin reload) -.TP -.BR \-\-rollback -undo the last changes to the grant\-tables. -.SH NOTE -At least the user and the db must be given (even with wildcards) -If no host is given, `localhost' is assumed -Wildcards (*,?,%,_) are allowed for host, user and db, but be sure -to escape them from your shell!! (i.e., type \\* or '*') -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysql(1), -mysqladmin(1), -mysqld(1), -mysqld_multi(1), -mysqld_safe(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -mysql_zap(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com/). -This software comes with no warranty. -Manual page by L. (Kill-9) Pedersen -(kill-9@kill\-9.dk), Mercurmedia Data Model Architect / -system developer (http://www.mercurmedia.com) - -.\" end of man page diff --git a/man/mysqladmin.1.in b/man/mysqladmin.1.in deleted file mode 100644 index e62cb32dc78..00000000000 --- a/man/mysqladmin.1.in +++ /dev/null @@ -1,209 +0,0 @@ -.TH mysqladmin 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME - mysqladmin [OPTIONS] command command.... \- A utility for performing administrative operations -.SH OPTION SYNOPSIS -.B mysqladmin -.RB [ \-# | \-\-debug= -.IR logfile ] -.RB [ \-f | \-\-force ] -.RB [ \-? | \-\-help ] -.BR [ --character-sets-dir=\fP\fIdirectory\fP ] -.RB [ \-C | \-\-compress ] -.RB [ \-h | \-\-host=[#] ] -.RB [ \-p[pwd] ] -.RI [ \-\-password=[pwd] ] -.RB [ \-P | \-\-port= -.IR pnum ] -.RB [ \-i | \-\-sleep= -.IR sec ] -.RB [ \-E | \-\-vertical ] -.RB [ \-s | \-\-silent ] -.RB [ \-S | \-\-socket= -.IR # ] -.RB [ \-r | \-\-relative ] -.RB [ \-t | \-\-timeout= -.IR # ] -.RB [ \-u | \-\-user= -.IR uname ] -.RB [ \-v | \-\-verbose ] -.RB [ \-V | \-\-version ] -.RB [ \-w | \-\-wait[=retries] ] -.SH OPTION DESCRIPTION -You can get a list of the options your version of -.IR mysqladmin -supports by executing -.BR "mysqladmin \-\-help" -.SH OPTIONS -.TP -.BR \-# | \-\-debug=\fP\fIlogfile\fP -Output debug log. Often this is 'd:t:o,filename` -.TP -.BR \-f | \-\-force -Don't ask for confirmation on drop database; with -multiple commands, continue even if an error occurs -.TP -.BR \-? | \-\-help - Display help and exit -.TP -.BR --character-sets-dir=\fP\fIdirectory\fP -Set the character set directory -.TP -.BR \-C | \-\-compress -Use compression in server/client protocol -.TP -\fB\-h\fP|\fP\-\-host=\fP\fIhostname\fP -Connect to host -.TP -\fB\-p\fP|\fB\-\-password\fP[\fB=\fP\fIpwd\fP] -Password to use when connecting to server -If password is not given it's asked from the tty -.TP -\fB\-P\fR|\fB\-\-port=\fP\fIpnum\fP -Port number to use for connection -.TP -\fB\-i\fR|\fB\-\-sleep=\fP\fIsec\fP -Execute commands again and again with a sleep between -.TP -.BR \-r | \-\-relative -Show difference between current and previous values -when used with -.BR -i -. Currently works only with -extended-status -.TP -.BR \-E | \-\-vertical -Print output vertically. Is similar to -.BR --relative, -but prints output vertically. -.TP -.BR \-s | \-\-silent -Silently exit if one can't connect to server -.TP -\fB\-S\fR|\fB\-\-socket=\fP\fIfile\fP -Socket file to use for connection -.TP -\fB\-t\fR|\fB\-\-timeout=\fP\fIsec\fP -Timeout for connection to the mysqld server -.TP -\fB\-u\fP|\fB\-\-user=\fP\fIuname\fP -User for login if not current user -.TP -.BR \-v | \-\-verbose -Write more information -.TP -.BR \-V | \-\-version -Output version information and exit -.TP -.BR \-w | \-\-wait - Wait and retry if connection is down -.SH COMMAND SYNOPSIS -.B MySQLADMIN -.RB [ "create \fP\fIdatabasename\fP "] -.RB [ "drop \fP\fIdatabasename\fP" ] -.RB [ extended-status ] -.RB [ flush-hosts ] -.RB [ flush-logs ] -.RB [ flush-tables ] -.RB [ flush-privileges ] -.RB [ " kill id,id,... " ] -.RB [ "password \fP\fInew-password\fP "] -.RB [ ping ] -.RB [ processlist ] -.RB [ reload ] -.RB [ refresh ] -.RB [ shutdown ] -.RB [ slave-start ] -.RB [ slave-stop ] -.RB [ status ] -.RB [ variables ] -.RB [ version ] - -.SH COMMANDS -Where command is a one or more of: (Commands may be shortened) -.TP -.BR "create databasename" -Create a new database -.TP -.BR "drop databasename" -Delete a database and all its tables -.TP -.BR extended-status -Gives an extended status message from the server -.TP -.BR flush-hosts -Flush all cached hosts -.TP -.BR flush-logs -Flush all logs -.TP -.BR flush-status -Clear status variables -.TP -.BR flush-tables -Flush all tables -.TP -.BR flush-threads -Flush the thread cache -.TP -.BR flush-privileges -Reload grant tables (same as reload) -.TP -.BR "kill id,id,..." -Kill mysql threads -.TP -.BR "password \fP\fInew-password\fP" -Change old password to new-password -.TP -.BR ping -Check if mysqld is alive -.TP -.BR processlist -Show list of active threads in server -.TP -.BR reload -Reload grant tables -.TP -.BR refresh -Flush all tables and close and open logfiles -.TP -.BR shutdown -Take server down -.TP -.BR status -Gives a short status message from the server -.TP -.BR variables -Prints variables available -.TP -.BR version -Get version info from server -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysql(1), -mysqlaccess(1), -mysqld(1), -mysqld_multi(1), -mysqld_safe(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -mysql_zap(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com/). -This software comes with no warranty. -Manual page by L. (Kill-9) Pedersen -(kill-9@kill-9.dk), Mercurmedia Data Model Architect / -system developer (http://www.mercurmedia.com) -.\" end of man page - diff --git a/man/mysqld.1.in b/man/mysqld.1.in deleted file mode 100644 index 73f07337f25..00000000000 --- a/man/mysqld.1.in +++ /dev/null @@ -1,234 +0,0 @@ -.TH mysqld 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -mysqld \- The MySQL server demon -.SH USAGE -mysqld [OPTIONS] -.SH SYNOPSIS -.B mysqld -.RB [ \-\-ansi ] -.RB [ \-b | \-\-basedir=\fP\fIpath\fP ] -.RB [ \-\-big-tables ] -.RB [ \-\-bind\-address=IP ] -.RB [ \-\-character\-sets\-dir=\fP\fIpath\fP ] -.RB [ \-\-chroot=\fP\fIpath\fP ] -.RB [ \-h | \-\-datadir=\fP\fIpath\fP ] -.RB [ \-\-default\-character\-set=\fP\fIcharset\fP ] -.RB [ \-\-default\-table\-type=\fP\fItype \fP] -.RB [ \-\-delay\-key\-write\-for\-all\-tables ] -.RB [ \-\-enable\-locking ] -.RB [ \-T | \-\-exit\-info] -.RB [ \-\-flush ] -.RB [ \-? | \-\-help ] -.RB [ \-\-init\-file=file ] -.RB [ \-L | \-\-language=... ] -.RB [ \-l | \-\-log[=file] ] -.RB [ \-\-log\-isam[=file] ] -.RB [ \-\-log\-slow\-queries\fP\fI[=file]\fP ] -.RB [ \-\-log\-update\fP\fI[=file]\fP ] -.RB [ \-\-log\-long\-format ] -.RB [ \-\-low\-priority\-updates ] -.RB [ \-\-memlock ] -.RB [ " \-\-myisam\-recover [=option[,option...]]] where option is one of DEFAULT, BACKUP, FORCE or QUICK." ] -.RB [ \-\-pid\-file=\fP\fIpath\fP ] -.RB [ \-P | \-\-port=... ] -.RB [ \-o | \-\-old\-protocol ] -.RB [ \-\-one\-thread ] -.RB [ \-O | \-\-set\-variable var=\fP\fIoption\fP ] -.RB [ \-Sg | \-\-skip\-grant\-tables ] -.RB [ \-\-safe\-mode ] -.RB [ \-\-secure ] -.RB [ \-\-skip\-concurrent\-insert ] -.RB [ \-\-skip\-delay\-key\-write ] -.RB [ \-\-skip\-locking ] -.RB [ \-\-skip\-name\-resolve ] -.RB [ \-\-skip\-networking ] -.RB [ \-\-skip\-new ] -.RB [ \-\-skip\-host\-cache ] -.RB [ \-\-skip\-show\-database ] -.RB [ \-\-skip\-thread\-priority ] -.RB [ \-\-socket=path ] -.RB [ \-t | \-\-tmpdir=\fP\fIpath \fP] -.RB [ \-u | \-\-user=\fP\fIuser_name\fP ] -.RB [ \-V | \-\-version ] -.SH DESCRIPTION -.TP -.BR --ansi -Use ANSI SQL syntax instead of MySQL syntax. See section 5.2 Running MySQL in ANSI Mode. -.TP -.BR -b | --basedir=\fP\fIpath \fP -Path to installation directory. All paths are usually resolved relative to this. -.TP -.BR --big-tables -Allow big result sets by saving all temporary sets on file. It solves most 'table full' errors, but also slows down the queries where in\-memory tables would suffice. Since Version 3.23.2, MySQL is able to solve it automaticaly by using memory for small temporary tables and switching to disk tables where necessary. -.TP -.BR \-\-bind\-address=\fP\fIIP \fP -IP address to bind to. -.TP -.BR \-\-character\-sets\-dir=\fP\fIpath \fP -Directory where character sets are. See section 10.1.1 The Character Set Used for Data and Sorting. -.TP -.BR \-\-chroot=\fP\fIpath \fP -Chroot mysqld daemon during startup. Recommended security measure. It will somewhat limit LOAD DATA INFILE and SELECT ... INTO OUTFILE though. -.TP -.BR \-h | \-\-datadir=\fP\fIpath \fP -Path to the database root. -.TP -.BR \-\-default\-character\-set=\fP\fIcharset \fP -Set the default character set. See section 10.1.1 The Character Set Used for Data and Sorting. -.TP -.BR \-\-default\-table\-type=\fP\fItype \fP -Set the default table type for tables. See section 8 MySQL Table Types. -.TP -.BR \-\-delay\-key\-write\-for\-all\-tables -Don't flush key buffers between writes for any MyISAM table. See Mysql Manual section 12.2.3 Tuning Server Parameters. -.TP -.BR \-\-enable\-locking -Enable system locking. -.TP -.BR \-T | \-\-exit\-info -Print some debug info at exit. -.TP -.BR \-\-flush -Flush all changes to disk after each SQL command. Normally MySQL only does a write of all changes to disk after each SQL command and lets the operating system handle the syncing to disk. See section 20.2 What to Do if MySQL Keeps Crashing. -.TP -.BR \-? | \-\-help -Display short help and exit. -.TP -.BR \-\-init\-file=\fP\fIfile \fP -Read SQL commands from this file at startup. -.TP -.BR \-L | \-\-language=... -Client error messages in given language. May be given as a full path. See Mysql Manual section 10.1 What Languages Are Supported by MySQL?. -.TP -.BR \-l | \-\-log\fP\fI[=file] \fP -Log connections and queries to file. -.TP -.BR \-\-log\-isam\fP\fI[=file] \fP -Log all ISAM/MyISAM changes to file (only used when debugging ISAM/MyISAM). -.TP -.BR \-\-log\-slow\-queries\fP\fI[=file] \fP -Log all queries that have taken more than long_query_time seconds to execute to file. See Mysql Manual section 21.5 The Slow Query Log. -.TP -.BR \-\-log\-update\fP\fI[=file] \fP -Log updates to file.# where # is a unique number if not given. See Mysql Manual section 21.3 The Update Log. -.TP -.BR \-\-log\-long\-format -Log some extra information to update log. If you are using -.BR \-\-log\-slow\-queries -then queries that are not using indexes are logged to the slow query log. -.TP -.BR \-\-low\-priority\-updates -Table\-modifying operations (INSERT/DELETE/UPDATE) will have lower priority than selects. It can also be done via {INSERT | REPLACE | UPDATE | DELETE} LOW_PRIORITY ... to lower the priority of only one query, or by SET OPTION SQL_LOW_PRIORITY_UPDATES=1 to change the priority in one thread. See Mysql Manual section 12.2.9 Table Locking Issues. -.TP -.BR \-\-memlock -Lock the mysqld process in memory. This works only if your system supports the mlockall() system call. This may help if you have a problem where the operating system is causing mysqld to swap on disk. -.TP -.BR " \-\-myisam\-recover [=option[,option...]]] where option is one of DEFAULT, BACKUP, FORCE or QUICK. " -If this option is used, mysqld will on open check if the table is marked as crashed or if if the table wasn't closed properly (The last option only works if you are running with \-\-skip\-locking). If this is the case mysqld will run check on the table. If the table was corrupted, mysqld will attempt to repair it. The following options affects how the repair works. -.BR DEFAULT -The same as not giving any option to \-\-myisam\-recover. -.BR BACKUP -If the data table was changed during recover, save a backup of the `table_name.MYD' data file as `table_name\-datetime.BAK'. -.BR FORCE -Run recover even if we will loose more than one row from the .MYD file. -.BR QUICK -Don't check the rows in the table if there isn't any delete blocks. -Before a table is automaticly repaired, mysqld will add a note about this in the error log. If you want to be able to recover from most things without user intervention, you should use the options BACKUP,FORCE. This will force a repair of a table even if some rows would be deleted, but it will keep the old data file as a backup so that you can later examine what happened. -.TP -.BR \-\-pid\-file=\fP\fIpath \fP -Path to pid file used by mysqld_safe. -.TP -.BR \-P | \-\-port=... -Port number to listen for TCP/IP connections. -.TP -.BR \-o | \-\-old\-protocol -Use the 3.20 protocol for compatibility with some very old clients. See Mysql Manual section 4.17.3 Upgrading from Version 3.20 to Version 3.21. -.TP -.BR \-\-one\-thread -Only use one thread (for debugging under Linux). See Mysql Manual section H.1 Debugging a MySQL server. -.TP -.BR \-O | " \-\-set\-variable var=\fP\fIoption\fP " -Give a variable a value. \-\-help lists variables. You can find a full description for all variables in the SHOW VARIABLES section in this manual. See Mysql Manual section 7.28.4 SHOW VARIABLES. The tuning server parameters section includes information of how to optimize these. See Mysql Manual section 12.2.3 Tuning Server Parameters. -.TP -.BR \-Sg | \-\-skip\-grant\-tables -This option causes the server not to use the privilege system at all. This gives everyone full access to all databases! (You can tell a running server to start using the grant tables again by executing mysqladmin flush\-privileges or mysqladmin reload.) -.TP -.BR \-\-safe\-mode -Skip some optimize stages. Implies -.BR \-\-skip\-delay\-key\-write. -.TP -.BR \-\-secure -IP numbers returned by the gethostbyname() system call are checked to make sure they resolve back to the original hostname. This makes it harder for someone on the outside to get access by pretending to be another host. This option also adds some sanity checks of hostnames. The option is turned off by default in MySQL Version 3.21 because sometimes it takes a long time to perform backward resolutions. MySQL Version 3.22 caches hostnames (unless \-\-skip\-host\-cache is used) and has this option enabled by default. -.TP -.BR \-\-skip\-concurrent\-insert -Turn off the ability to select and insert at the same time on MyISAM tables. (This is only to be used if you think you have found a bug in this feature). -.TP -.BR \-\-skip\-delay\-key\-write -Ignore the delay_key_write option for all tables. See Mysql Manual section 12.2.3 Tuning Server Parameters. -.TP -.BR \-\-skip\-locking -Don't use system locking. To use isamchk or myisamchk you must shut down the server. See Mysql Manual section 1.6 How Stable Is MySQL?. Note that in MySQL Version 3.23 you can use REPAIR and CHECK to repair/check MyISAM tables. -.TP -.BR \-\-skip\-name\-resolve -Hostnames are not resolved. All Host column values in the grant tables must be IP numbers or localhost. -.TP -.BR \-\-skip\-networking -Don't listen for TCP/IP connections at all. All interaction with mysqld must be made via Unix sockets. This option is highly recommended for systems where only local requests are allowed. However, this option is unsuitable for systems that use MIT\-pthreads, because the MIT\-pthreads package doesn't support Unix sockets. -.TP -.BR \-\-skip\-new -Don't use new, possible wrong routines. Implies -.BR \-\-skip\-delay\-key\-write -. This will also set default table type to ISAM. See Mysql Manual section 8.3 ISAM Tables. -.TP -.BR \-\-skip\-host\-cache -Never use host name cache for faster name\-ip resolution, but query DNS server on every connect instead. -.TP -.BR \-\-skip\-show\-database -Don't allow 'SHOW DATABASE' commands, unless the user has process privilege. -.TP -.BR \-\-skip\-thread\-priority -Disable using thread priorities for faster response time. -.TP -.BR \-\-socket=\fP\fIpath \fP -Socket file to use for local connections instead of default /tmp/mysql.sock. -.TP -.BR \-t | \-\-tmpdir=\fP\fIpath\fP -Path for temporary files. It may be useful if your default /tmp directory resides on a partition too small to hold temporary tables. -.TP -.BR \-u | \-\-user=\fP\fIuser_name \fP -Run mysqld daemon as user user_name. This option is mandatory when starting mysqld as root. -.TP -.BR \-V | \-\-version -Output version information and exit. - -.SH NOTE -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysql(1), -mysqlaccess(1), -mysqladmin(1), -mysqld_multi(1), -mysqld_safe(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -mysql_zap(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com/). -This software comes with no warranty. -Manual page by L. (Kill-9) Pedersen -(kill-9@kill\-9.dk), Mercurmedia Data Model Architect / -system developer (http://www.mercurmedia.com) - -.\" end of man page diff --git a/man/mysqld_multi.1.in b/man/mysqld_multi.1.in deleted file mode 100644 index 58e5c71d01d..00000000000 --- a/man/mysqld_multi.1.in +++ /dev/null @@ -1,94 +0,0 @@ -.TH mysqld_multi 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -mysqld_multi - is meant for managing several mysqld processes running in different UNIX sockets and TCP/IP ports. -.SH USAGE -mysqld_multi [OPTIONS] {start|stop|report} [GNR,GNR,GNR...] -.SH SYNOPSIS -.B mysqld_multi -.RB [ --config-file=... ] -.RB [ --example ] -.RB [ --help ] -.RB [ --log=... ] -.RB [ --mysqladmin=... ] -.RB [ --mysqld=... ] -.RB [ --no-log ] -.RB [ --password=... ] -.RB [ --tcp-ip ] -.RB [ --user=... ] -.RB [ --version ] -.SH DESCRIPTION -.TP -.BR mysqld_multi -.TP -.BR --config-file=... -Alternative config file. NOTE: This will not affect this program\'s own options (group [mysqld_multi]), but only groups [mysqld#]. Without this option everything will be searched from the ordinary my.cnf file. -.TP -.BR --example -Give an example of a config file. -.TP -.BR --help -Print this help and exit. -.TP -.BR --log=... -Log file. Full path to and the name for the log file. NOTE: If the file exists, everything will be appended. -.TP -.BR --mysqladmin=... -mysqladmin binary to be used for a server shutdown. -.TP -.BR --mysqld=... -mysqld binary to be used. Note that you can give mysqld_safe to this option also. The options are passed to mysqld. Just make sure you have mysqld in your environment variable PATH or fix mysqld_safe. -.TP -.BR --no-log -Print to stdout instead of the log file. By default the log file is turned on. -.TP -.BR --password=... -Password for user for mysqladmin. -.TP -.BR --tcp-ip -Connect to the MySQL server(s) via the TCP/IP port instead of the UNIX socket. This affects stopping and reporting. If a socket file is missing, the server may still be running, but can be accessed only via the TCP/IP port. By default connecting is done via the UNIX socket. -.TP -.BR --user=... -MySQL user for mysqladmin. -.TP -.BR --version -Print the version number and exit. -.SH NOTE -Please see the mysql manual for more detailed information on this. - - - -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysql(1), -mysqlaccess(1), -mysqladmin(1), -mysqld(1), -mysqld_safe(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -mysql_zap(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. - -.SH AUTHOR - -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com/). -This software comes with no warranty. -Manual page by L. (Kill-9) Pedersen -(kill-9@kill-9.dk), Mercurmedia Data Model Architect / -system developer (http://www.mercurmedia.com) - - -.\" end of man page - - diff --git a/man/mysqld_safe.1.in b/man/mysqld_safe.1.in deleted file mode 100644 index 5aabd232a11..00000000000 --- a/man/mysqld_safe.1.in +++ /dev/null @@ -1,91 +0,0 @@ -.TH safe_mysqld 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -mysqld_safe \- start the mysqld daemon on Unix. -.SH SYNOPSIS -.B mysqld_safe -.RB [ \-\-basedir=\fP\fIpath\fP ] -.RB [ \-\-core\-file\-size=# ] -.RB [ \-\-defaults\-extra\-file=\fP\fIpath\fP ] -.RB [ \-\-defaults\-file=\fP\fIpath\fP ] -.RB [ \-\-open\-files=# ] -.RB [ \-\-datadir=\fP\fIpath\fP ] -.RB [ \-\-err\-log=\fP\fIpath \fP] -.RB [ \-\-ledir=path ] -.RB [ \-\-log=\fP\fIpath\fP ] -.RB [ \-\-no\-defaults ] -.RB [ \-\-open\-files=# ] -.RB [ \-\-pid\-file=\fP\fIpath\fP ] -.RB [ \-\-port=# ] -.RB [ \-\-socket=\fP\fIpath\fP ] -.RB [ \-\-timezone=# ] -.RB [ \-\-user=# ] -.SH DESCRIPTION -mysqld_safe adds some safety features such as restarting the server when an -error occurs and logging run-time information to a log file. -.BR -.TP -.BR \-\-basedir=\fP\fIpath \fP -.TP -.BR \-\-core\-file\-size=# -Size of the core file mysqld should be able to create. Passed to ulimit \-c. -.TP -.BR \-\-defaults\-extra\-file=\fP\fIpath \fP -.TP -.BR \-\-defaults\-file=\fP\fIpath \fP -.TP -.BR \-\-datadir=\fP\fIpath \fP -.TP -.BR \-\-err\-log=\fP\fIpath \fP -.TP -.BR \-\-ledir=\fP\fIpath \fP -Path to mysqld -.TP -.BR \-\-log=\fP\fIpath \fP -.TP -.BR \-\-no\-defaults -.TP -.BR \-\-open\-files=# -Number of files mysqld should be able to open. Passed to ulimit \-n. -.TP -.BR \-\-pid\-file=\fP\fIpath \fP -.TP -.BR \-\-port=# -.TP -.BR \-\-socket=\fP\fIpath \fP -.TP -.BR \-\-timezone=# -Set the timezone (the TZ) variable to the value of this parameter. -.TP -.BR \-\-user=# -.SH NOTE -Note that all options on the command line to mysqld_safe are passed to mysqld. If you wants to use any options in mysqld_safe that mysqld doesn't support, you must specify these in the option file. -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysql(1), -mysqlaccess(1), -mysqladmin(1), -mysqld(1), -mysqld_multi(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -mysql_zap(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com). -This software comes with no warranty. -Manual page by L. (Kill-9) Pedersen -(kill-9@kill\-9.dk), Mercurmedia Data Model Architect / -system developer (http://www.mercurmedia.com) - -.\" end of man page diff --git a/man/mysqldump.1.in b/man/mysqldump.1.in deleted file mode 100644 index 0f581429af7..00000000000 --- a/man/mysqldump.1.in +++ /dev/null @@ -1,279 +0,0 @@ -.TH mysqldump 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -mysqldump \- text\-based client for dumping or backing up mysql databases, tables and or data. - -.SH USAGE -.BR "mysqldump [\fP\fIOPTIONS\fP] database [\fP\fItables\fP]" -.TP -OR -.BR "mysqldump [\fP\fIOPTIONS\fP] \-\-databases [\fP\fIOPTIONS\fP] DB1 [\fP\fIDB2 DB3...\fP]" -.TP -OR -.BR "mysqldump [\fP\fIOPTIONS\fP] \-\-all-databases [\fP\fIOPTIONS\fP]" - -.SH OPTION SYNOPSIS -.B mysqldump -.RB [ \-A | \-\-all-databases ] -.RB [ \-a | \-\-all ] -.RB [ \-# | \-\-debug=... ] -.RB [ \-\-character-sets-dir=...] -.RB [ \-? | \-\-help ] -.RB [ \-B | \-\-databases ] -.RB [ \-c | \-\-complete-insert ] -.RB [ \-C | \-\-compress ] -.RB [ \-\-default-character-set=...] -.RB [ \-e | \-\-extended-insert ] -.RB [ \-\-add-drop-table ] -.RB [ \-\-add-locks ] -.RB [ \-\-allow-keywords ] -.RB [ \-\-delayed-insert ] -.RB [ \-F | \-\-flush-logs ] -.RB [ \-f | \-\-force ] -.RB [ \-h | \-\-host=... ] -.RB [ \-l | \-\-lock-tables ] -.RB [ \-n | \-\-no-create-db ] -.RB [ \-t | \-\-no-create-info ] -.RB [ \-d | \-\-no-data ] -.RB [ \-O | \-\-set-variable var=\fP\fIoption\fP ] -.RB [ \-\-opt ] -.RB [ \-p | \-\-password\fP\fI[=...]\fP ] -.RB [ \-P | \-\-port=... ] -.RB [ \-q | \-\-quick ] -.RB [ \-Q | \-\-quote-names ] -.RB [ \-S | \-\-socket=... ] -.RB [ \-\-tables ] -.RB [ \-T | \-\-tab=... ] -.RB [ \-u | \-\-user=# ] -.RB [ \-v | \-\-verbose ] -.RB [ \-V | \-\-version ] -.RB [ \-w | \-\-where= ] -.RB [ \-\-delayed ] -.RB [ \-e | \-\-extended-insert ] -.RB [ \-\-fields\-terminated\-by=... ] -.RB [ \-\-fields\-enclosed\-by=... ] -.RB [ \-\-fields-optionally\-enclosed\-by=... ] -.RB [ \-\-fields\-escaped\-by=... ] -.RB [ \-\-lines\-terminated\-by=... ] -.RB [ \-v | \-\-verbose ] -.RB [ \-V | \-\-version ] -.RB [ "\-O net_buffer_length=#, where # < 16M" ] -.SH DESCRIPTION -Dumping definition and data mysql database or table -.IR mysqldump -supports by executing -.TP -.BR \-A | \-\-all\-databases -Dump all the databases. This will be same as -.BR \-\-databases -with all databases selected. -.TP -.BR \-a | \-\-all -Include all MySQL specific create options. -.TP -.BR \-# | \-\-debug=... -Output debug log. Often this is 'd:t:o,filename`. -.TP -.BR \-\-character\-sets\-dir=... -Directory where character sets are -.TP -.BR \-? | \-\-help -Display this help message and exit. -.TP -.BR \-B | \-\-databases -To dump several databases. Note the difference in -usage; In this case no tables are given. All name -arguments are regarded as databasenames. -'USE db_name;' will be included in the output -.TP -.BR \-c | \-\-complete\-insert -Use complete insert statements. -.TP -.BR \-C | \-\-compress -Use compression in server/client protocol. -.TP -.BR \-\-default\-character\-set=... -Set the default character set -.TP -.BR \-e | \-\-extended\-insert -Allows utilization of the new, much faster -INSERT syntax. -.TP -.BR \-\-add\-drop\-table -Add a 'drop table' before each create. -.TP -.BR \-\-add\-locks -Add locks around insert statements. -.TP -.BR \-\-allow\-keywords -Allow creation of column names that are keywords. -.TP -.BR \-\-delayed\-insert -Insert rows with INSERT DELAYED. -.TP -.BR \-F | \-\-flush\-logs -Flush logs file in server before starting dump. -.TP -.BR \-f | \-\-force -Continue even if we get an sql\-error. -.TP -.BR \-h | \-\-host=... -Connect to host. -.TP -.BR \-l | \-\-lock\-tables -Lock all tables for read. -.TP -.BR \-n | \-\-no\-create\-db -\&'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' -will not be put in the output. The above line will -be added otherwise, if -.BR \-\-databases -or -.BR \-\-all\-databases -option was given. -.TP -.BR \-t | \-\-no\-create\-info -Don't write table creation info. -.TP -.BR \-d | \-\-no\-data -No row information. -.TP -.BR \-O | "\-\-set\-variable var=option" -give a variable a value. -.BR \-\-help -lists variables -.TP -.BR \-\-opt -Same as -.BR " \-\-add\-drop\-table \-\-add\-locks \-\-all \-\-extended\-insert \-\-quick \-\-lock\-tables " -.TP -.BR \-p | \-\-password[=...] -Password to use when connecting to server. -If password is not given it's solicited on the tty. -.TP -.BR \-P | \-\-port=... -Port number to use for connection. -.TP -.BR \-q | \-\-quick -Don't buffer query, dump directly to stdout. -.TP -.BR \-Q | \-\-quote\-names -Quote table and column names with ` -.TP -.BR \-S | \-\-socket=... -Socket file to use for connection. -.TP -.BR \-\-tables -\fP\fIOverrides \fPoption -.BR \-\-databases (\-B). -.TP -.BR \-T | \-\-tab=... -Creates tab separated textfile for each table to -given path. (creates .sql and .txt files). -NOTE: This only works if mysqldump is run on -the same machine as the mysqld daemon. -.TP -.BR \-u | \-\-user=# -User for login if not current user. -.TP -.BR \-v | \-\-verbose -Print info about the various stages. -.TP -.BR \-V | \-\-version -Output version information and exit. -.TP -.BR \-w | \-\-where= -dump only selected records; QUOTES mandatory! -.TP -.BR \-\-delayed -Insert rows with the INSERT DELAYED command. -.TP -.BR \-e | \-\-extended-insert -Use the new multiline INSERT syntax. (Gives more compact and faster inserts statements.) -.TP -.BR \-\-fields\-terminated\-by=... -.TP -.BR \-\-fields\-enclosed\-by=... -.TP -.TP -.BR \-\-fields-optionally\-enclosed\-by=... -.TP -.BR \-\-fields\-escaped\-by=... -.TP -.BR \-\-lines\-terminated\-by=... -These options are used with the -.BR -T -option and have the same meaning as the corresponding clauses for LOAD DATA INFILE. See Mysql manual section 7.23 LOAD DATA INFILE Syntax. -.TP -.BR \-v | \-\-verbose -Verbose mode. Print out more information on what the program does. -.TP -.BR \-V | \-\-version -Print version information and exit. -.TP -.BR "\-O net_buffer_length=#, where # < 16M " -When creating multi-row-insert statements (as with option -.BR --extended-insert -or -.BR --opt -), mysqldump will create rows up to net_buffer_length length. If you increase this variable, you should also ensure that the max_allowed_packet variable in the MySQL server is bigger than the net_buffer_length. -.SH EXAMPLES -.TP -The most normal use of mysqldump is probably for making a backup of whole -databases. See the section on Database Backups in the MySQL Reference Manual. -.TP -mysqldump \-\-opt \fP\fIdatabase\fP > backup-file.sql -.TP -You can read this back into MySQL with: -.TP -.BR mysql -\fP\fIdatabase\fP -.BR < -backup-file.sql -.TP -or -.TP -.BR mysql -\-e 'source /patch\-to\-backup/backup\-file.sql' database -.TP -However, it's also very useful to populate another MySQL server with information from a database: -.TP -mysqldump \-\-opt \fP\fIdatabase\fP | mysql \-\-host=\fP\fIremote\-host\fP \-C database -.TP -It is possible to dump several databases with one command: -.TP -mysqldump \-\-databases database1 [ database2 database3... ] > my_databases.sql -.TP -If all the databases are wanted, one can use: -.TP -mysqldump \fP\fI\-\-all\-databases\fP > all_databases.sql - -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysql(1), -mysqlaccess(1), -mysqladmin(1), -mysqld(1), -mysqld_multi(1), -mysqld_safe(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -mysql_zap(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com/). -This software comes with no warranty. -Manual page by L. (Kill-9) Pedersen -(kill-9@kill-9.dk), Mercurmedia Data Model Architect / -system developer (http://www.mercurmedia.com) - -.\" end of man page diff --git a/man/mysqlman.1.in b/man/mysqlman.1 index b09b01ca759..2170942ebd9 100644 --- a/man/mysqlman.1.in +++ b/man/mysqlman.1 @@ -1,4 +1,4 @@ -.TH mysqlman 1 "20 July 2004" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" +.TH mysqlman 1 "20 July 2004" "MySQL" "MySQL database" .SH NAME mysqlman \- default man page for mysql .SH "DESCRIPTION" diff --git a/man/mysqlshow.1.in b/man/mysqlshow.1.in deleted file mode 100644 index 2db79ae070e..00000000000 --- a/man/mysqlshow.1.in +++ /dev/null @@ -1,98 +0,0 @@ -.TH mysqlshow 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -.BR mysqlshow - \- Shows the structure of a mysql database (databases,tables and columns) -.SH USAGE -shell> mysqlshow [\fP\fIOPTIONS\fP] [\fP\fIdatabase [table [column]]\fP] -.SH SYNOPSIS -.B mysqlshow -.RB [ \-# | \-\-debug=...] -.RB [ \-? | \-\-help ] -.RB [ \-c | \-\-character\-sets\-dir=...] -.RB [ \-C | \-\-compress ] -.RB [ \-h | \-\-host=... ] -.RB [ \-i | \-\-status ] -.RB [ \-k | \-\-keys ] -.RB [ \-p | \-\-password\fP\fI[=...]\fP ] -.RB [ \-P | \-\-port=... ] -.RB [ \-S | \-\-socket=... ] -.RB [ \-u | \-\-user=# ] -.RB [ \-V | \-\-version ] -.SH DESCRIPTION -.TP -.BR \-# | \-\-debug=... -output debug log. Often this is 'd:t:o,filename` -.TP -.BR \-? | \-\-help -display help and exit -.TP -.BR \-c | \-\-character\-sets\-dir=... -Directory where character sets are -.TP -.BR \-C | \-\-compress -Use compression in server/client protocol -.TP -.BR \-h | \-\-host=... -connect to host -.TP -.BR \-i | \-\-status -Shows a lot of extra information about each table -.TP -.BR \-k | \-\-keys -show keys for table -.TP -.BR \-p | \-\-password \fP\fI[=...] \fP -password to use when connecting to server -If password is not given it's asked from the tty. -.TP -.BR \-P | \-\-port=... -Port number to use for connection -.TP -.BR \-S | \-\-socket=... -Socket file to use for connection -.TP -.BR \-u | \-\-user=# -user for login if not current user -.TP -.BR \-V | \-\-version -output version information and exit - - -.SH NOTE -If last argument contains a shell or SQL wildcard (*,?,% or _) then only -what's matched by the wildcard is shown. -If no database is given then all matching databases are shown. -If no table is given then all matching tables in database are shown -If no column is given then all matching columns and columntypes in table -are shown - -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysql(1), -mysqlaccess(1), -mysqladmin(1), -mysqld(1), -mysqld_multi(1), -mysqld_safe(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysql_zap(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com/). -This software comes with no warranty. -Manual page by L. (Kill-9) Pedersen -(kill-9@kill\-9.dk), Mercurmedia Data Model Architect / -system developer (http://www.mercurmedia.com) - -.\" end of man page diff --git a/man/perror.1.in b/man/perror.1.in deleted file mode 100644 index 45b343a9c3f..00000000000 --- a/man/perror.1.in +++ /dev/null @@ -1,58 +0,0 @@ -.TH perror 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -perror \- describes a system or MySQL error code. -.SH SYNOPSIS -perror [OPTIONS] [ERRORCODE [ERRORCODE...]] -.SH DESCRIPTION -Can be used to display a description for a system error code, or an MyISAM/ISAM table handler error code. -The error messages are mostly system dependent. -.SH OPTIONS -.TP -.BR \-? | \-\-help -Displays this help and exits. -.TP -.BR \-I | \-\-info -Synonym for the above. -.TP -.BR \-s | \-\-silent -Only print the error message -.TP -.BR \-v | \-\-verbose -Print error code and message (default). -.TP -.BR \-V | \-\-version -Displays version information and exits. -.SH EXAMPLE -shell> perror 64 79 -Error code 64: Machine is not on the network -Error code 79: Can not access a needed shared library -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysql(1), -mysqlaccess(1), -mysqladmin(1), -mysqld(1), -mysqld_multi(1), -mysqld_safe(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -mysql_zap(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com/). -This software comes with no warranty. -Manual page by L. (Kill-9) Pedersen -(kill-9@kill\-9.dk), Mercurmedia Data Model Architect / -system developer (http://www.mercurmedia.com) - -.\" end of man page diff --git a/man/replace.1.in b/man/replace.1.in deleted file mode 100644 index 618ed0f5bea..00000000000 --- a/man/replace.1.in +++ /dev/null @@ -1,73 +0,0 @@ -.TH replace 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -.TP -replace - A utility program that is used by msql2mysql, but that has more general applicability as well. replace changes strings in place in files or on the standard input. Uses a finite state machine to match longer strings first. Can be used to swap strings. -.SH USAGE -replace [-?svIV] from to from to ... -- [files] -.TP -or -.TP -replace [-?svIV] from to from to ... < fromfile > tofile -.SH SYNOPSIS -.B replace -.RB [ -? | -I ] -.RB [ -s ] -.RB [ -v ] -.SH DESCRIPTION -.TP -.BR replace -.TP -.BR -? | -I -info -.TP -.BR -s -silent -.TP -.BR -v -verbose -.SH EXTRA INFO -.B Special characters in from string: -.TP -\\^ -Match start of line. -.TP -\\$ -Match end of line. -.TP -\\b -Match space-character, start of line or end of line. For a end \\b the next replace starts locking at the end space-character. A \\b alone in a string matches only a space-character. -.SH EXAMPLE -this command swaps a and b in the given files: -.TP -shell> replace a b b a -- file1 file2 ... -.SH "SEE ALSO" -isamchk(1), -isamlog(1), -mysql(1), -mysqlaccess(1), -mysqladmin(1), -mysqld(1), -mysqld_multi(1), -mysqld_safe(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -mysql_zap(1), -perror(1), -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://dev.mysql.com/doc/mysql/en -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com/). -This software comes with no warranty. -Manual page by L. (Kill-9) Pedersen -(kill-9@kill-9.dk), Mercurmedia Data Model Architect / -system developer (http://www.mercurmedia.com) -.\" end of man page - - diff --git a/myisam/ft_parser.c b/myisam/ft_parser.c index 2fad2363ae2..6e79696bd6e 100644 --- a/myisam/ft_parser.c +++ b/myisam/ft_parser.c @@ -149,8 +149,10 @@ byte ft_get_word(CHARSET_INFO *cs, byte **start, byte *end, for (word->pos=doc; doc<end; length++, mbl=my_mbcharlen(cs, *(uchar *)doc), doc+=(mbl ? mbl : 1)) if (true_word_char(cs,*doc)) mwc=0; - else if (!misc_word_char(*doc) || mwc++) + else if (!misc_word_char(*doc) || mwc) break; + else + mwc++; param->prev='A'; /* be sure *prev is true_word_char */ word->len= (uint)(doc-word->pos) - mwc; @@ -196,8 +198,10 @@ byte ft_simple_get_word(CHARSET_INFO *cs, byte **start, const byte *end, for (word->pos=doc; doc<end; length++, mbl=my_mbcharlen(cs, *(uchar *)doc), doc+=(mbl ? mbl : 1)) if (true_word_char(cs,*doc)) mwc= 0; - else if (!misc_word_char(*doc) || mwc++) + else if (!misc_word_char(*doc) || mwc) break; + else + mwc++; word->len= (uint)(doc-word->pos) - mwc; diff --git a/myisam/mi_check.c b/myisam/mi_check.c index f5d46210944..9ce1dff51af 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -392,14 +392,17 @@ int chk_key(MI_CHECK *param, register MI_INFO *info) found_keys++; param->record_checksum=init_checksum; + bzero((char*) ¶m->unique_count,sizeof(param->unique_count)); + bzero((char*) ¶m->notnull_count,sizeof(param->notnull_count)); + if ((!(param->testflag & T_SILENT))) printf ("- check data record references index: %d\n",key+1); if (keyinfo->flag & HA_FULLTEXT) full_text_keys++; if (share->state.key_root[key] == HA_OFFSET_ERROR && (info->state->records == 0 || keyinfo->flag & HA_FULLTEXT)) - continue; + goto do_stat; if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key], DFLT_INIT_HITS,info->buff,0)) { @@ -495,9 +498,12 @@ int chk_key(MI_CHECK *param, register MI_INFO *info) param->max_level); all_keydata+=param->keydata; all_totaldata+=param->totaldata; key_totlength+=length; +do_stat: if (param->testflag & T_STATISTICS) update_key_parts(keyinfo, rec_per_key_part, param->unique_count, - (ulonglong) info->state->records); + param->stats_method == MI_STATS_METHOD_IGNORE_NULLS? + param->notnull_count: NULL, + (ulonglong)info->state->records); } if (param->testflag & T_INFO) { @@ -553,6 +559,96 @@ err: return 1; } + +/* + "Ignore NULLs" statistics collection method: process first index tuple. + + SYNOPSIS + mi_collect_stats_nonulls_first() + keyseg IN Array of key part descriptions + notnull INOUT Array, notnull[i] = (number of {keypart1...keypart_i} + tuples that don't contain NULLs) + key IN Key values tuple + + DESCRIPTION + Process the first index tuple - find out which prefix tuples don't + contain NULLs, and update the array of notnull counters accordingly. +*/ + +static +void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, ulonglong *notnull, + uchar *key) +{ + uint first_null, kp; + first_null= ha_find_null(keyseg, key) - keyseg; + /* + All prefix tuples that don't include keypart_{first_null} are not-null + tuples (and all others aren't), increment counters for them. + */ + for (kp= 0; kp < first_null; kp++) + notnull[kp]++; +} + + +/* + "Ignore NULLs" statistics collection method: process next index tuple. + + SYNOPSIS + mi_collect_stats_nonulls_next() + keyseg IN Array of key part descriptions + notnull INOUT Array, notnull[i] = (number of {keypart1...keypart_i} + tuples that don't contain NULLs) + prev_key IN Previous key values tuple + last_key IN Next key values tuple + + DESCRIPTION + Process the next index tuple: + 1. Find out which prefix tuples of last_key don't contain NULLs, and + update the array of notnull counters accordingly. + 2. Find the first keypart number where the prev_key and last_key tuples + are different(A), or last_key has NULL value(B), and return it, so the + caller can count number of unique tuples for each key prefix. We don't + need (B) to be counted, and that is compensated back in + update_key_parts(). + + RETURN + 1 + number of first keypart where values differ or last_key tuple has NULL +*/ + +static +int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, ulonglong *notnull, + uchar *prev_key, uchar *last_key) +{ + uint diffs[2]; + uint first_null_seg, kp; + HA_KEYSEG *seg; + + /* + Find the first keypart where values are different or either of them is + NULL. We get results in diffs array: + diffs[0]= 1 + number of first different keypart + diffs[1]=offset: (last_key + diffs[1]) points to first value in + last_key that is NULL or different from corresponding + value in prev_key. + */ + ha_key_cmp(keyseg, prev_key, last_key, USE_WHOLE_KEY, + SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diffs); + seg= keyseg + diffs[0] - 1; + + /* Find first NULL in last_key */ + first_null_seg= ha_find_null(seg, last_key + diffs[1]) - keyseg; + for (kp= 0; kp < first_null_seg; kp++) + notnull[kp]++; + + /* + Return 1+ number of first key part where values differ. Don't care if + these were NULLs and not .... We compensate for that in + update_key_parts. + */ + return diffs[0]; +} + + /* Check if index is ok */ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, @@ -564,7 +660,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, uchar key[MI_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos; my_off_t next_page,record; char llbuff[22]; - uint diff_pos; + uint diff_pos[2]; DBUG_ENTER("chk_index"); DBUG_DUMP("buff",(byte*) buff,mi_getint(buff)); @@ -622,7 +718,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, } if ((*keys)++ && (flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length, - comp_flag, &diff_pos)) >=0) + comp_flag, diff_pos)) >=0) { DBUG_DUMP("old",(byte*) info->lastkey, info->lastkey_length); DBUG_DUMP("new",(byte*) key, key_length); @@ -641,8 +737,20 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL) ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY, SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, - &diff_pos); - param->unique_count[diff_pos-1]++; + diff_pos); + else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS) + { + diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg, + param->notnull_count, + info->lastkey, key); + } + param->unique_count[diff_pos[0]-1]++; + } + else + { + if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS) + mi_collect_stats_nonulls_first(keyinfo->seg, param->notnull_count, + key); } } (*key_checksum)+= mi_byte_checksum((byte*) key, @@ -1294,25 +1402,30 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, param->calc_checksum=1; info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); + + /* + Clear all keys. Note that all key blocks allocated until now remain + "dead" parts of the key file. (Bug #4692) + */ for (i=0 ; i < info->s->base.keys ; i++) share->state.key_root[i]= HA_OFFSET_ERROR; + + /* Drop the delete chain. */ for (i=0 ; i < share->state.header.max_block_size ; i++) share->state.key_del[i]= HA_OFFSET_ERROR; /* - I think mi_repair and mi_repair_by_sort should do the same - (according, e.g. to ha_myisam::repair), but as mi_repair doesn't - touch key_map it cannot be used to T_CREATE_MISSING_KEYS. - That is what the next line is for + If requested, activate (enable) all keys in key_map. In this case, + all indexes will be (re-)built. */ - if (param->testflag & T_CREATE_MISSING_KEYS) - mi_copy_keys_active(share->state.key_map, share->base.keys, - param->keys_in_use); + mi_set_all_keys_active(share->state.key_map, share->base.keys); info->state->key_file_length=share->base.keystart; lock_memory(param); /* Everything is alloced */ + + /* Re-create all keys, which are set in key_map. */ while (!(error=sort_get_next_record(&sort_param))) { if (writekeys(param,info,(byte*)sort_param.record,sort_param.filepos)) @@ -1735,9 +1848,10 @@ static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, _mi_kpointer(info,keypos-nod_flag,param->new_file_pos); /* Save new pos */ if (sort_one_index(param,info,keyinfo,next_page,new_file)) { - DBUG_PRINT("error",("From page: %ld, keyoffset: %d used_length: %d", - (ulong) pagepos, (int) (keypos - buff), - (int) used_length)); + DBUG_PRINT("error", + ("From page: %ld, keyoffset: %lu used_length: %d", + (ulong) pagepos, (ulong) (keypos - buff), + (int) used_length)); DBUG_DUMP("buff",(byte*) buff,used_length); goto err; } @@ -2092,7 +2206,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, if (param->testflag & T_STATISTICS) update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique, - (ulonglong) info->state->records); + param->stats_method == MI_STATS_METHOD_IGNORE_NULLS? + sort_param.notnull: NULL,(ulonglong) info->state->records); mi_set_key_active(share->state.key_map, sort_param.key); if (sort_param.fix_datafile) @@ -3236,15 +3351,15 @@ int sort_write_record(MI_SORT_PARAM *sort_param) static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a, const void *b) { - uint not_used; + uint not_used[2]; return (ha_key_cmp(sort_param->seg, *((uchar**) a), *((uchar**) b), - USE_WHOLE_KEY, SEARCH_SAME,¬_used)); + USE_WHOLE_KEY, SEARCH_SAME, not_used)); } /* sort_key_cmp */ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a) { - uint diff_pos; + uint diff_pos[2]; char llbuff[22],llbuff2[22]; SORT_INFO *sort_info=sort_param->sort_info; MI_CHECK *param= sort_info->param; @@ -3254,16 +3369,26 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a) { cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE, - &diff_pos); + diff_pos); if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL) ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, (uchar*) a, USE_WHOLE_KEY, - SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, &diff_pos); - sort_param->unique[diff_pos-1]++; + SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos); + else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS) + { + diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg, + sort_param->notnull, + sort_info->key_block->lastkey, + (uchar*)a); + } + sort_param->unique[diff_pos[0]-1]++; } else { cmp= -1; + if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS) + mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull, + (uchar*)a); } if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0) { @@ -3981,24 +4106,34 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info, /* Update statistics for each part of an index - + SYNOPSIS update_key_parts() - keyinfo Index information (only key->keysegs used) + keyinfo IN Index information (only key->keysegs used) rec_per_key_part OUT Store statistics here - unique IN Array of #distinct values collected over index - run. + unique IN Array of (#distinct tuples) + notnull_tuples IN Array of (#tuples), or NULL records Number of records in the table - - NOTES + + DESCRIPTION + This function is called produce index statistics values from unique and + notnull_tuples arrays after these arrays were produced with sequential + index scan (the scan is done in two places: chk_index() and + sort_key_write()). + + This function handles all 3 index statistics collection methods. + Unique is an array: - unique[0]= (#different values of {keypart1}) - 1 - unique[1]= (#different values of {keypart2,keypart1} tuple) - unique[0] - 1 - ... - The 'unique' array is collected in one sequential scan through the entire - index. This is done in two places: in chk_index() and in sort_key_write(). - Statistics collection may consider NULLs as either equal or unequal (see - SEARCH_NULL_ARE_NOT_EQUAL, MI_STATS_METHOD_*). + unique[0]= (#different values of {keypart1}) - 1 + unique[1]= (#different values of {keypart1,keypart2} tuple)-unique[0]-1 + ... + + For MI_STATS_METHOD_IGNORE_NULLS method, notnull_tuples is an array too: + notnull_tuples[0]= (#of {keypart1} tuples such that keypart1 is not NULL) + notnull_tuples[1]= (#of {keypart1,keypart2} tuples such that all + keypart{i} are not NULL) + ... + For all other statistics collection methods notnull_tuples==NULL. Output is an array: rec_per_key_part[k] = @@ -4010,25 +4145,53 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info, index tuples} = #tuples-in-the-index / #distinct-tuples-in-the-index. + + The #tuples-in-the-index and #distinct-tuples-in-the-index have different + meaning depending on which statistics collection method is used: + + MI_STATS_METHOD_* how are nulls compared? which tuples are counted? + NULLS_EQUAL NULL == NULL all tuples in table + NULLS_NOT_EQUAL NULL != NULL all tuples in table + IGNORE_NULLS n/a tuples that don't have NULLs */ void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part, - ulonglong *unique, ulonglong records) + ulonglong *unique, ulonglong *notnull, + ulonglong records) { - ulonglong count=0,tmp; + ulonglong count=0,tmp, unique_tuples; + ulonglong tuples= records; uint parts; for (parts=0 ; parts < keyinfo->keysegs ; parts++) { count+=unique[parts]; - if (count == 0) - tmp=records; + unique_tuples= count + 1; + if (notnull) + { + tuples= notnull[parts]; + /* + #(unique_tuples not counting tuples with NULLs) = + #(unique_tuples counting tuples with NULLs as different) - + #(tuples with NULLs) + */ + unique_tuples -= (records - notnull[parts]); + } + + if (unique_tuples == 0) + tmp= 1; + else if (count == 0) + tmp= tuples; /* 1 unique tuple */ else - tmp= (records + (count+1)/2) / (count+1); - /* for some weird keys (e.g. FULLTEXT) tmp can be <1 here. - let's ensure it is not */ + tmp= (tuples + unique_tuples/2) / unique_tuples; + + /* + for some weird keys (e.g. FULLTEXT) tmp can be <1 here. + let's ensure it is not + */ set_if_bigger(tmp,1); if (tmp >= (ulonglong) ~(ulong) 0) tmp=(ulonglong) ~(ulong) 0; + *rec_per_key_part=(ulong) tmp; rec_per_key_part++; } diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 6d4106afda5..1a17febe94a 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -72,7 +72,6 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, } LINT_INIT(dfile); LINT_INIT(file); - pthread_mutex_lock(&THR_LOCK_myisam); errpos=0; options=0; bzero((byte*) &share,sizeof(share)); @@ -135,7 +134,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, pack_reclength++; min_pack_length++; /* We must test for 257 as length includes pack-length */ - if (test(rec->length >= 257)) + if (test(rec->length >= 257)) { long_varchar_count++; pack_reclength+= 2; /* May be packed on 3 bytes */ @@ -542,6 +541,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, if (! (flags & HA_DONT_TOUCH_DATA)) share.state.create_time= (long) time((time_t*) 0); + pthread_mutex_lock(&THR_LOCK_myisam); + if (ci->index_file_name) { fn_format(filename, ci->index_file_name,"",MI_NAME_IEXT,4); diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index 62ca7f8ff61..416d951d138 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -170,7 +170,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo, goto err; } if ((error=d_search(info,keyinfo, - (keyinfo->flag & HA_FULLTEXT ? SEARCH_FIND + (keyinfo->flag & HA_FULLTEXT ? SEARCH_FIND | SEARCH_UPDATE : SEARCH_SAME), key,key_length,old_root,root_buff)) >0) { @@ -407,7 +407,8 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key, MYISAM_SHARE *share=info->s; MI_KEY_PARAM s_temp; DBUG_ENTER("del"); - DBUG_PRINT("enter",("leaf_page: %ld keypos: %lx",leaf_page,keypos)); + DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx", leaf_page, + (ulong) keypos)); DBUG_DUMP("leaf_buff",(byte*) leaf_buff,mi_getint(leaf_buff)); endpos=leaf_buff+mi_getint(leaf_buff); @@ -512,7 +513,8 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo, MI_KEY_PARAM s_temp; MYISAM_SHARE *share=info->s; DBUG_ENTER("underflow"); - DBUG_PRINT("enter",("leaf_page: %ld keypos: %lx",(long) leaf_page,keypos)); + DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx",(long) leaf_page, + (ulong) keypos)); DBUG_DUMP("anc_buff",(byte*) anc_buff,mi_getint(anc_buff)); DBUG_DUMP("leaf_buff",(byte*) leaf_buff,mi_getint(leaf_buff)); diff --git a/myisam/mi_rnext_same.c b/myisam/mi_rnext_same.c index 4d770258a72..92692d0517f 100644 --- a/myisam/mi_rnext_same.c +++ b/myisam/mi_rnext_same.c @@ -28,7 +28,7 @@ int mi_rnext_same(MI_INFO *info, byte *buf) { int error; - uint inx,not_used; + uint inx,not_used[2]; MI_KEYDEF *keyinfo; DBUG_ENTER("mi_rnext_same"); @@ -69,7 +69,7 @@ int mi_rnext_same(MI_INFO *info, byte *buf) info->s->state.key_root[inx]))) break; if (ha_key_cmp(keyinfo->seg, info->lastkey, info->lastkey2, - info->last_rkey_length, SEARCH_FIND, ¬_used)) + info->last_rkey_length, SEARCH_FIND, not_used)) { error=1; my_errno=HA_ERR_END_OF_FILE; diff --git a/myisam/mi_search.c b/myisam/mi_search.c index 92efdfee457..a6c2cbd6082 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -128,13 +128,13 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0) { - uint not_used; + uint not_used[2]; if (_mi_get_prev_key(info,keyinfo, buff, info->lastkey, keypos, &info->lastkey_length)) goto err; if (!(nextflag & SEARCH_SMALLER) && ha_key_cmp(keyinfo->seg, info->lastkey, key, key_len, SEARCH_FIND, - ¬_used)) + not_used)) { my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */ goto err; @@ -179,7 +179,7 @@ int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, { reg4 int start,mid,end,save_end; int flag; - uint totlength,nod_flag,not_used; + uint totlength,nod_flag,not_used[2]; DBUG_ENTER("_mi_bin_search"); LINT_INIT(flag); @@ -193,7 +193,7 @@ int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, { mid= (start+end)/2; if ((flag=ha_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len, - comp_flag,¬_used)) + comp_flag, not_used)) >= 0) end=mid; else @@ -201,7 +201,7 @@ int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, } if (mid != start) flag=ha_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len, - comp_flag,¬_used); + comp_flag, not_used); if (flag < 0) start++; /* point at next, bigger key */ *ret_pos=page+(uint) start*totlength; @@ -242,7 +242,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, uchar *buff, my_bool *last_key) { int flag; - uint nod_flag,length,not_used; + uint nod_flag,length,not_used[2]; uchar t_buff[MI_MAX_KEY_BUFF],*end; DBUG_ENTER("_mi_seq_search"); @@ -264,7 +264,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, DBUG_RETURN(MI_FOUND_WRONG_KEY); } if ((flag=ha_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag, - ¬_used)) >= 0) + not_used)) >= 0) break; #ifdef EXTRA_DEBUG DBUG_PRINT("loop",("page: %lx key: '%s' flag: %d", (long) page, t_buff, @@ -507,9 +507,9 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, cmp_rest: if (key_len_left>0) { - uint not_used; + uint not_used[2]; if ((flag = ha_key_cmp(keyinfo->seg+1,vseg, - k,key_len_left,nextflag,¬_used)) >= 0) + k, key_len_left, nextflag, not_used)) >= 0) break; } else diff --git a/myisam/mi_write.c b/myisam/mi_write.c index 8785adae9a2..2dd84674bff 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -898,10 +898,10 @@ int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key, static int keys_compare(bulk_insert_param *param, uchar *key1, uchar *key2) { - uint not_used; + uint not_used[2]; return ha_key_cmp(param->info->s->keyinfo[param->keynr].seg, - key1, key2, USE_WHOLE_KEY, SEARCH_SAME, - ¬_used); + key1, key2, USE_WHOLE_KEY, SEARCH_SAME, + not_used); } diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index a90495e5fcb..e2c8b446322 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -165,7 +165,7 @@ static struct my_option my_long_options[] = "Analyze distribution of keys. Will make some joins in MySQL faster. You can check the calculated distribution.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __NETWARE__ - {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", + {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"block-search", 'b', @@ -339,7 +339,8 @@ static struct my_option my_long_options[] = REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"stats_method", OPT_STATS_METHOD, "Specifies how index statistics collection code should threat NULLs. " - "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), and \"nulls_equal\" (emulate 4.0 behavior).", + "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), " + "\"nulls_equal\" (emulate 4.0 behavior), and \"nulls_ignored\".", (gptr*) &myisam_stats_method_str, (gptr*) &myisam_stats_method_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} @@ -451,6 +452,10 @@ static void usage(void) -a, --analyze Analyze distribution of keys. Will make some joins in\n\ MySQL faster. You can check the calculated distribution\n\ by using '--description --verbose table_name'.\n\ + --stats_method=name Specifies how index statistics collection code should\n\ + threat NULLs. Possible values of name are \"nulls_unequal\"\n\ + (default for 4.1/5.0), \"nulls_equal\" (emulate 4.0), and \n\ + \"nulls_ignored\".\n\ -d, --description Prints some information about table.\n\ -A, --set-auto-increment[=value]\n\ Force auto_increment to start at this or higher value\n\ @@ -472,7 +477,7 @@ static void usage(void) #include <help_end.h> const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal", - NullS}; + "nulls_ignored", NullS}; TYPELIB myisam_stats_method_typelib= { array_elements(myisam_stats_method_names) - 1, "", myisam_stats_method_names, NULL}; @@ -699,13 +704,25 @@ get_one_option(int optid, case OPT_STATS_METHOD: { int method; + enum_mi_stats_method method_conv; myisam_stats_method_str= argument; if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0) { fprintf(stderr, "Invalid value of stats_method: %s.\n", argument); exit(1); } - check_param.stats_method= (enum_mi_stats_method) (method-1); + switch (method-1) { + case 0: + method_conv= MI_STATS_METHOD_NULLS_EQUAL; + break; + case 1: + method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; + break; + case 2: + method_conv= MI_STATS_METHOD_IGNORE_NULLS; + break; + } + check_param.stats_method= method_conv; break; } #ifdef DEBUG /* Only useful if debugging */ diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 36328c9d9f1..6ccb52aff22 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -298,7 +298,14 @@ typedef struct st_mi_sort_param pthread_t thr; IO_CACHE read_cache, tempfile, tempfile_for_exceptions; DYNAMIC_ARRAY buffpek; + + /* + The next two are used to collect statistics, see update_key_parts for + description. + */ ulonglong unique[MI_MAX_KEY_SEG+1]; + ulonglong notnull[MI_MAX_KEY_SEG+1]; + my_off_t pos,max_pos,filepos,start_recpos; uint key, key_length,real_key_length,sortbuff_size; uint maxbuffers, keys, find_length, sort_keys_length; diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 114e80d8f1a..d691c24e890 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -254,7 +254,7 @@ enum options_mp {OPT_CHARSETS_DIR_MP=256, OPT_AUTO_CLOSE}; static struct my_option my_long_options[] = { #ifdef __NETWARE__ - {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", + {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"backup", 'b', "Make a backup of the table as table_name.OLD.", diff --git a/myisam/sort.c b/myisam/sort.c index 6c718a0d453..c3eaddb3e92 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -481,8 +481,12 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) { mi_set_key_active(share->state.key_map, sinfo->key); if (param->testflag & T_STATISTICS) - update_key_parts(sinfo->keyinfo, rec_per_key_part, - sinfo->unique, (ulonglong) info->state->records); + update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique, + param->stats_method == MI_STATS_METHOD_IGNORE_NULLS? + sinfo->notnull: NULL, + (ulonglong) info->state->records); + + if (!sinfo->buffpek.elements) { if (param->testflag & T_VERBOSE) diff --git a/myisammrg/myrg_queue.c b/myisammrg/myrg_queue.c index dfb434d6397..7172b9f0e2a 100644 --- a/myisammrg/myrg_queue.c +++ b/myisammrg/myrg_queue.c @@ -20,9 +20,9 @@ static int queue_key_cmp(void *keyseg, byte *a, byte *b) { MI_INFO *aa=((MYRG_TABLE *)a)->table; MI_INFO *bb=((MYRG_TABLE *)b)->table; - uint not_used; + uint not_used[2]; int ret= ha_key_cmp((HA_KEYSEG *)keyseg, aa->lastkey, bb->lastkey, - USE_WHOLE_KEY, SEARCH_FIND, ¬_used); + USE_WHOLE_KEY, SEARCH_FIND, not_used); return ret < 0 ? -1 : ret > 0 ? 1 : 0; } /* queue_key_cmp */ diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index f1194d7fc2f..07ae10b2b07 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -95,6 +95,9 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(DESTDIR)$(testdir)/lib $(INSTALL_DATA) $(srcdir)/lib/*.pl $(DESTDIR)$(testdir)/lib +uninstall-local: + @RM@ -f -r $(DESTDIR)$(testdir) + std_data/client-key.pem: @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data std_data/client-cert.pem: diff --git a/mysql-test/include/common-tests.inc b/mysql-test/include/common-tests.inc new file mode 100644 index 00000000000..46d0182d17f --- /dev/null +++ b/mysql-test/include/common-tests.inc @@ -0,0 +1,1832 @@ +# +# This file contains a generic set of test that is run from +# different test scripts to test for example ssl encrypted +# and compressed connection +# +# + +# +# Simple select test +# + +--disable_warnings +drop table if exists t1,t2,t3,t4; +--enable_warnings + +CREATE TABLE t1 ( + Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, + Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL +); + +INSERT INTO t1 VALUES (9410,9412); + +select period from t1; +select * from t1; +select t1.* from t1; + +# +# Create test table +# + +CREATE TABLE t2 ( + auto int not null auto_increment, + fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL, + companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL, + fld3 char(30) DEFAULT '' NOT NULL, + fld4 char(35) DEFAULT '' NOT NULL, + fld5 char(35) DEFAULT '' NOT NULL, + fld6 char(4) DEFAULT '' NOT NULL, + UNIQUE fld1 (fld1), + KEY fld3 (fld3), + PRIMARY KEY (auto) +); + +# +# Populate table +# + +--disable_query_log +INSERT INTO t2 VALUES (1,000001,00,'Omaha','teethe','neat',''); +INSERT INTO t2 VALUES (2,011401,37,'breaking','dreaded','Steinberg','W'); +INSERT INTO t2 VALUES (3,011402,37,'Romans','scholastics','jarring',''); +INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily',''); +INSERT INTO t2 VALUES (5,011501,37,'bewilderingly','wallet','balled',''); +INSERT INTO t2 VALUES (6,011701,37,'astound','parters','persist','W'); +INSERT INTO t2 VALUES (7,011702,37,'admonishing','eschew','attainments',''); +INSERT INTO t2 VALUES (8,011703,37,'sumac','quitter','fanatic',''); +INSERT INTO t2 VALUES (9,012001,37,'flanking','neat','measures','FAS'); +INSERT INTO t2 VALUES (10,012003,37,'combed','Steinberg','rightfulness',''); +INSERT INTO t2 VALUES (11,012004,37,'subjective','jarring','capably',''); +INSERT INTO t2 VALUES (12,012005,37,'scatterbrain','tinily','impulsive',''); +INSERT INTO t2 VALUES (13,012301,37,'Eulerian','balled','starlet',''); +INSERT INTO t2 VALUES (14,012302,36,'dubbed','persist','terminators',''); +INSERT INTO t2 VALUES (15,012303,37,'Kane','attainments','untying',''); +INSERT INTO t2 VALUES (16,012304,37,'overlay','fanatic','announces','FAS'); +INSERT INTO t2 VALUES (17,012305,37,'perturb','measures','featherweight','FAS'); +INSERT INTO t2 VALUES (18,012306,37,'goblins','rightfulness','pessimist','FAS'); +INSERT INTO t2 VALUES (19,012501,37,'annihilates','capably','daughter',''); +INSERT INTO t2 VALUES (20,012602,37,'Wotan','impulsive','decliner','FAS'); +INSERT INTO t2 VALUES (21,012603,37,'snatching','starlet','lawgiver',''); +INSERT INTO t2 VALUES (22,012604,37,'concludes','terminators','stated',''); +INSERT INTO t2 VALUES (23,012605,37,'laterally','untying','readable',''); +INSERT INTO t2 VALUES (24,012606,37,'yelped','announces','attrition',''); +INSERT INTO t2 VALUES (25,012701,37,'grazing','featherweight','cascade','FAS'); +INSERT INTO t2 VALUES (26,012702,37,'Baird','pessimist','motors','FAS'); +INSERT INTO t2 VALUES (27,012703,37,'celery','daughter','interrogate',''); +INSERT INTO t2 VALUES (28,012704,37,'misunderstander','decliner','pests','W'); +INSERT INTO t2 VALUES (29,013601,37,'handgun','lawgiver','stairway',''); +INSERT INTO t2 VALUES (30,013602,37,'foldout','stated','dopers','FAS'); +INSERT INTO t2 VALUES (31,013603,37,'mystic','readable','testicle','W'); +INSERT INTO t2 VALUES (32,013604,37,'succumbed','attrition','Parsifal','W'); +INSERT INTO t2 VALUES (33,013605,37,'Nabisco','cascade','leavings',''); +INSERT INTO t2 VALUES (34,013606,37,'fingerings','motors','postulation','W'); +INSERT INTO t2 VALUES (35,013607,37,'aging','interrogate','squeaking',''); +INSERT INTO t2 VALUES (36,013608,37,'afield','pests','contrasted',''); +INSERT INTO t2 VALUES (37,013609,37,'ammonium','stairway','leftover',''); +INSERT INTO t2 VALUES (38,013610,37,'boat','dopers','whiteners',''); +INSERT INTO t2 VALUES (39,013801,37,'intelligibility','testicle','erases','W'); +INSERT INTO t2 VALUES (40,013802,37,'Augustine','Parsifal','Punjab','W'); +INSERT INTO t2 VALUES (41,013803,37,'teethe','leavings','Merritt',''); +INSERT INTO t2 VALUES (42,013804,37,'dreaded','postulation','Quixotism',''); +INSERT INTO t2 VALUES (43,013901,37,'scholastics','squeaking','sweetish','FAS'); +INSERT INTO t2 VALUES (44,016001,37,'audiology','contrasted','dogging','FAS'); +INSERT INTO t2 VALUES (45,016201,37,'wallet','leftover','scornfully','FAS'); +INSERT INTO t2 VALUES (46,016202,37,'parters','whiteners','bellow',''); +INSERT INTO t2 VALUES (47,016301,37,'eschew','erases','bills',''); +INSERT INTO t2 VALUES (48,016302,37,'quitter','Punjab','cupboard','FAS'); +INSERT INTO t2 VALUES (49,016303,37,'neat','Merritt','sureties','FAS'); +INSERT INTO t2 VALUES (50,016304,37,'Steinberg','Quixotism','puddings',''); +INSERT INTO t2 VALUES (51,018001,37,'jarring','sweetish','tapestry',''); +INSERT INTO t2 VALUES (52,018002,37,'tinily','dogging','fetters',''); +INSERT INTO t2 VALUES (53,018003,37,'balled','scornfully','bivalves',''); +INSERT INTO t2 VALUES (54,018004,37,'persist','bellow','incurring',''); +INSERT INTO t2 VALUES (55,018005,37,'attainments','bills','Adolph',''); +INSERT INTO t2 VALUES (56,018007,37,'fanatic','cupboard','pithed',''); +INSERT INTO t2 VALUES (57,018008,37,'measures','sureties','emergency',''); +INSERT INTO t2 VALUES (58,018009,37,'rightfulness','puddings','Miles',''); +INSERT INTO t2 VALUES (59,018010,37,'capably','tapestry','trimmings',''); +INSERT INTO t2 VALUES (60,018012,37,'impulsive','fetters','tragedies','W'); +INSERT INTO t2 VALUES (61,018013,37,'starlet','bivalves','skulking','W'); +INSERT INTO t2 VALUES (62,018014,37,'terminators','incurring','flint',''); +INSERT INTO t2 VALUES (63,018015,37,'untying','Adolph','flopping','W'); +INSERT INTO t2 VALUES (64,018016,37,'announces','pithed','relaxing','FAS'); +INSERT INTO t2 VALUES (65,018017,37,'featherweight','emergency','offload','FAS'); +INSERT INTO t2 VALUES (66,018018,37,'pessimist','Miles','suites','W'); +INSERT INTO t2 VALUES (67,018019,37,'daughter','trimmings','lists','FAS'); +INSERT INTO t2 VALUES (68,018020,37,'decliner','tragedies','animized','FAS'); +INSERT INTO t2 VALUES (69,018021,37,'lawgiver','skulking','multilayer','W'); +INSERT INTO t2 VALUES (70,018022,37,'stated','flint','standardizes','FAS'); +INSERT INTO t2 VALUES (71,018023,37,'readable','flopping','Judas',''); +INSERT INTO t2 VALUES (72,018024,37,'attrition','relaxing','vacuuming','W'); +INSERT INTO t2 VALUES (73,018025,37,'cascade','offload','dentally','W'); +INSERT INTO t2 VALUES (74,018026,37,'motors','suites','humanness','W'); +INSERT INTO t2 VALUES (75,018027,37,'interrogate','lists','inch','W'); +INSERT INTO t2 VALUES (76,018028,37,'pests','animized','Weissmuller','W'); +INSERT INTO t2 VALUES (77,018029,37,'stairway','multilayer','irresponsibly','W'); +INSERT INTO t2 VALUES (78,018030,37,'dopers','standardizes','luckily','FAS'); +INSERT INTO t2 VALUES (79,018032,37,'testicle','Judas','culled','W'); +INSERT INTO t2 VALUES (80,018033,37,'Parsifal','vacuuming','medical','FAS'); +INSERT INTO t2 VALUES (81,018034,37,'leavings','dentally','bloodbath','FAS'); +INSERT INTO t2 VALUES (82,018035,37,'postulation','humanness','subschema','W'); +INSERT INTO t2 VALUES (83,018036,37,'squeaking','inch','animals','W'); +INSERT INTO t2 VALUES (84,018037,37,'contrasted','Weissmuller','Micronesia',''); +INSERT INTO t2 VALUES (85,018038,37,'leftover','irresponsibly','repetitions',''); +INSERT INTO t2 VALUES (86,018039,37,'whiteners','luckily','Antares',''); +INSERT INTO t2 VALUES (87,018040,37,'erases','culled','ventilate','W'); +INSERT INTO t2 VALUES (88,018041,37,'Punjab','medical','pityingly',''); +INSERT INTO t2 VALUES (89,018042,37,'Merritt','bloodbath','interdependent',''); +INSERT INTO t2 VALUES (90,018043,37,'Quixotism','subschema','Graves','FAS'); +INSERT INTO t2 VALUES (91,018044,37,'sweetish','animals','neonatal',''); +INSERT INTO t2 VALUES (92,018045,37,'dogging','Micronesia','scribbled','FAS'); +INSERT INTO t2 VALUES (93,018046,37,'scornfully','repetitions','chafe','W'); +INSERT INTO t2 VALUES (94,018048,37,'bellow','Antares','honoring',''); +INSERT INTO t2 VALUES (95,018049,37,'bills','ventilate','realtor',''); +INSERT INTO t2 VALUES (96,018050,37,'cupboard','pityingly','elite',''); +INSERT INTO t2 VALUES (97,018051,37,'sureties','interdependent','funereal',''); +INSERT INTO t2 VALUES (98,018052,37,'puddings','Graves','abrogating',''); +INSERT INTO t2 VALUES (99,018053,50,'tapestry','neonatal','sorters',''); +INSERT INTO t2 VALUES (100,018054,37,'fetters','scribbled','Conley',''); +INSERT INTO t2 VALUES (101,018055,37,'bivalves','chafe','lectured',''); +INSERT INTO t2 VALUES (102,018056,37,'incurring','honoring','Abraham',''); +INSERT INTO t2 VALUES (103,018057,37,'Adolph','realtor','Hawaii','W'); +INSERT INTO t2 VALUES (104,018058,37,'pithed','elite','cage',''); +INSERT INTO t2 VALUES (105,018059,36,'emergency','funereal','hushes',''); +INSERT INTO t2 VALUES (106,018060,37,'Miles','abrogating','Simla',''); +INSERT INTO t2 VALUES (107,018061,37,'trimmings','sorters','reporters',''); +INSERT INTO t2 VALUES (108,018101,37,'tragedies','Conley','Dutchman','FAS'); +INSERT INTO t2 VALUES (109,018102,37,'skulking','lectured','descendants','FAS'); +INSERT INTO t2 VALUES (110,018103,37,'flint','Abraham','groupings','FAS'); +INSERT INTO t2 VALUES (111,018104,37,'flopping','Hawaii','dissociate',''); +INSERT INTO t2 VALUES (112,018201,37,'relaxing','cage','coexist','W'); +INSERT INTO t2 VALUES (113,018202,37,'offload','hushes','Beebe',''); +INSERT INTO t2 VALUES (114,018402,37,'suites','Simla','Taoism',''); +INSERT INTO t2 VALUES (115,018403,37,'lists','reporters','Connally',''); +INSERT INTO t2 VALUES (116,018404,37,'animized','Dutchman','fetched','FAS'); +INSERT INTO t2 VALUES (117,018405,37,'multilayer','descendants','checkpoints','FAS'); +INSERT INTO t2 VALUES (118,018406,37,'standardizes','groupings','rusting',''); +INSERT INTO t2 VALUES (119,018409,37,'Judas','dissociate','galling',''); +INSERT INTO t2 VALUES (120,018601,37,'vacuuming','coexist','obliterates',''); +INSERT INTO t2 VALUES (121,018602,37,'dentally','Beebe','traitor',''); +INSERT INTO t2 VALUES (122,018603,37,'humanness','Taoism','resumes','FAS'); +INSERT INTO t2 VALUES (123,018801,37,'inch','Connally','analyzable','FAS'); +INSERT INTO t2 VALUES (124,018802,37,'Weissmuller','fetched','terminator','FAS'); +INSERT INTO t2 VALUES (125,018803,37,'irresponsibly','checkpoints','gritty','FAS'); +INSERT INTO t2 VALUES (126,018804,37,'luckily','rusting','firearm','W'); +INSERT INTO t2 VALUES (127,018805,37,'culled','galling','minima',''); +INSERT INTO t2 VALUES (128,018806,37,'medical','obliterates','Selfridge',''); +INSERT INTO t2 VALUES (129,018807,37,'bloodbath','traitor','disable',''); +INSERT INTO t2 VALUES (130,018808,37,'subschema','resumes','witchcraft','W'); +INSERT INTO t2 VALUES (131,018809,37,'animals','analyzable','betroth','W'); +INSERT INTO t2 VALUES (132,018810,37,'Micronesia','terminator','Manhattanize',''); +INSERT INTO t2 VALUES (133,018811,37,'repetitions','gritty','imprint',''); +INSERT INTO t2 VALUES (134,018812,37,'Antares','firearm','peeked',''); +INSERT INTO t2 VALUES (135,019101,37,'ventilate','minima','swelling',''); +INSERT INTO t2 VALUES (136,019102,37,'pityingly','Selfridge','interrelationships','W'); +INSERT INTO t2 VALUES (137,019103,37,'interdependent','disable','riser',''); +INSERT INTO t2 VALUES (138,019201,37,'Graves','witchcraft','Gandhian','W'); +INSERT INTO t2 VALUES (139,030501,37,'neonatal','betroth','peacock','A'); +INSERT INTO t2 VALUES (140,030502,50,'scribbled','Manhattanize','bee','A'); +INSERT INTO t2 VALUES (141,030503,37,'chafe','imprint','kanji',''); +INSERT INTO t2 VALUES (142,030504,37,'honoring','peeked','dental',''); +INSERT INTO t2 VALUES (143,031901,37,'realtor','swelling','scarf','FAS'); +INSERT INTO t2 VALUES (144,036001,37,'elite','interrelationships','chasm','A'); +INSERT INTO t2 VALUES (145,036002,37,'funereal','riser','insolence','A'); +INSERT INTO t2 VALUES (146,036004,37,'abrogating','Gandhian','syndicate',''); +INSERT INTO t2 VALUES (147,036005,37,'sorters','peacock','alike',''); +INSERT INTO t2 VALUES (148,038001,37,'Conley','bee','imperial','A'); +INSERT INTO t2 VALUES (149,038002,37,'lectured','kanji','convulsion','A'); +INSERT INTO t2 VALUES (150,038003,37,'Abraham','dental','railway','A'); +INSERT INTO t2 VALUES (151,038004,37,'Hawaii','scarf','validate','A'); +INSERT INTO t2 VALUES (152,038005,37,'cage','chasm','normalizes','A'); +INSERT INTO t2 VALUES (153,038006,37,'hushes','insolence','comprehensive',''); +INSERT INTO t2 VALUES (154,038007,37,'Simla','syndicate','chewing',''); +INSERT INTO t2 VALUES (155,038008,37,'reporters','alike','denizen',''); +INSERT INTO t2 VALUES (156,038009,37,'Dutchman','imperial','schemer',''); +INSERT INTO t2 VALUES (157,038010,37,'descendants','convulsion','chronicle',''); +INSERT INTO t2 VALUES (158,038011,37,'groupings','railway','Kline',''); +INSERT INTO t2 VALUES (159,038012,37,'dissociate','validate','Anatole',''); +INSERT INTO t2 VALUES (160,038013,37,'coexist','normalizes','partridges',''); +INSERT INTO t2 VALUES (161,038014,37,'Beebe','comprehensive','brunch',''); +INSERT INTO t2 VALUES (162,038015,37,'Taoism','chewing','recruited',''); +INSERT INTO t2 VALUES (163,038016,37,'Connally','denizen','dimensions','W'); +INSERT INTO t2 VALUES (164,038017,37,'fetched','schemer','Chicana','W'); +INSERT INTO t2 VALUES (165,038018,37,'checkpoints','chronicle','announced',''); +INSERT INTO t2 VALUES (166,038101,37,'rusting','Kline','praised','FAS'); +INSERT INTO t2 VALUES (167,038102,37,'galling','Anatole','employing',''); +INSERT INTO t2 VALUES (168,038103,37,'obliterates','partridges','linear',''); +INSERT INTO t2 VALUES (169,038104,37,'traitor','brunch','quagmire',''); +INSERT INTO t2 VALUES (170,038201,37,'resumes','recruited','western','A'); +INSERT INTO t2 VALUES (171,038202,37,'analyzable','dimensions','relishing',''); +INSERT INTO t2 VALUES (172,038203,37,'terminator','Chicana','serving','A'); +INSERT INTO t2 VALUES (173,038204,37,'gritty','announced','scheduling',''); +INSERT INTO t2 VALUES (174,038205,37,'firearm','praised','lore',''); +INSERT INTO t2 VALUES (175,038206,37,'minima','employing','eventful',''); +INSERT INTO t2 VALUES (176,038208,37,'Selfridge','linear','arteriole','A'); +INSERT INTO t2 VALUES (177,042801,37,'disable','quagmire','disentangle',''); +INSERT INTO t2 VALUES (178,042802,37,'witchcraft','western','cured','A'); +INSERT INTO t2 VALUES (179,046101,37,'betroth','relishing','Fenton','W'); +INSERT INTO t2 VALUES (180,048001,37,'Manhattanize','serving','avoidable','A'); +INSERT INTO t2 VALUES (181,048002,37,'imprint','scheduling','drains','A'); +INSERT INTO t2 VALUES (182,048003,37,'peeked','lore','detectably','FAS'); +INSERT INTO t2 VALUES (183,048004,37,'swelling','eventful','husky',''); +INSERT INTO t2 VALUES (184,048005,37,'interrelationships','arteriole','impelling',''); +INSERT INTO t2 VALUES (185,048006,37,'riser','disentangle','undoes',''); +INSERT INTO t2 VALUES (186,048007,37,'Gandhian','cured','evened',''); +INSERT INTO t2 VALUES (187,048008,37,'peacock','Fenton','squeezes',''); +INSERT INTO t2 VALUES (188,048101,37,'bee','avoidable','destroyer','FAS'); +INSERT INTO t2 VALUES (189,048102,37,'kanji','drains','rudeness',''); +INSERT INTO t2 VALUES (190,048201,37,'dental','detectably','beaner','FAS'); +INSERT INTO t2 VALUES (191,048202,37,'scarf','husky','boorish',''); +INSERT INTO t2 VALUES (192,048203,37,'chasm','impelling','Everhart',''); +INSERT INTO t2 VALUES (193,048204,37,'insolence','undoes','encompass','A'); +INSERT INTO t2 VALUES (194,048205,37,'syndicate','evened','mushrooms',''); +INSERT INTO t2 VALUES (195,048301,37,'alike','squeezes','Alison','A'); +INSERT INTO t2 VALUES (196,048302,37,'imperial','destroyer','externally','FAS'); +INSERT INTO t2 VALUES (197,048303,37,'convulsion','rudeness','pellagra',''); +INSERT INTO t2 VALUES (198,048304,37,'railway','beaner','cult',''); +INSERT INTO t2 VALUES (199,048305,37,'validate','boorish','creek','A'); +INSERT INTO t2 VALUES (200,048401,37,'normalizes','Everhart','Huffman',''); +INSERT INTO t2 VALUES (201,048402,37,'comprehensive','encompass','Majorca','FAS'); +INSERT INTO t2 VALUES (202,048403,37,'chewing','mushrooms','governing','A'); +INSERT INTO t2 VALUES (203,048404,37,'denizen','Alison','gadfly','FAS'); +INSERT INTO t2 VALUES (204,048405,37,'schemer','externally','reassigned','FAS'); +INSERT INTO t2 VALUES (205,048406,37,'chronicle','pellagra','intentness','W'); +INSERT INTO t2 VALUES (206,048407,37,'Kline','cult','craziness',''); +INSERT INTO t2 VALUES (207,048408,37,'Anatole','creek','psychic',''); +INSERT INTO t2 VALUES (208,048409,37,'partridges','Huffman','squabbled',''); +INSERT INTO t2 VALUES (209,048410,37,'brunch','Majorca','burlesque',''); +INSERT INTO t2 VALUES (210,048411,37,'recruited','governing','capped',''); +INSERT INTO t2 VALUES (211,048412,37,'dimensions','gadfly','extracted','A'); +INSERT INTO t2 VALUES (212,048413,37,'Chicana','reassigned','DiMaggio',''); +INSERT INTO t2 VALUES (213,048601,37,'announced','intentness','exclamation','FAS'); +INSERT INTO t2 VALUES (214,048602,37,'praised','craziness','subdirectory',''); +INSERT INTO t2 VALUES (215,048603,37,'employing','psychic','fangs',''); +INSERT INTO t2 VALUES (216,048604,37,'linear','squabbled','buyer','A'); +INSERT INTO t2 VALUES (217,048801,37,'quagmire','burlesque','pithing','A'); +INSERT INTO t2 VALUES (218,050901,37,'western','capped','transistorizing','A'); +INSERT INTO t2 VALUES (219,051201,37,'relishing','extracted','nonbiodegradable',''); +INSERT INTO t2 VALUES (220,056002,37,'serving','DiMaggio','dislocate',''); +INSERT INTO t2 VALUES (221,056003,37,'scheduling','exclamation','monochromatic','FAS'); +INSERT INTO t2 VALUES (222,056004,37,'lore','subdirectory','batting',''); +INSERT INTO t2 VALUES (223,056102,37,'eventful','fangs','postcondition','A'); +INSERT INTO t2 VALUES (224,056203,37,'arteriole','buyer','catalog','FAS'); +INSERT INTO t2 VALUES (225,056204,37,'disentangle','pithing','Remus',''); +INSERT INTO t2 VALUES (226,058003,37,'cured','transistorizing','devices','A'); +INSERT INTO t2 VALUES (227,058004,37,'Fenton','nonbiodegradable','bike','A'); +INSERT INTO t2 VALUES (228,058005,37,'avoidable','dislocate','qualify',''); +INSERT INTO t2 VALUES (229,058006,37,'drains','monochromatic','detained',''); +INSERT INTO t2 VALUES (230,058007,37,'detectably','batting','commended',''); +INSERT INTO t2 VALUES (231,058101,37,'husky','postcondition','civilize',''); +INSERT INTO t2 VALUES (232,058102,37,'impelling','catalog','Elmhurst',''); +INSERT INTO t2 VALUES (233,058103,37,'undoes','Remus','anesthetizing',''); +INSERT INTO t2 VALUES (234,058105,37,'evened','devices','deaf',''); +INSERT INTO t2 VALUES (235,058111,37,'squeezes','bike','Brigham',''); +INSERT INTO t2 VALUES (236,058112,37,'destroyer','qualify','title',''); +INSERT INTO t2 VALUES (237,058113,37,'rudeness','detained','coarse',''); +INSERT INTO t2 VALUES (238,058114,37,'beaner','commended','combinations',''); +INSERT INTO t2 VALUES (239,058115,37,'boorish','civilize','grayness',''); +INSERT INTO t2 VALUES (240,058116,37,'Everhart','Elmhurst','innumerable','FAS'); +INSERT INTO t2 VALUES (241,058117,37,'encompass','anesthetizing','Caroline','A'); +INSERT INTO t2 VALUES (242,058118,37,'mushrooms','deaf','fatty','FAS'); +INSERT INTO t2 VALUES (243,058119,37,'Alison','Brigham','eastbound',''); +INSERT INTO t2 VALUES (244,058120,37,'externally','title','inexperienced',''); +INSERT INTO t2 VALUES (245,058121,37,'pellagra','coarse','hoarder','A'); +INSERT INTO t2 VALUES (246,058122,37,'cult','combinations','scotch','W'); +INSERT INTO t2 VALUES (247,058123,37,'creek','grayness','passport','A'); +INSERT INTO t2 VALUES (248,058124,37,'Huffman','innumerable','strategic','FAS'); +INSERT INTO t2 VALUES (249,058125,37,'Majorca','Caroline','gated',''); +INSERT INTO t2 VALUES (250,058126,37,'governing','fatty','flog',''); +INSERT INTO t2 VALUES (251,058127,37,'gadfly','eastbound','Pipestone',''); +INSERT INTO t2 VALUES (252,058128,37,'reassigned','inexperienced','Dar',''); +INSERT INTO t2 VALUES (253,058201,37,'intentness','hoarder','Corcoran',''); +INSERT INTO t2 VALUES (254,058202,37,'craziness','scotch','flyers','A'); +INSERT INTO t2 VALUES (255,058303,37,'psychic','passport','competitions','W'); +INSERT INTO t2 VALUES (256,058304,37,'squabbled','strategic','suppliers','FAS'); +INSERT INTO t2 VALUES (257,058602,37,'burlesque','gated','skips',''); +INSERT INTO t2 VALUES (258,058603,37,'capped','flog','institutes',''); +INSERT INTO t2 VALUES (259,058604,37,'extracted','Pipestone','troop','A'); +INSERT INTO t2 VALUES (260,058605,37,'DiMaggio','Dar','connective','W'); +INSERT INTO t2 VALUES (261,058606,37,'exclamation','Corcoran','denies',''); +INSERT INTO t2 VALUES (262,058607,37,'subdirectory','flyers','polka',''); +INSERT INTO t2 VALUES (263,060401,36,'fangs','competitions','observations','FAS'); +INSERT INTO t2 VALUES (264,061701,36,'buyer','suppliers','askers',''); +INSERT INTO t2 VALUES (265,066201,36,'pithing','skips','homeless','FAS'); +INSERT INTO t2 VALUES (266,066501,36,'transistorizing','institutes','Anna',''); +INSERT INTO t2 VALUES (267,068001,36,'nonbiodegradable','troop','subdirectories','W'); +INSERT INTO t2 VALUES (268,068002,36,'dislocate','connective','decaying','FAS'); +INSERT INTO t2 VALUES (269,068005,36,'monochromatic','denies','outwitting','W'); +INSERT INTO t2 VALUES (270,068006,36,'batting','polka','Harpy','W'); +INSERT INTO t2 VALUES (271,068007,36,'postcondition','observations','crazed',''); +INSERT INTO t2 VALUES (272,068008,36,'catalog','askers','suffocate',''); +INSERT INTO t2 VALUES (273,068009,36,'Remus','homeless','provers','FAS'); +INSERT INTO t2 VALUES (274,068010,36,'devices','Anna','technically',''); +INSERT INTO t2 VALUES (275,068011,36,'bike','subdirectories','Franklinizations',''); +INSERT INTO t2 VALUES (276,068202,36,'qualify','decaying','considered',''); +INSERT INTO t2 VALUES (277,068302,36,'detained','outwitting','tinnily',''); +INSERT INTO t2 VALUES (278,068303,36,'commended','Harpy','uninterruptedly',''); +INSERT INTO t2 VALUES (279,068401,36,'civilize','crazed','whistled','A'); +INSERT INTO t2 VALUES (280,068501,36,'Elmhurst','suffocate','automate',''); +INSERT INTO t2 VALUES (281,068502,36,'anesthetizing','provers','gutting','W'); +INSERT INTO t2 VALUES (282,068503,36,'deaf','technically','surreptitious',''); +INSERT INTO t2 VALUES (283,068602,36,'Brigham','Franklinizations','Choctaw',''); +INSERT INTO t2 VALUES (284,068603,36,'title','considered','cooks',''); +INSERT INTO t2 VALUES (285,068701,36,'coarse','tinnily','millivolt','FAS'); +INSERT INTO t2 VALUES (286,068702,36,'combinations','uninterruptedly','counterpoise',''); +INSERT INTO t2 VALUES (287,068703,36,'grayness','whistled','Gothicism',''); +INSERT INTO t2 VALUES (288,076001,36,'innumerable','automate','feminine',''); +INSERT INTO t2 VALUES (289,076002,36,'Caroline','gutting','metaphysically','W'); +INSERT INTO t2 VALUES (290,076101,36,'fatty','surreptitious','sanding','A'); +INSERT INTO t2 VALUES (291,076102,36,'eastbound','Choctaw','contributorily',''); +INSERT INTO t2 VALUES (292,076103,36,'inexperienced','cooks','receivers','FAS'); +INSERT INTO t2 VALUES (293,076302,36,'hoarder','millivolt','adjourn',''); +INSERT INTO t2 VALUES (294,076303,36,'scotch','counterpoise','straggled','A'); +INSERT INTO t2 VALUES (295,076304,36,'passport','Gothicism','druggists',''); +INSERT INTO t2 VALUES (296,076305,36,'strategic','feminine','thanking','FAS'); +INSERT INTO t2 VALUES (297,076306,36,'gated','metaphysically','ostrich',''); +INSERT INTO t2 VALUES (298,076307,36,'flog','sanding','hopelessness','FAS'); +INSERT INTO t2 VALUES (299,076402,36,'Pipestone','contributorily','Eurydice',''); +INSERT INTO t2 VALUES (300,076501,36,'Dar','receivers','excitation','W'); +INSERT INTO t2 VALUES (301,076502,36,'Corcoran','adjourn','presumes','FAS'); +INSERT INTO t2 VALUES (302,076701,36,'flyers','straggled','imaginable','FAS'); +INSERT INTO t2 VALUES (303,078001,36,'competitions','druggists','concoct','W'); +INSERT INTO t2 VALUES (304,078002,36,'suppliers','thanking','peering','W'); +INSERT INTO t2 VALUES (305,078003,36,'skips','ostrich','Phelps','FAS'); +INSERT INTO t2 VALUES (306,078004,36,'institutes','hopelessness','ferociousness','FAS'); +INSERT INTO t2 VALUES (307,078005,36,'troop','Eurydice','sentences',''); +INSERT INTO t2 VALUES (308,078006,36,'connective','excitation','unlocks',''); +INSERT INTO t2 VALUES (309,078007,36,'denies','presumes','engrossing','W'); +INSERT INTO t2 VALUES (310,078008,36,'polka','imaginable','Ruth',''); +INSERT INTO t2 VALUES (311,078101,36,'observations','concoct','tying',''); +INSERT INTO t2 VALUES (312,078103,36,'askers','peering','exclaimers',''); +INSERT INTO t2 VALUES (313,078104,36,'homeless','Phelps','synergy',''); +INSERT INTO t2 VALUES (314,078105,36,'Anna','ferociousness','Huey','W'); +INSERT INTO t2 VALUES (315,082101,36,'subdirectories','sentences','merging',''); +INSERT INTO t2 VALUES (316,083401,36,'decaying','unlocks','judges','A'); +INSERT INTO t2 VALUES (317,084001,36,'outwitting','engrossing','Shylock','W'); +INSERT INTO t2 VALUES (318,084002,36,'Harpy','Ruth','Miltonism',''); +INSERT INTO t2 VALUES (319,086001,36,'crazed','tying','hen','W'); +INSERT INTO t2 VALUES (320,086102,36,'suffocate','exclaimers','honeybee','FAS'); +INSERT INTO t2 VALUES (321,086201,36,'provers','synergy','towers',''); +INSERT INTO t2 VALUES (322,088001,36,'technically','Huey','dilutes','W'); +INSERT INTO t2 VALUES (323,088002,36,'Franklinizations','merging','numerals','FAS'); +INSERT INTO t2 VALUES (324,088003,36,'considered','judges','democracy','FAS'); +INSERT INTO t2 VALUES (325,088004,36,'tinnily','Shylock','Ibero-',''); +INSERT INTO t2 VALUES (326,088101,36,'uninterruptedly','Miltonism','invalids',''); +INSERT INTO t2 VALUES (327,088102,36,'whistled','hen','behavior',''); +INSERT INTO t2 VALUES (328,088103,36,'automate','honeybee','accruing',''); +INSERT INTO t2 VALUES (329,088104,36,'gutting','towers','relics','A'); +INSERT INTO t2 VALUES (330,088105,36,'surreptitious','dilutes','rackets',''); +INSERT INTO t2 VALUES (331,088106,36,'Choctaw','numerals','Fischbein','W'); +INSERT INTO t2 VALUES (332,088201,36,'cooks','democracy','phony','W'); +INSERT INTO t2 VALUES (333,088203,36,'millivolt','Ibero-','cross','FAS'); +INSERT INTO t2 VALUES (334,088204,36,'counterpoise','invalids','cleanup',''); +INSERT INTO t2 VALUES (335,088302,37,'Gothicism','behavior','conspirator',''); +INSERT INTO t2 VALUES (336,088303,37,'feminine','accruing','label','FAS'); +INSERT INTO t2 VALUES (337,088305,37,'metaphysically','relics','university',''); +INSERT INTO t2 VALUES (338,088402,37,'sanding','rackets','cleansed','FAS'); +INSERT INTO t2 VALUES (339,088501,36,'contributorily','Fischbein','ballgown',''); +INSERT INTO t2 VALUES (340,088502,36,'receivers','phony','starlet',''); +INSERT INTO t2 VALUES (341,088503,36,'adjourn','cross','aqueous',''); +INSERT INTO t2 VALUES (342,098001,58,'straggled','cleanup','portrayal','A'); +INSERT INTO t2 VALUES (343,098002,58,'druggists','conspirator','despising','W'); +INSERT INTO t2 VALUES (344,098003,58,'thanking','label','distort','W'); +INSERT INTO t2 VALUES (345,098004,58,'ostrich','university','palmed',''); +INSERT INTO t2 VALUES (346,098005,58,'hopelessness','cleansed','faced',''); +INSERT INTO t2 VALUES (347,098006,58,'Eurydice','ballgown','silverware',''); +INSERT INTO t2 VALUES (348,141903,29,'excitation','starlet','assessor',''); +INSERT INTO t2 VALUES (349,098008,58,'presumes','aqueous','spiders',''); +INSERT INTO t2 VALUES (350,098009,58,'imaginable','portrayal','artificially',''); +INSERT INTO t2 VALUES (351,098010,58,'concoct','despising','reminiscence',''); +INSERT INTO t2 VALUES (352,098011,58,'peering','distort','Mexican',''); +INSERT INTO t2 VALUES (353,098012,58,'Phelps','palmed','obnoxious',''); +INSERT INTO t2 VALUES (354,098013,58,'ferociousness','faced','fragile',''); +INSERT INTO t2 VALUES (355,098014,58,'sentences','silverware','apprehensible',''); +INSERT INTO t2 VALUES (356,098015,58,'unlocks','assessor','births',''); +INSERT INTO t2 VALUES (357,098016,58,'engrossing','spiders','garages',''); +INSERT INTO t2 VALUES (358,098017,58,'Ruth','artificially','panty',''); +INSERT INTO t2 VALUES (359,098018,58,'tying','reminiscence','anteater',''); +INSERT INTO t2 VALUES (360,098019,58,'exclaimers','Mexican','displacement','A'); +INSERT INTO t2 VALUES (361,098020,58,'synergy','obnoxious','drovers','A'); +INSERT INTO t2 VALUES (362,098021,58,'Huey','fragile','patenting','A'); +INSERT INTO t2 VALUES (363,098022,58,'merging','apprehensible','far','A'); +INSERT INTO t2 VALUES (364,098023,58,'judges','births','shrieks',''); +INSERT INTO t2 VALUES (365,098024,58,'Shylock','garages','aligning','W'); +INSERT INTO t2 VALUES (366,098025,37,'Miltonism','panty','pragmatism',''); +INSERT INTO t2 VALUES (367,106001,36,'hen','anteater','fevers','W'); +INSERT INTO t2 VALUES (368,108001,36,'honeybee','displacement','reexamines','A'); +INSERT INTO t2 VALUES (369,108002,36,'towers','drovers','occupancies',''); +INSERT INTO t2 VALUES (370,108003,36,'dilutes','patenting','sweats','FAS'); +INSERT INTO t2 VALUES (371,108004,36,'numerals','far','modulators',''); +INSERT INTO t2 VALUES (372,108005,36,'democracy','shrieks','demand','W'); +INSERT INTO t2 VALUES (373,108007,36,'Ibero-','aligning','Madeira',''); +INSERT INTO t2 VALUES (374,108008,36,'invalids','pragmatism','Viennese','W'); +INSERT INTO t2 VALUES (375,108009,36,'behavior','fevers','chillier','W'); +INSERT INTO t2 VALUES (376,108010,36,'accruing','reexamines','wildcats','FAS'); +INSERT INTO t2 VALUES (377,108011,36,'relics','occupancies','gentle',''); +INSERT INTO t2 VALUES (378,108012,36,'rackets','sweats','Angles','W'); +INSERT INTO t2 VALUES (379,108101,36,'Fischbein','modulators','accuracies',''); +INSERT INTO t2 VALUES (380,108102,36,'phony','demand','toggle',''); +INSERT INTO t2 VALUES (381,108103,36,'cross','Madeira','Mendelssohn','W'); +INSERT INTO t2 VALUES (382,108111,50,'cleanup','Viennese','behaviorally',''); +INSERT INTO t2 VALUES (383,108105,36,'conspirator','chillier','Rochford',''); +INSERT INTO t2 VALUES (384,108106,36,'label','wildcats','mirror','W'); +INSERT INTO t2 VALUES (385,108107,36,'university','gentle','Modula',''); +INSERT INTO t2 VALUES (386,108108,50,'cleansed','Angles','clobbering',''); +INSERT INTO t2 VALUES (387,108109,36,'ballgown','accuracies','chronography',''); +INSERT INTO t2 VALUES (388,108110,36,'starlet','toggle','Eskimoizeds',''); +INSERT INTO t2 VALUES (389,108201,36,'aqueous','Mendelssohn','British','W'); +INSERT INTO t2 VALUES (390,108202,36,'portrayal','behaviorally','pitfalls',''); +INSERT INTO t2 VALUES (391,108203,36,'despising','Rochford','verify','W'); +INSERT INTO t2 VALUES (392,108204,36,'distort','mirror','scatter','FAS'); +INSERT INTO t2 VALUES (393,108205,36,'palmed','Modula','Aztecan',''); +INSERT INTO t2 VALUES (394,108301,36,'faced','clobbering','acuity','W'); +INSERT INTO t2 VALUES (395,108302,36,'silverware','chronography','sinking','W'); +INSERT INTO t2 VALUES (396,112101,36,'assessor','Eskimoizeds','beasts','FAS'); +INSERT INTO t2 VALUES (397,112102,36,'spiders','British','Witt','W'); +INSERT INTO t2 VALUES (398,113701,36,'artificially','pitfalls','physicists','FAS'); +INSERT INTO t2 VALUES (399,116001,36,'reminiscence','verify','folksong','A'); +INSERT INTO t2 VALUES (400,116201,36,'Mexican','scatter','strokes','FAS'); +INSERT INTO t2 VALUES (401,116301,36,'obnoxious','Aztecan','crowder',''); +INSERT INTO t2 VALUES (402,116302,36,'fragile','acuity','merry',''); +INSERT INTO t2 VALUES (403,116601,36,'apprehensible','sinking','cadenced',''); +INSERT INTO t2 VALUES (404,116602,36,'births','beasts','alimony','A'); +INSERT INTO t2 VALUES (405,116603,36,'garages','Witt','principled','A'); +INSERT INTO t2 VALUES (406,116701,36,'panty','physicists','golfing',''); +INSERT INTO t2 VALUES (407,116702,36,'anteater','folksong','undiscovered',''); +INSERT INTO t2 VALUES (408,118001,36,'displacement','strokes','irritates',''); +INSERT INTO t2 VALUES (409,118002,36,'drovers','crowder','patriots','A'); +INSERT INTO t2 VALUES (410,118003,36,'patenting','merry','rooms','FAS'); +INSERT INTO t2 VALUES (411,118004,36,'far','cadenced','towering','W'); +INSERT INTO t2 VALUES (412,118005,36,'shrieks','alimony','displease',''); +INSERT INTO t2 VALUES (413,118006,36,'aligning','principled','photosensitive',''); +INSERT INTO t2 VALUES (414,118007,36,'pragmatism','golfing','inking',''); +INSERT INTO t2 VALUES (415,118008,36,'fevers','undiscovered','gainers',''); +INSERT INTO t2 VALUES (416,118101,36,'reexamines','irritates','leaning','A'); +INSERT INTO t2 VALUES (417,118102,36,'occupancies','patriots','hydrant','A'); +INSERT INTO t2 VALUES (418,118103,36,'sweats','rooms','preserve',''); +INSERT INTO t2 VALUES (419,118202,36,'modulators','towering','blinded','A'); +INSERT INTO t2 VALUES (420,118203,36,'demand','displease','interactions','A'); +INSERT INTO t2 VALUES (421,118204,36,'Madeira','photosensitive','Barry',''); +INSERT INTO t2 VALUES (422,118302,36,'Viennese','inking','whiteness','A'); +INSERT INTO t2 VALUES (423,118304,36,'chillier','gainers','pastimes','W'); +INSERT INTO t2 VALUES (424,118305,36,'wildcats','leaning','Edenization',''); +INSERT INTO t2 VALUES (425,118306,36,'gentle','hydrant','Muscat',''); +INSERT INTO t2 VALUES (426,118307,36,'Angles','preserve','assassinated',''); +INSERT INTO t2 VALUES (427,123101,36,'accuracies','blinded','labeled',''); +INSERT INTO t2 VALUES (428,123102,36,'toggle','interactions','glacial','A'); +INSERT INTO t2 VALUES (429,123301,36,'Mendelssohn','Barry','implied','W'); +INSERT INTO t2 VALUES (430,126001,36,'behaviorally','whiteness','bibliographies','W'); +INSERT INTO t2 VALUES (431,126002,36,'Rochford','pastimes','Buchanan',''); +INSERT INTO t2 VALUES (432,126003,36,'mirror','Edenization','forgivably','FAS'); +INSERT INTO t2 VALUES (433,126101,36,'Modula','Muscat','innuendo','A'); +INSERT INTO t2 VALUES (434,126301,36,'clobbering','assassinated','den','FAS'); +INSERT INTO t2 VALUES (435,126302,36,'chronography','labeled','submarines','W'); +INSERT INTO t2 VALUES (436,126402,36,'Eskimoizeds','glacial','mouthful','A'); +INSERT INTO t2 VALUES (437,126601,36,'British','implied','expiring',''); +INSERT INTO t2 VALUES (438,126602,36,'pitfalls','bibliographies','unfulfilled','FAS'); +INSERT INTO t2 VALUES (439,126702,36,'verify','Buchanan','precession',''); +INSERT INTO t2 VALUES (440,128001,36,'scatter','forgivably','nullified',''); +INSERT INTO t2 VALUES (441,128002,36,'Aztecan','innuendo','affects',''); +INSERT INTO t2 VALUES (442,128003,36,'acuity','den','Cynthia',''); +INSERT INTO t2 VALUES (443,128004,36,'sinking','submarines','Chablis','A'); +INSERT INTO t2 VALUES (444,128005,36,'beasts','mouthful','betterments','FAS'); +INSERT INTO t2 VALUES (445,128007,36,'Witt','expiring','advertising',''); +INSERT INTO t2 VALUES (446,128008,36,'physicists','unfulfilled','rubies','A'); +INSERT INTO t2 VALUES (447,128009,36,'folksong','precession','southwest','FAS'); +INSERT INTO t2 VALUES (448,128010,36,'strokes','nullified','superstitious','A'); +INSERT INTO t2 VALUES (449,128011,36,'crowder','affects','tabernacle','W'); +INSERT INTO t2 VALUES (450,128012,36,'merry','Cynthia','silk','A'); +INSERT INTO t2 VALUES (451,128013,36,'cadenced','Chablis','handsomest','A'); +INSERT INTO t2 VALUES (452,128014,36,'alimony','betterments','Persian','A'); +INSERT INTO t2 VALUES (453,128015,36,'principled','advertising','analog','W'); +INSERT INTO t2 VALUES (454,128016,36,'golfing','rubies','complex','W'); +INSERT INTO t2 VALUES (455,128017,36,'undiscovered','southwest','Taoist',''); +INSERT INTO t2 VALUES (456,128018,36,'irritates','superstitious','suspend',''); +INSERT INTO t2 VALUES (457,128019,36,'patriots','tabernacle','relegated',''); +INSERT INTO t2 VALUES (458,128020,36,'rooms','silk','awesome','W'); +INSERT INTO t2 VALUES (459,128021,36,'towering','handsomest','Bruxelles',''); +INSERT INTO t2 VALUES (460,128022,36,'displease','Persian','imprecisely','A'); +INSERT INTO t2 VALUES (461,128023,36,'photosensitive','analog','televise',''); +INSERT INTO t2 VALUES (462,128101,36,'inking','complex','braking',''); +INSERT INTO t2 VALUES (463,128102,36,'gainers','Taoist','true','FAS'); +INSERT INTO t2 VALUES (464,128103,36,'leaning','suspend','disappointing','FAS'); +INSERT INTO t2 VALUES (465,128104,36,'hydrant','relegated','navally','W'); +INSERT INTO t2 VALUES (466,128106,36,'preserve','awesome','circus',''); +INSERT INTO t2 VALUES (467,128107,36,'blinded','Bruxelles','beetles',''); +INSERT INTO t2 VALUES (468,128108,36,'interactions','imprecisely','trumps',''); +INSERT INTO t2 VALUES (469,128202,36,'Barry','televise','fourscore','W'); +INSERT INTO t2 VALUES (470,128203,36,'whiteness','braking','Blackfoots',''); +INSERT INTO t2 VALUES (471,128301,36,'pastimes','true','Grady',''); +INSERT INTO t2 VALUES (472,128302,36,'Edenization','disappointing','quiets','FAS'); +INSERT INTO t2 VALUES (473,128303,36,'Muscat','navally','floundered','FAS'); +INSERT INTO t2 VALUES (474,128304,36,'assassinated','circus','profundity','W'); +INSERT INTO t2 VALUES (475,128305,36,'labeled','beetles','Garrisonian','W'); +INSERT INTO t2 VALUES (476,128307,36,'glacial','trumps','Strauss',''); +INSERT INTO t2 VALUES (477,128401,36,'implied','fourscore','cemented','FAS'); +INSERT INTO t2 VALUES (478,128502,36,'bibliographies','Blackfoots','contrition','A'); +INSERT INTO t2 VALUES (479,128503,36,'Buchanan','Grady','mutations',''); +INSERT INTO t2 VALUES (480,128504,36,'forgivably','quiets','exhibits','W'); +INSERT INTO t2 VALUES (481,128505,36,'innuendo','floundered','tits',''); +INSERT INTO t2 VALUES (482,128601,36,'den','profundity','mate','A'); +INSERT INTO t2 VALUES (483,128603,36,'submarines','Garrisonian','arches',''); +INSERT INTO t2 VALUES (484,128604,36,'mouthful','Strauss','Moll',''); +INSERT INTO t2 VALUES (485,128702,36,'expiring','cemented','ropers',''); +INSERT INTO t2 VALUES (486,128703,36,'unfulfilled','contrition','bombast',''); +INSERT INTO t2 VALUES (487,128704,36,'precession','mutations','difficultly','A'); +INSERT INTO t2 VALUES (488,138001,36,'nullified','exhibits','adsorption',''); +INSERT INTO t2 VALUES (489,138002,36,'affects','tits','definiteness','FAS'); +INSERT INTO t2 VALUES (490,138003,36,'Cynthia','mate','cultivation','A'); +INSERT INTO t2 VALUES (491,138004,36,'Chablis','arches','heals','A'); +INSERT INTO t2 VALUES (492,138005,36,'betterments','Moll','Heusen','W'); +INSERT INTO t2 VALUES (493,138006,36,'advertising','ropers','target','FAS'); +INSERT INTO t2 VALUES (494,138007,36,'rubies','bombast','cited','A'); +INSERT INTO t2 VALUES (495,138008,36,'southwest','difficultly','congresswoman','W'); +INSERT INTO t2 VALUES (496,138009,36,'superstitious','adsorption','Katherine',''); +INSERT INTO t2 VALUES (497,138102,36,'tabernacle','definiteness','titter','A'); +INSERT INTO t2 VALUES (498,138103,36,'silk','cultivation','aspire','A'); +INSERT INTO t2 VALUES (499,138104,36,'handsomest','heals','Mardis',''); +INSERT INTO t2 VALUES (500,138105,36,'Persian','Heusen','Nadia','W'); +INSERT INTO t2 VALUES (501,138201,36,'analog','target','estimating','FAS'); +INSERT INTO t2 VALUES (502,138302,36,'complex','cited','stuck','A'); +INSERT INTO t2 VALUES (503,138303,36,'Taoist','congresswoman','fifteenth','A'); +INSERT INTO t2 VALUES (504,138304,36,'suspend','Katherine','Colombo',''); +INSERT INTO t2 VALUES (505,138401,29,'relegated','titter','survey','A'); +INSERT INTO t2 VALUES (506,140102,29,'awesome','aspire','staffing',''); +INSERT INTO t2 VALUES (507,140103,29,'Bruxelles','Mardis','obtain',''); +INSERT INTO t2 VALUES (508,140104,29,'imprecisely','Nadia','loaded',''); +INSERT INTO t2 VALUES (509,140105,29,'televise','estimating','slaughtered',''); +INSERT INTO t2 VALUES (510,140201,29,'braking','stuck','lights','A'); +INSERT INTO t2 VALUES (511,140701,29,'true','fifteenth','circumference',''); +INSERT INTO t2 VALUES (512,141501,29,'disappointing','Colombo','dull','A'); +INSERT INTO t2 VALUES (513,141502,29,'navally','survey','weekly','A'); +INSERT INTO t2 VALUES (514,141901,29,'circus','staffing','wetness',''); +INSERT INTO t2 VALUES (515,141902,29,'beetles','obtain','visualized',''); +INSERT INTO t2 VALUES (516,142101,29,'trumps','loaded','Tannenbaum',''); +INSERT INTO t2 VALUES (517,142102,29,'fourscore','slaughtered','moribund',''); +INSERT INTO t2 VALUES (518,142103,29,'Blackfoots','lights','demultiplex',''); +INSERT INTO t2 VALUES (519,142701,29,'Grady','circumference','lockings',''); +INSERT INTO t2 VALUES (520,143001,29,'quiets','dull','thugs','FAS'); +INSERT INTO t2 VALUES (521,143501,29,'floundered','weekly','unnerves',''); +INSERT INTO t2 VALUES (522,143502,29,'profundity','wetness','abut',''); +INSERT INTO t2 VALUES (523,148001,29,'Garrisonian','visualized','Chippewa','A'); +INSERT INTO t2 VALUES (524,148002,29,'Strauss','Tannenbaum','stratifications','A'); +INSERT INTO t2 VALUES (525,148003,29,'cemented','moribund','signaled',''); +INSERT INTO t2 VALUES (526,148004,29,'contrition','demultiplex','Italianizes','A'); +INSERT INTO t2 VALUES (527,148005,29,'mutations','lockings','algorithmic','A'); +INSERT INTO t2 VALUES (528,148006,29,'exhibits','thugs','paranoid','FAS'); +INSERT INTO t2 VALUES (529,148007,29,'tits','unnerves','camping','A'); +INSERT INTO t2 VALUES (530,148009,29,'mate','abut','signifying','A'); +INSERT INTO t2 VALUES (531,148010,29,'arches','Chippewa','Patrice','W'); +INSERT INTO t2 VALUES (532,148011,29,'Moll','stratifications','search','A'); +INSERT INTO t2 VALUES (533,148012,29,'ropers','signaled','Angeles','A'); +INSERT INTO t2 VALUES (534,148013,29,'bombast','Italianizes','semblance',''); +INSERT INTO t2 VALUES (535,148023,36,'difficultly','algorithmic','taxed',''); +INSERT INTO t2 VALUES (536,148015,29,'adsorption','paranoid','Beatrice',''); +INSERT INTO t2 VALUES (537,148016,29,'definiteness','camping','retrace',''); +INSERT INTO t2 VALUES (538,148017,29,'cultivation','signifying','lockout',''); +INSERT INTO t2 VALUES (539,148018,29,'heals','Patrice','grammatic',''); +INSERT INTO t2 VALUES (540,148019,29,'Heusen','search','helmsman',''); +INSERT INTO t2 VALUES (541,148020,29,'target','Angeles','uniform','W'); +INSERT INTO t2 VALUES (542,148021,29,'cited','semblance','hamming',''); +INSERT INTO t2 VALUES (543,148022,29,'congresswoman','taxed','disobedience',''); +INSERT INTO t2 VALUES (544,148101,29,'Katherine','Beatrice','captivated','A'); +INSERT INTO t2 VALUES (545,148102,29,'titter','retrace','transferals','A'); +INSERT INTO t2 VALUES (546,148201,29,'aspire','lockout','cartographer','A'); +INSERT INTO t2 VALUES (547,148401,29,'Mardis','grammatic','aims','FAS'); +INSERT INTO t2 VALUES (548,148402,29,'Nadia','helmsman','Pakistani',''); +INSERT INTO t2 VALUES (549,148501,29,'estimating','uniform','burglarized','FAS'); +INSERT INTO t2 VALUES (550,148502,29,'stuck','hamming','saucepans','A'); +INSERT INTO t2 VALUES (551,148503,29,'fifteenth','disobedience','lacerating','A'); +INSERT INTO t2 VALUES (552,148504,29,'Colombo','captivated','corny',''); +INSERT INTO t2 VALUES (553,148601,29,'survey','transferals','megabytes','FAS'); +INSERT INTO t2 VALUES (554,148602,29,'staffing','cartographer','chancellor',''); +INSERT INTO t2 VALUES (555,150701,29,'obtain','aims','bulk','A'); +INSERT INTO t2 VALUES (556,152101,29,'loaded','Pakistani','commits','A'); +INSERT INTO t2 VALUES (557,152102,29,'slaughtered','burglarized','meson','W'); +INSERT INTO t2 VALUES (558,155202,36,'lights','saucepans','deputies',''); +INSERT INTO t2 VALUES (559,155203,29,'circumference','lacerating','northeaster','A'); +INSERT INTO t2 VALUES (560,155204,29,'dull','corny','dipole',''); +INSERT INTO t2 VALUES (561,155205,29,'weekly','megabytes','machining','0'); +INSERT INTO t2 VALUES (562,156001,29,'wetness','chancellor','therefore',''); +INSERT INTO t2 VALUES (563,156002,29,'visualized','bulk','Telefunken',''); +INSERT INTO t2 VALUES (564,156102,29,'Tannenbaum','commits','salvaging',''); +INSERT INTO t2 VALUES (565,156301,29,'moribund','meson','Corinthianizes','A'); +INSERT INTO t2 VALUES (566,156302,29,'demultiplex','deputies','restlessly','A'); +INSERT INTO t2 VALUES (567,156303,29,'lockings','northeaster','bromides',''); +INSERT INTO t2 VALUES (568,156304,29,'thugs','dipole','generalized','A'); +INSERT INTO t2 VALUES (569,156305,29,'unnerves','machining','mishaps',''); +INSERT INTO t2 VALUES (570,156306,29,'abut','therefore','quelling',''); +INSERT INTO t2 VALUES (571,156501,29,'Chippewa','Telefunken','spiritual','A'); +INSERT INTO t2 VALUES (572,158001,29,'stratifications','salvaging','beguiles','FAS'); +INSERT INTO t2 VALUES (573,158002,29,'signaled','Corinthianizes','Trobriand','FAS'); +INSERT INTO t2 VALUES (574,158101,29,'Italianizes','restlessly','fleeing','A'); +INSERT INTO t2 VALUES (575,158102,29,'algorithmic','bromides','Armour','A'); +INSERT INTO t2 VALUES (576,158103,29,'paranoid','generalized','chin','A'); +INSERT INTO t2 VALUES (577,158201,29,'camping','mishaps','provers','A'); +INSERT INTO t2 VALUES (578,158202,29,'signifying','quelling','aeronautic','A'); +INSERT INTO t2 VALUES (579,158203,29,'Patrice','spiritual','voltage','W'); +INSERT INTO t2 VALUES (580,158204,29,'search','beguiles','sash',''); +INSERT INTO t2 VALUES (581,158301,29,'Angeles','Trobriand','anaerobic','A'); +INSERT INTO t2 VALUES (582,158302,29,'semblance','fleeing','simultaneous','A'); +INSERT INTO t2 VALUES (583,158303,29,'taxed','Armour','accumulating','A'); +INSERT INTO t2 VALUES (584,158304,29,'Beatrice','chin','Medusan','A'); +INSERT INTO t2 VALUES (585,158305,29,'retrace','provers','shouted','A'); +INSERT INTO t2 VALUES (586,158306,29,'lockout','aeronautic','freakish',''); +INSERT INTO t2 VALUES (587,158501,29,'grammatic','voltage','index','FAS'); +INSERT INTO t2 VALUES (588,160301,29,'helmsman','sash','commercially',''); +INSERT INTO t2 VALUES (589,166101,50,'uniform','anaerobic','mistiness','A'); +INSERT INTO t2 VALUES (590,166102,50,'hamming','simultaneous','endpoint',''); +INSERT INTO t2 VALUES (591,168001,29,'disobedience','accumulating','straight','A'); +INSERT INTO t2 VALUES (592,168002,29,'captivated','Medusan','flurried',''); +INSERT INTO t2 VALUES (593,168003,29,'transferals','shouted','denotative','A'); +INSERT INTO t2 VALUES (594,168101,29,'cartographer','freakish','coming','FAS'); +INSERT INTO t2 VALUES (595,168102,29,'aims','index','commencements','FAS'); +INSERT INTO t2 VALUES (596,168103,29,'Pakistani','commercially','gentleman',''); +INSERT INTO t2 VALUES (597,168104,29,'burglarized','mistiness','gifted',''); +INSERT INTO t2 VALUES (598,168202,29,'saucepans','endpoint','Shanghais',''); +INSERT INTO t2 VALUES (599,168301,29,'lacerating','straight','sportswriting','A'); +INSERT INTO t2 VALUES (600,168502,29,'corny','flurried','sloping','A'); +INSERT INTO t2 VALUES (601,168503,29,'megabytes','denotative','navies',''); +INSERT INTO t2 VALUES (602,168601,29,'chancellor','coming','leaflet','A'); +INSERT INTO t2 VALUES (603,173001,40,'bulk','commencements','shooter',''); +INSERT INTO t2 VALUES (604,173701,40,'commits','gentleman','Joplin','FAS'); +INSERT INTO t2 VALUES (605,173702,40,'meson','gifted','babies',''); +INSERT INTO t2 VALUES (606,176001,40,'deputies','Shanghais','subdivision','FAS'); +INSERT INTO t2 VALUES (607,176101,40,'northeaster','sportswriting','burstiness','W'); +INSERT INTO t2 VALUES (608,176201,40,'dipole','sloping','belted','FAS'); +INSERT INTO t2 VALUES (609,176401,40,'machining','navies','assails','FAS'); +INSERT INTO t2 VALUES (610,176501,40,'therefore','leaflet','admiring','W'); +INSERT INTO t2 VALUES (611,176601,40,'Telefunken','shooter','swaying','0'); +INSERT INTO t2 VALUES (612,176602,40,'salvaging','Joplin','Goldstine','FAS'); +INSERT INTO t2 VALUES (613,176603,40,'Corinthianizes','babies','fitting',''); +INSERT INTO t2 VALUES (614,178001,40,'restlessly','subdivision','Norwalk','W'); +INSERT INTO t2 VALUES (615,178002,40,'bromides','burstiness','weakening','W'); +INSERT INTO t2 VALUES (616,178003,40,'generalized','belted','analogy','FAS'); +INSERT INTO t2 VALUES (617,178004,40,'mishaps','assails','deludes',''); +INSERT INTO t2 VALUES (618,178005,40,'quelling','admiring','cokes',''); +INSERT INTO t2 VALUES (619,178006,40,'spiritual','swaying','Clayton',''); +INSERT INTO t2 VALUES (620,178007,40,'beguiles','Goldstine','exhausts',''); +INSERT INTO t2 VALUES (621,178008,40,'Trobriand','fitting','causality',''); +INSERT INTO t2 VALUES (622,178101,40,'fleeing','Norwalk','sating','FAS'); +INSERT INTO t2 VALUES (623,178102,40,'Armour','weakening','icon',''); +INSERT INTO t2 VALUES (624,178103,40,'chin','analogy','throttles',''); +INSERT INTO t2 VALUES (625,178201,40,'provers','deludes','communicants','FAS'); +INSERT INTO t2 VALUES (626,178202,40,'aeronautic','cokes','dehydrate','FAS'); +INSERT INTO t2 VALUES (627,178301,40,'voltage','Clayton','priceless','FAS'); +INSERT INTO t2 VALUES (628,178302,40,'sash','exhausts','publicly',''); +INSERT INTO t2 VALUES (629,178401,40,'anaerobic','causality','incidentals','FAS'); +INSERT INTO t2 VALUES (630,178402,40,'simultaneous','sating','commonplace',''); +INSERT INTO t2 VALUES (631,178403,40,'accumulating','icon','mumbles',''); +INSERT INTO t2 VALUES (632,178404,40,'Medusan','throttles','furthermore','W'); +INSERT INTO t2 VALUES (633,178501,40,'shouted','communicants','cautioned','W'); +INSERT INTO t2 VALUES (634,186002,37,'freakish','dehydrate','parametrized','A'); +INSERT INTO t2 VALUES (635,186102,37,'index','priceless','registration','A'); +INSERT INTO t2 VALUES (636,186201,40,'commercially','publicly','sadly','FAS'); +INSERT INTO t2 VALUES (637,186202,40,'mistiness','incidentals','positioning',''); +INSERT INTO t2 VALUES (638,186203,40,'endpoint','commonplace','babysitting',''); +INSERT INTO t2 VALUES (639,186302,37,'straight','mumbles','eternal','A'); +INSERT INTO t2 VALUES (640,188007,37,'flurried','furthermore','hoarder',''); +INSERT INTO t2 VALUES (641,188008,37,'denotative','cautioned','congregates',''); +INSERT INTO t2 VALUES (642,188009,37,'coming','parametrized','rains',''); +INSERT INTO t2 VALUES (643,188010,37,'commencements','registration','workers','W'); +INSERT INTO t2 VALUES (644,188011,37,'gentleman','sadly','sags','A'); +INSERT INTO t2 VALUES (645,188012,37,'gifted','positioning','unplug','W'); +INSERT INTO t2 VALUES (646,188013,37,'Shanghais','babysitting','garage','A'); +INSERT INTO t2 VALUES (647,188014,37,'sportswriting','eternal','boulder','A'); +INSERT INTO t2 VALUES (648,188015,37,'sloping','hoarder','hollowly','A'); +INSERT INTO t2 VALUES (649,188016,37,'navies','congregates','specifics',''); +INSERT INTO t2 VALUES (650,188017,37,'leaflet','rains','Teresa',''); +INSERT INTO t2 VALUES (651,188102,37,'shooter','workers','Winsett',''); +INSERT INTO t2 VALUES (652,188103,37,'Joplin','sags','convenient','A'); +INSERT INTO t2 VALUES (653,188202,37,'babies','unplug','buckboards','FAS'); +INSERT INTO t2 VALUES (654,188301,40,'subdivision','garage','amenities',''); +INSERT INTO t2 VALUES (655,188302,40,'burstiness','boulder','resplendent','FAS'); +INSERT INTO t2 VALUES (656,188303,40,'belted','hollowly','priding','FAS'); +INSERT INTO t2 VALUES (657,188401,37,'assails','specifics','configurations',''); +INSERT INTO t2 VALUES (658,188402,37,'admiring','Teresa','untidiness','A'); +INSERT INTO t2 VALUES (659,188503,37,'swaying','Winsett','Brice','W'); +INSERT INTO t2 VALUES (660,188504,37,'Goldstine','convenient','sews','FAS'); +INSERT INTO t2 VALUES (661,188505,37,'fitting','buckboards','participated',''); +INSERT INTO t2 VALUES (662,190701,37,'Norwalk','amenities','Simon','FAS'); +INSERT INTO t2 VALUES (663,190703,50,'weakening','resplendent','certificates',''); +INSERT INTO t2 VALUES (664,191701,37,'analogy','priding','Fitzpatrick',''); +INSERT INTO t2 VALUES (665,191702,37,'deludes','configurations','Evanston','A'); +INSERT INTO t2 VALUES (666,191703,37,'cokes','untidiness','misted',''); +INSERT INTO t2 VALUES (667,196001,37,'Clayton','Brice','textures','A'); +INSERT INTO t2 VALUES (668,196002,37,'exhausts','sews','save',''); +INSERT INTO t2 VALUES (669,196003,37,'causality','participated','count',''); +INSERT INTO t2 VALUES (670,196101,37,'sating','Simon','rightful','A'); +INSERT INTO t2 VALUES (671,196103,37,'icon','certificates','chaperone',''); +INSERT INTO t2 VALUES (672,196104,37,'throttles','Fitzpatrick','Lizzy','A'); +INSERT INTO t2 VALUES (673,196201,37,'communicants','Evanston','clenched','A'); +INSERT INTO t2 VALUES (674,196202,37,'dehydrate','misted','effortlessly',''); +INSERT INTO t2 VALUES (675,196203,37,'priceless','textures','accessed',''); +INSERT INTO t2 VALUES (676,198001,37,'publicly','save','beaters','A'); +INSERT INTO t2 VALUES (677,198003,37,'incidentals','count','Hornblower','FAS'); +INSERT INTO t2 VALUES (678,198004,37,'commonplace','rightful','vests','A'); +INSERT INTO t2 VALUES (679,198005,37,'mumbles','chaperone','indulgences','FAS'); +INSERT INTO t2 VALUES (680,198006,37,'furthermore','Lizzy','infallibly','A'); +INSERT INTO t2 VALUES (681,198007,37,'cautioned','clenched','unwilling','FAS'); +INSERT INTO t2 VALUES (682,198008,37,'parametrized','effortlessly','excrete','FAS'); +INSERT INTO t2 VALUES (683,198009,37,'registration','accessed','spools','A'); +INSERT INTO t2 VALUES (684,198010,37,'sadly','beaters','crunches','FAS'); +INSERT INTO t2 VALUES (685,198011,37,'positioning','Hornblower','overestimating','FAS'); +INSERT INTO t2 VALUES (686,198012,37,'babysitting','vests','ineffective',''); +INSERT INTO t2 VALUES (687,198013,37,'eternal','indulgences','humiliation','A'); +INSERT INTO t2 VALUES (688,198014,37,'hoarder','infallibly','sophomore',''); +INSERT INTO t2 VALUES (689,198015,37,'congregates','unwilling','star',''); +INSERT INTO t2 VALUES (690,198017,37,'rains','excrete','rifles',''); +INSERT INTO t2 VALUES (691,198018,37,'workers','spools','dialysis',''); +INSERT INTO t2 VALUES (692,198019,37,'sags','crunches','arriving',''); +INSERT INTO t2 VALUES (693,198020,37,'unplug','overestimating','indulge',''); +INSERT INTO t2 VALUES (694,198021,37,'garage','ineffective','clockers',''); +INSERT INTO t2 VALUES (695,198022,37,'boulder','humiliation','languages',''); +INSERT INTO t2 VALUES (696,198023,50,'hollowly','sophomore','Antarctica','A'); +INSERT INTO t2 VALUES (697,198024,37,'specifics','star','percentage',''); +INSERT INTO t2 VALUES (698,198101,37,'Teresa','rifles','ceiling','A'); +INSERT INTO t2 VALUES (699,198103,37,'Winsett','dialysis','specification',''); +INSERT INTO t2 VALUES (700,198105,37,'convenient','arriving','regimented','A'); +INSERT INTO t2 VALUES (701,198106,37,'buckboards','indulge','ciphers',''); +INSERT INTO t2 VALUES (702,198201,37,'amenities','clockers','pictures','A'); +INSERT INTO t2 VALUES (703,198204,37,'resplendent','languages','serpents','A'); +INSERT INTO t2 VALUES (704,198301,53,'priding','Antarctica','allot','A'); +INSERT INTO t2 VALUES (705,198302,53,'configurations','percentage','realized','A'); +INSERT INTO t2 VALUES (706,198303,53,'untidiness','ceiling','mayoral','A'); +INSERT INTO t2 VALUES (707,198304,53,'Brice','specification','opaquely','A'); +INSERT INTO t2 VALUES (708,198401,37,'sews','regimented','hostess','FAS'); +INSERT INTO t2 VALUES (709,198402,37,'participated','ciphers','fiftieth',''); +INSERT INTO t2 VALUES (710,198403,37,'Simon','pictures','incorrectly',''); +INSERT INTO t2 VALUES (711,202101,37,'certificates','serpents','decomposition','FAS'); +INSERT INTO t2 VALUES (712,202301,37,'Fitzpatrick','allot','stranglings',''); +INSERT INTO t2 VALUES (713,202302,37,'Evanston','realized','mixture','FAS'); +INSERT INTO t2 VALUES (714,202303,37,'misted','mayoral','electroencephalography','FAS'); +INSERT INTO t2 VALUES (715,202304,37,'textures','opaquely','similarities','FAS'); +INSERT INTO t2 VALUES (716,202305,37,'save','hostess','charges','W'); +INSERT INTO t2 VALUES (717,202601,37,'count','fiftieth','freest','FAS'); +INSERT INTO t2 VALUES (718,202602,37,'rightful','incorrectly','Greenberg','FAS'); +INSERT INTO t2 VALUES (719,202605,37,'chaperone','decomposition','tinting',''); +INSERT INTO t2 VALUES (720,202606,37,'Lizzy','stranglings','expelled','W'); +INSERT INTO t2 VALUES (721,202607,37,'clenched','mixture','warm',''); +INSERT INTO t2 VALUES (722,202901,37,'effortlessly','electroencephalography','smoothed',''); +INSERT INTO t2 VALUES (723,202902,37,'accessed','similarities','deductions','FAS'); +INSERT INTO t2 VALUES (724,202903,37,'beaters','charges','Romano','W'); +INSERT INTO t2 VALUES (725,202904,37,'Hornblower','freest','bitterroot',''); +INSERT INTO t2 VALUES (726,202907,37,'vests','Greenberg','corset',''); +INSERT INTO t2 VALUES (727,202908,37,'indulgences','tinting','securing',''); +INSERT INTO t2 VALUES (728,203101,37,'infallibly','expelled','environing','FAS'); +INSERT INTO t2 VALUES (729,203103,37,'unwilling','warm','cute',''); +INSERT INTO t2 VALUES (730,203104,37,'excrete','smoothed','Crays',''); +INSERT INTO t2 VALUES (731,203105,37,'spools','deductions','heiress','FAS'); +INSERT INTO t2 VALUES (732,203401,37,'crunches','Romano','inform','FAS'); +INSERT INTO t2 VALUES (733,203402,37,'overestimating','bitterroot','avenge',''); +INSERT INTO t2 VALUES (734,203404,37,'ineffective','corset','universals',''); +INSERT INTO t2 VALUES (735,203901,37,'humiliation','securing','Kinsey','W'); +INSERT INTO t2 VALUES (736,203902,37,'sophomore','environing','ravines','FAS'); +INSERT INTO t2 VALUES (737,203903,37,'star','cute','bestseller',''); +INSERT INTO t2 VALUES (738,203906,37,'rifles','Crays','equilibrium',''); +INSERT INTO t2 VALUES (739,203907,37,'dialysis','heiress','extents','0'); +INSERT INTO t2 VALUES (740,203908,37,'arriving','inform','relatively',''); +INSERT INTO t2 VALUES (741,203909,37,'indulge','avenge','pressure','FAS'); +INSERT INTO t2 VALUES (742,206101,37,'clockers','universals','critiques','FAS'); +INSERT INTO t2 VALUES (743,206201,37,'languages','Kinsey','befouled',''); +INSERT INTO t2 VALUES (744,206202,37,'Antarctica','ravines','rightfully','FAS'); +INSERT INTO t2 VALUES (745,206203,37,'percentage','bestseller','mechanizing','FAS'); +INSERT INTO t2 VALUES (746,206206,37,'ceiling','equilibrium','Latinizes',''); +INSERT INTO t2 VALUES (747,206207,37,'specification','extents','timesharing',''); +INSERT INTO t2 VALUES (748,206208,37,'regimented','relatively','Aden',''); +INSERT INTO t2 VALUES (749,208001,37,'ciphers','pressure','embassies',''); +INSERT INTO t2 VALUES (750,208002,37,'pictures','critiques','males','FAS'); +INSERT INTO t2 VALUES (751,208003,37,'serpents','befouled','shapelessly','FAS'); +INSERT INTO t2 VALUES (752,208004,37,'allot','rightfully','genres','FAS'); +INSERT INTO t2 VALUES (753,208008,37,'realized','mechanizing','mastering',''); +INSERT INTO t2 VALUES (754,208009,37,'mayoral','Latinizes','Newtonian',''); +INSERT INTO t2 VALUES (755,208010,37,'opaquely','timesharing','finishers','FAS'); +INSERT INTO t2 VALUES (756,208011,37,'hostess','Aden','abates',''); +INSERT INTO t2 VALUES (757,208101,37,'fiftieth','embassies','teem',''); +INSERT INTO t2 VALUES (758,208102,37,'incorrectly','males','kiting','FAS'); +INSERT INTO t2 VALUES (759,208103,37,'decomposition','shapelessly','stodgy','FAS'); +INSERT INTO t2 VALUES (760,208104,37,'stranglings','genres','scalps','FAS'); +INSERT INTO t2 VALUES (761,208105,37,'mixture','mastering','feed','FAS'); +INSERT INTO t2 VALUES (762,208110,37,'electroencephalography','Newtonian','guitars',''); +INSERT INTO t2 VALUES (763,208111,37,'similarities','finishers','airships',''); +INSERT INTO t2 VALUES (764,208112,37,'charges','abates','store',''); +INSERT INTO t2 VALUES (765,208113,37,'freest','teem','denounces',''); +INSERT INTO t2 VALUES (766,208201,37,'Greenberg','kiting','Pyle','FAS'); +INSERT INTO t2 VALUES (767,208203,37,'tinting','stodgy','Saxony',''); +INSERT INTO t2 VALUES (768,208301,37,'expelled','scalps','serializations','FAS'); +INSERT INTO t2 VALUES (769,208302,37,'warm','feed','Peruvian','FAS'); +INSERT INTO t2 VALUES (770,208305,37,'smoothed','guitars','taxonomically','FAS'); +INSERT INTO t2 VALUES (771,208401,37,'deductions','airships','kingdom','A'); +INSERT INTO t2 VALUES (772,208402,37,'Romano','store','stint','A'); +INSERT INTO t2 VALUES (773,208403,37,'bitterroot','denounces','Sault','A'); +INSERT INTO t2 VALUES (774,208404,37,'corset','Pyle','faithful',''); +INSERT INTO t2 VALUES (775,208501,37,'securing','Saxony','Ganymede','FAS'); +INSERT INTO t2 VALUES (776,208502,37,'environing','serializations','tidiness','FAS'); +INSERT INTO t2 VALUES (777,208503,37,'cute','Peruvian','gainful','FAS'); +INSERT INTO t2 VALUES (778,208504,37,'Crays','taxonomically','contrary','FAS'); +INSERT INTO t2 VALUES (779,208505,37,'heiress','kingdom','Tipperary','FAS'); +INSERT INTO t2 VALUES (780,210101,37,'inform','stint','tropics','W'); +INSERT INTO t2 VALUES (781,210102,37,'avenge','Sault','theorizers',''); +INSERT INTO t2 VALUES (782,210103,37,'universals','faithful','renew','0'); +INSERT INTO t2 VALUES (783,210104,37,'Kinsey','Ganymede','already',''); +INSERT INTO t2 VALUES (784,210105,37,'ravines','tidiness','terminal',''); +INSERT INTO t2 VALUES (785,210106,37,'bestseller','gainful','Hegelian',''); +INSERT INTO t2 VALUES (786,210107,37,'equilibrium','contrary','hypothesizer',''); +INSERT INTO t2 VALUES (787,210401,37,'extents','Tipperary','warningly','FAS'); +INSERT INTO t2 VALUES (788,213201,37,'relatively','tropics','journalizing','FAS'); +INSERT INTO t2 VALUES (789,213203,37,'pressure','theorizers','nested',''); +INSERT INTO t2 VALUES (790,213204,37,'critiques','renew','Lars',''); +INSERT INTO t2 VALUES (791,213205,37,'befouled','already','saplings',''); +INSERT INTO t2 VALUES (792,213206,37,'rightfully','terminal','foothill',''); +INSERT INTO t2 VALUES (793,213207,37,'mechanizing','Hegelian','labeled',''); +INSERT INTO t2 VALUES (794,216101,37,'Latinizes','hypothesizer','imperiously','FAS'); +INSERT INTO t2 VALUES (795,216103,37,'timesharing','warningly','reporters','FAS'); +INSERT INTO t2 VALUES (796,218001,37,'Aden','journalizing','furnishings','FAS'); +INSERT INTO t2 VALUES (797,218002,37,'embassies','nested','precipitable','FAS'); +INSERT INTO t2 VALUES (798,218003,37,'males','Lars','discounts','FAS'); +INSERT INTO t2 VALUES (799,218004,37,'shapelessly','saplings','excises','FAS'); +INSERT INTO t2 VALUES (800,143503,50,'genres','foothill','Stalin',''); +INSERT INTO t2 VALUES (801,218006,37,'mastering','labeled','despot','FAS'); +INSERT INTO t2 VALUES (802,218007,37,'Newtonian','imperiously','ripeness','FAS'); +INSERT INTO t2 VALUES (803,218008,37,'finishers','reporters','Arabia',''); +INSERT INTO t2 VALUES (804,218009,37,'abates','furnishings','unruly',''); +INSERT INTO t2 VALUES (805,218010,37,'teem','precipitable','mournfulness',''); +INSERT INTO t2 VALUES (806,218011,37,'kiting','discounts','boom','FAS'); +INSERT INTO t2 VALUES (807,218020,37,'stodgy','excises','slaughter','A'); +INSERT INTO t2 VALUES (808,218021,50,'scalps','Stalin','Sabine',''); +INSERT INTO t2 VALUES (809,218022,37,'feed','despot','handy','FAS'); +INSERT INTO t2 VALUES (810,218023,37,'guitars','ripeness','rural',''); +INSERT INTO t2 VALUES (811,218024,37,'airships','Arabia','organizer',''); +INSERT INTO t2 VALUES (812,218101,37,'store','unruly','shipyard','FAS'); +INSERT INTO t2 VALUES (813,218102,37,'denounces','mournfulness','civics','FAS'); +INSERT INTO t2 VALUES (814,218103,37,'Pyle','boom','inaccuracy','FAS'); +INSERT INTO t2 VALUES (815,218201,37,'Saxony','slaughter','rules','FAS'); +INSERT INTO t2 VALUES (816,218202,37,'serializations','Sabine','juveniles','FAS'); +INSERT INTO t2 VALUES (817,218203,37,'Peruvian','handy','comprised','W'); +INSERT INTO t2 VALUES (818,218204,37,'taxonomically','rural','investigations',''); +INSERT INTO t2 VALUES (819,218205,37,'kingdom','organizer','stabilizes','A'); +INSERT INTO t2 VALUES (820,218301,37,'stint','shipyard','seminaries','FAS'); +INSERT INTO t2 VALUES (821,218302,37,'Sault','civics','Hunter','A'); +INSERT INTO t2 VALUES (822,218401,37,'faithful','inaccuracy','sporty','FAS'); +INSERT INTO t2 VALUES (823,218402,37,'Ganymede','rules','test','FAS'); +INSERT INTO t2 VALUES (824,218403,37,'tidiness','juveniles','weasels',''); +INSERT INTO t2 VALUES (825,218404,37,'gainful','comprised','CERN',''); +INSERT INTO t2 VALUES (826,218407,37,'contrary','investigations','tempering',''); +INSERT INTO t2 VALUES (827,218408,37,'Tipperary','stabilizes','afore','FAS'); +INSERT INTO t2 VALUES (828,218409,37,'tropics','seminaries','Galatean',''); +INSERT INTO t2 VALUES (829,218410,37,'theorizers','Hunter','techniques','W'); +INSERT INTO t2 VALUES (830,226001,37,'renew','sporty','error',''); +INSERT INTO t2 VALUES (831,226002,37,'already','test','veranda',''); +INSERT INTO t2 VALUES (832,226003,37,'terminal','weasels','severely',''); +INSERT INTO t2 VALUES (833,226004,37,'Hegelian','CERN','Cassites','FAS'); +INSERT INTO t2 VALUES (834,226005,37,'hypothesizer','tempering','forthcoming',''); +INSERT INTO t2 VALUES (835,226006,37,'warningly','afore','guides',''); +INSERT INTO t2 VALUES (836,226007,37,'journalizing','Galatean','vanish','FAS'); +INSERT INTO t2 VALUES (837,226008,37,'nested','techniques','lied','A'); +INSERT INTO t2 VALUES (838,226203,37,'Lars','error','sawtooth','FAS'); +INSERT INTO t2 VALUES (839,226204,37,'saplings','veranda','fated','FAS'); +INSERT INTO t2 VALUES (840,226205,37,'foothill','severely','gradually',''); +INSERT INTO t2 VALUES (841,226206,37,'labeled','Cassites','widens',''); +INSERT INTO t2 VALUES (842,226207,37,'imperiously','forthcoming','preclude',''); +INSERT INTO t2 VALUES (843,226208,37,'reporters','guides','Jobrel',''); +INSERT INTO t2 VALUES (844,226209,37,'furnishings','vanish','hooker',''); +INSERT INTO t2 VALUES (845,226210,37,'precipitable','lied','rainstorm',''); +INSERT INTO t2 VALUES (846,226211,37,'discounts','sawtooth','disconnects',''); +INSERT INTO t2 VALUES (847,228001,37,'excises','fated','cruelty',''); +INSERT INTO t2 VALUES (848,228004,37,'Stalin','gradually','exponentials','A'); +INSERT INTO t2 VALUES (849,228005,37,'despot','widens','affective','A'); +INSERT INTO t2 VALUES (850,228006,37,'ripeness','preclude','arteries',''); +INSERT INTO t2 VALUES (851,228007,37,'Arabia','Jobrel','Crosby','FAS'); +INSERT INTO t2 VALUES (852,228008,37,'unruly','hooker','acquaint',''); +INSERT INTO t2 VALUES (853,228009,37,'mournfulness','rainstorm','evenhandedly',''); +INSERT INTO t2 VALUES (854,228101,37,'boom','disconnects','percentage',''); +INSERT INTO t2 VALUES (855,228108,37,'slaughter','cruelty','disobedience',''); +INSERT INTO t2 VALUES (856,228109,37,'Sabine','exponentials','humility',''); +INSERT INTO t2 VALUES (857,228110,37,'handy','affective','gleaning','A'); +INSERT INTO t2 VALUES (858,228111,37,'rural','arteries','petted','A'); +INSERT INTO t2 VALUES (859,228112,37,'organizer','Crosby','bloater','A'); +INSERT INTO t2 VALUES (860,228113,37,'shipyard','acquaint','minion','A'); +INSERT INTO t2 VALUES (861,228114,37,'civics','evenhandedly','marginal','A'); +INSERT INTO t2 VALUES (862,228115,37,'inaccuracy','percentage','apiary','A'); +INSERT INTO t2 VALUES (863,228116,37,'rules','disobedience','measures',''); +INSERT INTO t2 VALUES (864,228117,37,'juveniles','humility','precaution',''); +INSERT INTO t2 VALUES (865,228118,37,'comprised','gleaning','repelled',''); +INSERT INTO t2 VALUES (866,228119,37,'investigations','petted','primary','FAS'); +INSERT INTO t2 VALUES (867,228120,37,'stabilizes','bloater','coverings',''); +INSERT INTO t2 VALUES (868,228121,37,'seminaries','minion','Artemia','A'); +INSERT INTO t2 VALUES (869,228122,37,'Hunter','marginal','navigate',''); +INSERT INTO t2 VALUES (870,228201,37,'sporty','apiary','spatial',''); +INSERT INTO t2 VALUES (871,228206,37,'test','measures','Gurkha',''); +INSERT INTO t2 VALUES (872,228207,37,'weasels','precaution','meanwhile','A'); +INSERT INTO t2 VALUES (873,228208,37,'CERN','repelled','Melinda','A'); +INSERT INTO t2 VALUES (874,228209,37,'tempering','primary','Butterfield',''); +INSERT INTO t2 VALUES (875,228210,37,'afore','coverings','Aldrich','A'); +INSERT INTO t2 VALUES (876,228211,37,'Galatean','Artemia','previewing','A'); +INSERT INTO t2 VALUES (877,228212,37,'techniques','navigate','glut','A'); +INSERT INTO t2 VALUES (878,228213,37,'error','spatial','unaffected',''); +INSERT INTO t2 VALUES (879,228214,37,'veranda','Gurkha','inmate',''); +INSERT INTO t2 VALUES (880,228301,37,'severely','meanwhile','mineral',''); +INSERT INTO t2 VALUES (881,228305,37,'Cassites','Melinda','impending','A'); +INSERT INTO t2 VALUES (882,228306,37,'forthcoming','Butterfield','meditation','A'); +INSERT INTO t2 VALUES (883,228307,37,'guides','Aldrich','ideas',''); +INSERT INTO t2 VALUES (884,228308,37,'vanish','previewing','miniaturizes','W'); +INSERT INTO t2 VALUES (885,228309,37,'lied','glut','lewdly',''); +INSERT INTO t2 VALUES (886,228310,37,'sawtooth','unaffected','title',''); +INSERT INTO t2 VALUES (887,228311,37,'fated','inmate','youthfulness',''); +INSERT INTO t2 VALUES (888,228312,37,'gradually','mineral','creak','FAS'); +INSERT INTO t2 VALUES (889,228313,37,'widens','impending','Chippewa',''); +INSERT INTO t2 VALUES (890,228314,37,'preclude','meditation','clamored',''); +INSERT INTO t2 VALUES (891,228401,65,'Jobrel','ideas','freezes',''); +INSERT INTO t2 VALUES (892,228402,65,'hooker','miniaturizes','forgivably','FAS'); +INSERT INTO t2 VALUES (893,228403,65,'rainstorm','lewdly','reduce','FAS'); +INSERT INTO t2 VALUES (894,228404,65,'disconnects','title','McGovern','W'); +INSERT INTO t2 VALUES (895,228405,65,'cruelty','youthfulness','Nazis','W'); +INSERT INTO t2 VALUES (896,228406,65,'exponentials','creak','epistle','W'); +INSERT INTO t2 VALUES (897,228407,65,'affective','Chippewa','socializes','W'); +INSERT INTO t2 VALUES (898,228408,65,'arteries','clamored','conceptions',''); +INSERT INTO t2 VALUES (899,228409,65,'Crosby','freezes','Kevin',''); +INSERT INTO t2 VALUES (900,228410,65,'acquaint','forgivably','uncovering',''); +INSERT INTO t2 VALUES (901,230301,37,'evenhandedly','reduce','chews','FAS'); +INSERT INTO t2 VALUES (902,230302,37,'percentage','McGovern','appendixes','FAS'); +INSERT INTO t2 VALUES (903,230303,37,'disobedience','Nazis','raining',''); +INSERT INTO t2 VALUES (904,018062,37,'humility','epistle','infest',''); +INSERT INTO t2 VALUES (905,230501,37,'gleaning','socializes','compartment',''); +INSERT INTO t2 VALUES (906,230502,37,'petted','conceptions','minting',''); +INSERT INTO t2 VALUES (907,230503,37,'bloater','Kevin','ducks',''); +INSERT INTO t2 VALUES (908,230504,37,'minion','uncovering','roped','A'); +INSERT INTO t2 VALUES (909,230505,37,'marginal','chews','waltz',''); +INSERT INTO t2 VALUES (910,230506,37,'apiary','appendixes','Lillian',''); +INSERT INTO t2 VALUES (911,230507,37,'measures','raining','repressions','A'); +INSERT INTO t2 VALUES (912,230508,37,'precaution','infest','chillingly',''); +INSERT INTO t2 VALUES (913,230509,37,'repelled','compartment','noncritical',''); +INSERT INTO t2 VALUES (914,230901,37,'primary','minting','lithograph',''); +INSERT INTO t2 VALUES (915,230902,37,'coverings','ducks','spongers',''); +INSERT INTO t2 VALUES (916,230903,37,'Artemia','roped','parenthood',''); +INSERT INTO t2 VALUES (917,230904,37,'navigate','waltz','posed',''); +INSERT INTO t2 VALUES (918,230905,37,'spatial','Lillian','instruments',''); +INSERT INTO t2 VALUES (919,230906,37,'Gurkha','repressions','filial',''); +INSERT INTO t2 VALUES (920,230907,37,'meanwhile','chillingly','fixedly',''); +INSERT INTO t2 VALUES (921,230908,37,'Melinda','noncritical','relives',''); +INSERT INTO t2 VALUES (922,230909,37,'Butterfield','lithograph','Pandora',''); +INSERT INTO t2 VALUES (923,230910,37,'Aldrich','spongers','watering','A'); +INSERT INTO t2 VALUES (924,230911,37,'previewing','parenthood','ungrateful',''); +INSERT INTO t2 VALUES (925,230912,37,'glut','posed','secures',''); +INSERT INTO t2 VALUES (926,230913,37,'unaffected','instruments','chastisers',''); +INSERT INTO t2 VALUES (927,230914,37,'inmate','filial','icon',''); +INSERT INTO t2 VALUES (928,231304,37,'mineral','fixedly','reuniting','A'); +INSERT INTO t2 VALUES (929,231305,37,'impending','relives','imagining','A'); +INSERT INTO t2 VALUES (930,231306,37,'meditation','Pandora','abiding','A'); +INSERT INTO t2 VALUES (931,231307,37,'ideas','watering','omnisciently',''); +INSERT INTO t2 VALUES (932,231308,37,'miniaturizes','ungrateful','Britannic',''); +INSERT INTO t2 VALUES (933,231309,37,'lewdly','secures','scholastics','A'); +INSERT INTO t2 VALUES (934,231310,37,'title','chastisers','mechanics','A'); +INSERT INTO t2 VALUES (935,231311,37,'youthfulness','icon','humidly','A'); +INSERT INTO t2 VALUES (936,231312,37,'creak','reuniting','masterpiece',''); +INSERT INTO t2 VALUES (937,231313,37,'Chippewa','imagining','however',''); +INSERT INTO t2 VALUES (938,231314,37,'clamored','abiding','Mendelian',''); +INSERT INTO t2 VALUES (939,231315,37,'freezes','omnisciently','jarred',''); +INSERT INTO t2 VALUES (940,232102,37,'forgivably','Britannic','scolds',''); +INSERT INTO t2 VALUES (941,232103,37,'reduce','scholastics','infatuate',''); +INSERT INTO t2 VALUES (942,232104,37,'McGovern','mechanics','willed','A'); +INSERT INTO t2 VALUES (943,232105,37,'Nazis','humidly','joyfully',''); +INSERT INTO t2 VALUES (944,232106,37,'epistle','masterpiece','Microsoft',''); +INSERT INTO t2 VALUES (945,232107,37,'socializes','however','fibrosities',''); +INSERT INTO t2 VALUES (946,232108,37,'conceptions','Mendelian','Baltimorean',''); +INSERT INTO t2 VALUES (947,232601,37,'Kevin','jarred','equestrian',''); +INSERT INTO t2 VALUES (948,232602,37,'uncovering','scolds','Goodrich',''); +INSERT INTO t2 VALUES (949,232603,37,'chews','infatuate','apish','A'); +INSERT INTO t2 VALUES (950,232605,37,'appendixes','willed','Adlerian',''); +INSERT INTO t2 VALUES (5950,1232605,37,'appendixes','willed','Adlerian',''); +INSERT INTO t2 VALUES (5951,1232606,37,'appendixes','willed','Adlerian',''); +INSERT INTO t2 VALUES (5952,1232607,37,'appendixes','willed','Adlerian',''); +INSERT INTO t2 VALUES (5953,1232608,37,'appendixes','willed','Adlerian',''); +INSERT INTO t2 VALUES (5954,1232609,37,'appendixes','willed','Adlerian',''); +INSERT INTO t2 VALUES (951,232606,37,'raining','joyfully','Tropez',''); +INSERT INTO t2 VALUES (952,232607,37,'infest','Microsoft','nouns',''); +INSERT INTO t2 VALUES (953,232608,37,'compartment','fibrosities','distracting',''); +INSERT INTO t2 VALUES (954,232609,37,'minting','Baltimorean','mutton',''); +INSERT INTO t2 VALUES (955,236104,37,'ducks','equestrian','bridgeable','A'); +INSERT INTO t2 VALUES (956,236105,37,'roped','Goodrich','stickers','A'); +INSERT INTO t2 VALUES (957,236106,37,'waltz','apish','transcontinental','A'); +INSERT INTO t2 VALUES (958,236107,37,'Lillian','Adlerian','amateurish',''); +INSERT INTO t2 VALUES (959,236108,37,'repressions','Tropez','Gandhian',''); +INSERT INTO t2 VALUES (960,236109,37,'chillingly','nouns','stratified',''); +INSERT INTO t2 VALUES (961,236110,37,'noncritical','distracting','chamberlains',''); +INSERT INTO t2 VALUES (962,236111,37,'lithograph','mutton','creditably',''); +INSERT INTO t2 VALUES (963,236112,37,'spongers','bridgeable','philosophic',''); +INSERT INTO t2 VALUES (964,236113,37,'parenthood','stickers','ores',''); +INSERT INTO t2 VALUES (965,238005,37,'posed','transcontinental','Carleton',''); +INSERT INTO t2 VALUES (966,238006,37,'instruments','amateurish','tape','A'); +INSERT INTO t2 VALUES (967,238007,37,'filial','Gandhian','afloat','A'); +INSERT INTO t2 VALUES (968,238008,37,'fixedly','stratified','goodness','A'); +INSERT INTO t2 VALUES (969,238009,37,'relives','chamberlains','welcoming',''); +INSERT INTO t2 VALUES (970,238010,37,'Pandora','creditably','Pinsky','FAS'); +INSERT INTO t2 VALUES (971,238011,37,'watering','philosophic','halting',''); +INSERT INTO t2 VALUES (972,238012,37,'ungrateful','ores','bibliography',''); +INSERT INTO t2 VALUES (973,238013,37,'secures','Carleton','decoding',''); +INSERT INTO t2 VALUES (974,240401,41,'chastisers','tape','variance','A'); +INSERT INTO t2 VALUES (975,240402,41,'icon','afloat','allowed','A'); +INSERT INTO t2 VALUES (976,240901,41,'reuniting','goodness','dire','A'); +INSERT INTO t2 VALUES (977,240902,41,'imagining','welcoming','dub','A'); +INSERT INTO t2 VALUES (978,241801,41,'abiding','Pinsky','poisoning',''); +INSERT INTO t2 VALUES (979,242101,41,'omnisciently','halting','Iraqis','A'); +INSERT INTO t2 VALUES (980,242102,41,'Britannic','bibliography','heaving',''); +INSERT INTO t2 VALUES (981,242201,41,'scholastics','decoding','population','A'); +INSERT INTO t2 VALUES (982,242202,41,'mechanics','variance','bomb','A'); +INSERT INTO t2 VALUES (983,242501,41,'humidly','allowed','Majorca','A'); +INSERT INTO t2 VALUES (984,242502,41,'masterpiece','dire','Gershwins',''); +INSERT INTO t2 VALUES (985,246201,41,'however','dub','explorers',''); +INSERT INTO t2 VALUES (986,246202,41,'Mendelian','poisoning','libretto','A'); +INSERT INTO t2 VALUES (987,246203,41,'jarred','Iraqis','occurred',''); +INSERT INTO t2 VALUES (988,246204,41,'scolds','heaving','Lagos',''); +INSERT INTO t2 VALUES (989,246205,41,'infatuate','population','rats',''); +INSERT INTO t2 VALUES (990,246301,41,'willed','bomb','bankruptcies','A'); +INSERT INTO t2 VALUES (991,246302,41,'joyfully','Majorca','crying',''); +INSERT INTO t2 VALUES (992,248001,41,'Microsoft','Gershwins','unexpected',''); +INSERT INTO t2 VALUES (993,248002,41,'fibrosities','explorers','accessed','A'); +INSERT INTO t2 VALUES (994,248003,41,'Baltimorean','libretto','colorful','A'); +INSERT INTO t2 VALUES (995,248004,41,'equestrian','occurred','versatility','A'); +INSERT INTO t2 VALUES (996,248005,41,'Goodrich','Lagos','cosy',''); +INSERT INTO t2 VALUES (997,248006,41,'apish','rats','Darius','A'); +INSERT INTO t2 VALUES (998,248007,41,'Adlerian','bankruptcies','mastering','A'); +INSERT INTO t2 VALUES (999,248008,41,'Tropez','crying','Asiaticizations','A'); +INSERT INTO t2 VALUES (1000,248009,41,'nouns','unexpected','offerers','A'); +INSERT INTO t2 VALUES (1001,248010,41,'distracting','accessed','uncles','A'); +INSERT INTO t2 VALUES (1002,248011,41,'mutton','colorful','sleepwalk',''); +INSERT INTO t2 VALUES (1003,248012,41,'bridgeable','versatility','Ernestine',''); +INSERT INTO t2 VALUES (1004,248013,41,'stickers','cosy','checksumming',''); +INSERT INTO t2 VALUES (1005,248014,41,'transcontinental','Darius','stopped',''); +INSERT INTO t2 VALUES (1006,248015,41,'amateurish','mastering','sicker',''); +INSERT INTO t2 VALUES (1007,248016,41,'Gandhian','Asiaticizations','Italianization',''); +INSERT INTO t2 VALUES (1008,248017,41,'stratified','offerers','alphabetic',''); +INSERT INTO t2 VALUES (1009,248018,41,'chamberlains','uncles','pharmaceutic',''); +INSERT INTO t2 VALUES (1010,248019,41,'creditably','sleepwalk','creator',''); +INSERT INTO t2 VALUES (1011,248020,41,'philosophic','Ernestine','chess',''); +INSERT INTO t2 VALUES (1012,248021,41,'ores','checksumming','charcoal',''); +INSERT INTO t2 VALUES (1013,248101,41,'Carleton','stopped','Epiphany','A'); +INSERT INTO t2 VALUES (1014,248102,41,'tape','sicker','bulldozes','A'); +INSERT INTO t2 VALUES (1015,248201,41,'afloat','Italianization','Pygmalion','A'); +INSERT INTO t2 VALUES (1016,248202,41,'goodness','alphabetic','caressing','A'); +INSERT INTO t2 VALUES (1017,248203,41,'welcoming','pharmaceutic','Palestine','A'); +INSERT INTO t2 VALUES (1018,248204,41,'Pinsky','creator','regimented','A'); +INSERT INTO t2 VALUES (1019,248205,41,'halting','chess','scars','A'); +INSERT INTO t2 VALUES (1020,248206,41,'bibliography','charcoal','realest','A'); +INSERT INTO t2 VALUES (1021,248207,41,'decoding','Epiphany','diffusing','A'); +INSERT INTO t2 VALUES (1022,248208,41,'variance','bulldozes','clubroom','A'); +INSERT INTO t2 VALUES (1023,248209,41,'allowed','Pygmalion','Blythe','A'); +INSERT INTO t2 VALUES (1024,248210,41,'dire','caressing','ahead',''); +INSERT INTO t2 VALUES (1025,248211,50,'dub','Palestine','reviver',''); +INSERT INTO t2 VALUES (1026,250501,34,'poisoning','regimented','retransmitting','A'); +INSERT INTO t2 VALUES (1027,250502,34,'Iraqis','scars','landslide',''); +INSERT INTO t2 VALUES (1028,250503,34,'heaving','realest','Eiffel',''); +INSERT INTO t2 VALUES (1029,250504,34,'population','diffusing','absentee',''); +INSERT INTO t2 VALUES (1030,250505,34,'bomb','clubroom','aye',''); +INSERT INTO t2 VALUES (1031,250601,34,'Majorca','Blythe','forked','A'); +INSERT INTO t2 VALUES (1032,250602,34,'Gershwins','ahead','Peruvianizes',''); +INSERT INTO t2 VALUES (1033,250603,34,'explorers','reviver','clerked',''); +INSERT INTO t2 VALUES (1034,250604,34,'libretto','retransmitting','tutor',''); +INSERT INTO t2 VALUES (1035,250605,34,'occurred','landslide','boulevard',''); +INSERT INTO t2 VALUES (1036,251001,34,'Lagos','Eiffel','shuttered',''); +INSERT INTO t2 VALUES (1037,251002,34,'rats','absentee','quotes','A'); +INSERT INTO t2 VALUES (1038,251003,34,'bankruptcies','aye','Caltech',''); +INSERT INTO t2 VALUES (1039,251004,34,'crying','forked','Mossberg',''); +INSERT INTO t2 VALUES (1040,251005,34,'unexpected','Peruvianizes','kept',''); +INSERT INTO t2 VALUES (1041,251301,34,'accessed','clerked','roundly',''); +INSERT INTO t2 VALUES (1042,251302,34,'colorful','tutor','features','A'); +INSERT INTO t2 VALUES (1043,251303,34,'versatility','boulevard','imaginable','A'); +INSERT INTO t2 VALUES (1044,251304,34,'cosy','shuttered','controller',''); +INSERT INTO t2 VALUES (1045,251305,34,'Darius','quotes','racial',''); +INSERT INTO t2 VALUES (1046,251401,34,'mastering','Caltech','uprisings','A'); +INSERT INTO t2 VALUES (1047,251402,34,'Asiaticizations','Mossberg','narrowed','A'); +INSERT INTO t2 VALUES (1048,251403,34,'offerers','kept','cannot','A'); +INSERT INTO t2 VALUES (1049,251404,34,'uncles','roundly','vest',''); +INSERT INTO t2 VALUES (1050,251405,34,'sleepwalk','features','famine',''); +INSERT INTO t2 VALUES (1051,251406,34,'Ernestine','imaginable','sugars',''); +INSERT INTO t2 VALUES (1052,251801,34,'checksumming','controller','exterminated','A'); +INSERT INTO t2 VALUES (1053,251802,34,'stopped','racial','belays',''); +INSERT INTO t2 VALUES (1054,252101,34,'sicker','uprisings','Hodges','A'); +INSERT INTO t2 VALUES (1055,252102,34,'Italianization','narrowed','translatable',''); +INSERT INTO t2 VALUES (1056,252301,34,'alphabetic','cannot','duality','A'); +INSERT INTO t2 VALUES (1057,252302,34,'pharmaceutic','vest','recording','A'); +INSERT INTO t2 VALUES (1058,252303,34,'creator','famine','rouses','A'); +INSERT INTO t2 VALUES (1059,252304,34,'chess','sugars','poison',''); +INSERT INTO t2 VALUES (1060,252305,34,'charcoal','exterminated','attitude',''); +INSERT INTO t2 VALUES (1061,252306,34,'Epiphany','belays','dusted',''); +INSERT INTO t2 VALUES (1062,252307,34,'bulldozes','Hodges','encompasses',''); +INSERT INTO t2 VALUES (1063,252308,34,'Pygmalion','translatable','presentation',''); +INSERT INTO t2 VALUES (1064,252309,34,'caressing','duality','Kantian',''); +INSERT INTO t2 VALUES (1065,256001,34,'Palestine','recording','imprecision','A'); +INSERT INTO t2 VALUES (1066,256002,34,'regimented','rouses','saving',''); +INSERT INTO t2 VALUES (1067,256003,34,'scars','poison','maternal',''); +INSERT INTO t2 VALUES (1068,256004,34,'realest','attitude','hewed',''); +INSERT INTO t2 VALUES (1069,256005,34,'diffusing','dusted','kerosene',''); +INSERT INTO t2 VALUES (1070,258001,34,'clubroom','encompasses','Cubans',''); +INSERT INTO t2 VALUES (1071,258002,34,'Blythe','presentation','photographers',''); +INSERT INTO t2 VALUES (1072,258003,34,'ahead','Kantian','nymph','A'); +INSERT INTO t2 VALUES (1073,258004,34,'reviver','imprecision','bedlam','A'); +INSERT INTO t2 VALUES (1074,258005,34,'retransmitting','saving','north','A'); +INSERT INTO t2 VALUES (1075,258006,34,'landslide','maternal','Schoenberg','A'); +INSERT INTO t2 VALUES (1076,258007,34,'Eiffel','hewed','botany','A'); +INSERT INTO t2 VALUES (1077,258008,34,'absentee','kerosene','curs',''); +INSERT INTO t2 VALUES (1078,258009,34,'aye','Cubans','solidification',''); +INSERT INTO t2 VALUES (1079,258010,34,'forked','photographers','inheritresses',''); +INSERT INTO t2 VALUES (1080,258011,34,'Peruvianizes','nymph','stiller',''); +INSERT INTO t2 VALUES (1081,258101,68,'clerked','bedlam','t1','A'); +INSERT INTO t2 VALUES (1082,258102,68,'tutor','north','suite','A'); +INSERT INTO t2 VALUES (1083,258103,34,'boulevard','Schoenberg','ransomer',''); +INSERT INTO t2 VALUES (1084,258104,68,'shuttered','botany','Willy',''); +INSERT INTO t2 VALUES (1085,258105,68,'quotes','curs','Rena','A'); +INSERT INTO t2 VALUES (1086,258106,68,'Caltech','solidification','Seattle','A'); +INSERT INTO t2 VALUES (1087,258107,68,'Mossberg','inheritresses','relaxes','A'); +INSERT INTO t2 VALUES (1088,258108,68,'kept','stiller','exclaim',''); +INSERT INTO t2 VALUES (1089,258109,68,'roundly','t1','implicated','A'); +INSERT INTO t2 VALUES (1090,258110,68,'features','suite','distinguish',''); +INSERT INTO t2 VALUES (1091,258111,68,'imaginable','ransomer','assayed',''); +INSERT INTO t2 VALUES (1092,258112,68,'controller','Willy','homeowner',''); +INSERT INTO t2 VALUES (1093,258113,68,'racial','Rena','and',''); +INSERT INTO t2 VALUES (1094,258201,34,'uprisings','Seattle','stealth',''); +INSERT INTO t2 VALUES (1095,258202,34,'narrowed','relaxes','coinciding','A'); +INSERT INTO t2 VALUES (1096,258203,34,'cannot','exclaim','founder','A'); +INSERT INTO t2 VALUES (1097,258204,34,'vest','implicated','environing',''); +INSERT INTO t2 VALUES (1098,258205,34,'famine','distinguish','jewelry',''); +INSERT INTO t2 VALUES (1099,258301,34,'sugars','assayed','lemons','A'); +INSERT INTO t2 VALUES (1100,258401,34,'exterminated','homeowner','brokenness','A'); +INSERT INTO t2 VALUES (1101,258402,34,'belays','and','bedpost','A'); +INSERT INTO t2 VALUES (1102,258403,34,'Hodges','stealth','assurers','A'); +INSERT INTO t2 VALUES (1103,258404,34,'translatable','coinciding','annoyers',''); +INSERT INTO t2 VALUES (1104,258405,34,'duality','founder','affixed',''); +INSERT INTO t2 VALUES (1105,258406,34,'recording','environing','warbling',''); +INSERT INTO t2 VALUES (1106,258407,34,'rouses','jewelry','seriously',''); +INSERT INTO t2 VALUES (1107,228123,37,'poison','lemons','boasted',''); +INSERT INTO t2 VALUES (1108,250606,34,'attitude','brokenness','Chantilly',''); +INSERT INTO t2 VALUES (1109,208405,37,'dusted','bedpost','Iranizes',''); +INSERT INTO t2 VALUES (1110,212101,37,'encompasses','assurers','violinist',''); +INSERT INTO t2 VALUES (1111,218206,37,'presentation','annoyers','extramarital',''); +INSERT INTO t2 VALUES (1112,150401,37,'Kantian','affixed','spates',''); +INSERT INTO t2 VALUES (1113,248212,41,'imprecision','warbling','cloakroom',''); +INSERT INTO t2 VALUES (1114,128026,00,'saving','seriously','gazer',''); +INSERT INTO t2 VALUES (1115,128024,00,'maternal','boasted','hand',''); +INSERT INTO t2 VALUES (1116,128027,00,'hewed','Chantilly','tucked',''); +INSERT INTO t2 VALUES (1117,128025,00,'kerosene','Iranizes','gems',''); +INSERT INTO t2 VALUES (1118,128109,00,'Cubans','violinist','clinker',''); +INSERT INTO t2 VALUES (1119,128705,00,'photographers','extramarital','refiner',''); +INSERT INTO t2 VALUES (1120,126303,00,'nymph','spates','callus',''); +INSERT INTO t2 VALUES (1121,128308,00,'bedlam','cloakroom','leopards',''); +INSERT INTO t2 VALUES (1122,128204,00,'north','gazer','comfortingly',''); +INSERT INTO t2 VALUES (1123,128205,00,'Schoenberg','hand','generically',''); +INSERT INTO t2 VALUES (1124,128206,00,'botany','tucked','getters',''); +INSERT INTO t2 VALUES (1125,128207,00,'curs','gems','sexually',''); +INSERT INTO t2 VALUES (1126,118205,00,'solidification','clinker','spear',''); +INSERT INTO t2 VALUES (1127,116801,00,'inheritresses','refiner','serums',''); +INSERT INTO t2 VALUES (1128,116803,00,'stiller','callus','Italianization',''); +INSERT INTO t2 VALUES (1129,116804,00,'t1','leopards','attendants',''); +INSERT INTO t2 VALUES (1130,116802,00,'suite','comfortingly','spies',''); +INSERT INTO t2 VALUES (1131,128605,00,'ransomer','generically','Anthony',''); +INSERT INTO t2 VALUES (1132,118308,00,'Willy','getters','planar',''); +INSERT INTO t2 VALUES (1133,113702,00,'Rena','sexually','cupped',''); +INSERT INTO t2 VALUES (1134,113703,00,'Seattle','spear','cleanser',''); +INSERT INTO t2 VALUES (1135,112103,00,'relaxes','serums','commuters',''); +INSERT INTO t2 VALUES (1136,118009,00,'exclaim','Italianization','honeysuckle',''); +INSERT INTO t2 VALUES (5136,1118009,00,'exclaim','Italianization','honeysuckle',''); +INSERT INTO t2 VALUES (1137,138011,00,'implicated','attendants','orphanage',''); +INSERT INTO t2 VALUES (1138,138010,00,'distinguish','spies','skies',''); +INSERT INTO t2 VALUES (1139,138012,00,'assayed','Anthony','crushers',''); +INSERT INTO t2 VALUES (1140,068304,00,'homeowner','planar','Puritan',''); +INSERT INTO t2 VALUES (1141,078009,00,'and','cupped','squeezer',''); +INSERT INTO t2 VALUES (1142,108013,00,'stealth','cleanser','bruises',''); +INSERT INTO t2 VALUES (1143,084004,00,'coinciding','commuters','bonfire',''); +INSERT INTO t2 VALUES (1144,083402,00,'founder','honeysuckle','Colombo',''); +INSERT INTO t2 VALUES (1145,084003,00,'environing','orphanage','nondecreasing',''); +INSERT INTO t2 VALUES (1146,088504,00,'jewelry','skies','innocents',''); +INSERT INTO t2 VALUES (1147,088005,00,'lemons','crushers','masked',''); +INSERT INTO t2 VALUES (1148,088007,00,'brokenness','Puritan','file',''); +INSERT INTO t2 VALUES (1149,088006,00,'bedpost','squeezer','brush',''); +INSERT INTO t2 VALUES (1150,148025,00,'assurers','bruises','mutilate',''); +INSERT INTO t2 VALUES (1151,148024,00,'annoyers','bonfire','mommy',''); +INSERT INTO t2 VALUES (1152,138305,00,'affixed','Colombo','bulkheads',''); +INSERT INTO t2 VALUES (1153,138306,00,'warbling','nondecreasing','undeclared',''); +INSERT INTO t2 VALUES (1154,152701,00,'seriously','innocents','displacements',''); +INSERT INTO t2 VALUES (1155,148505,00,'boasted','masked','nieces',''); +INSERT INTO t2 VALUES (1156,158003,00,'Chantilly','file','coeducation',''); +INSERT INTO t2 VALUES (1157,156201,00,'Iranizes','brush','brassy',''); +INSERT INTO t2 VALUES (1158,156202,00,'violinist','mutilate','authenticator',''); +INSERT INTO t2 VALUES (1159,158307,00,'extramarital','mommy','Washoe',''); +INSERT INTO t2 VALUES (1160,158402,00,'spates','bulkheads','penny',''); +INSERT INTO t2 VALUES (1161,158401,00,'cloakroom','undeclared','Flagler',''); +INSERT INTO t2 VALUES (1162,068013,00,'gazer','displacements','stoned',''); +INSERT INTO t2 VALUES (1163,068012,00,'hand','nieces','cranes',''); +INSERT INTO t2 VALUES (1164,068203,00,'tucked','coeducation','masterful',''); +INSERT INTO t2 VALUES (1165,088205,00,'gems','brassy','biracial',''); +INSERT INTO t2 VALUES (1166,068704,00,'clinker','authenticator','steamships',''); +INSERT INTO t2 VALUES (1167,068604,00,'refiner','Washoe','windmills',''); +INSERT INTO t2 VALUES (1168,158502,00,'callus','penny','exploit',''); +INSERT INTO t2 VALUES (1169,123103,00,'leopards','Flagler','riverfront',''); +INSERT INTO t2 VALUES (1170,148026,00,'comfortingly','stoned','sisterly',''); +INSERT INTO t2 VALUES (1171,123302,00,'generically','cranes','sharpshoot',''); +INSERT INTO t2 VALUES (1172,076503,00,'getters','masterful','mittens',''); +INSERT INTO t2 VALUES (1173,126304,00,'sexually','biracial','interdependency',''); +INSERT INTO t2 VALUES (1174,068306,00,'spear','steamships','policy',''); +INSERT INTO t2 VALUES (1175,143504,00,'serums','windmills','unleashing',''); +INSERT INTO t2 VALUES (1176,160201,00,'Italianization','exploit','pretenders',''); +INSERT INTO t2 VALUES (1177,148028,00,'attendants','riverfront','overstatements',''); +INSERT INTO t2 VALUES (1178,148027,00,'spies','sisterly','birthed',''); +INSERT INTO t2 VALUES (1179,143505,00,'Anthony','sharpshoot','opportunism',''); +INSERT INTO t2 VALUES (1180,108014,00,'planar','mittens','showroom',''); +INSERT INTO t2 VALUES (1181,076104,00,'cupped','interdependency','compromisingly',''); +INSERT INTO t2 VALUES (1182,078106,00,'cleanser','policy','Medicare',''); +INSERT INTO t2 VALUES (1183,126102,00,'commuters','unleashing','corresponds',''); +INSERT INTO t2 VALUES (1184,128029,00,'honeysuckle','pretenders','hardware',''); +INSERT INTO t2 VALUES (1185,128028,00,'orphanage','overstatements','implant',''); +INSERT INTO t2 VALUES (1186,018410,00,'skies','birthed','Alicia',''); +INSERT INTO t2 VALUES (1187,128110,00,'crushers','opportunism','requesting',''); +INSERT INTO t2 VALUES (1188,148506,00,'Puritan','showroom','produced',''); +INSERT INTO t2 VALUES (1189,123303,00,'squeezer','compromisingly','criticizes',''); +INSERT INTO t2 VALUES (1190,123304,00,'bruises','Medicare','backer',''); +INSERT INTO t2 VALUES (1191,068504,00,'bonfire','corresponds','positively',''); +INSERT INTO t2 VALUES (1192,068305,00,'Colombo','hardware','colicky',''); +INSERT INTO t2 VALUES (1193,000000,00,'nondecreasing','implant','thrillingly',''); +--enable_query_log + +# +# Search with a key +# + +select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%"; +select fld3 from t2 where fld3 like "%cultivation" ; + +# +# Search with a key using sorting and limit the same time +# + +select t2.fld3,companynr from t2 where companynr = 57+1 order by fld3; +select fld3,companynr from t2 where companynr = 58 order by fld3; + +select fld3 from t2 order by fld3 desc limit 10; +select fld3 from t2 order by fld3 desc limit 5; +select fld3 from t2 order by fld3 desc limit 5,5; + +# +# Search with a key having a constant with each unique key. +# The table is read directly with read-next on fld3 +# + +select t2.fld3 from t2 where fld3 = 'honeysuckle'; +select t2.fld3 from t2 where fld3 LIKE 'honeysuckl_'; +select t2.fld3 from t2 where fld3 LIKE 'hon_ysuckl_'; +select t2.fld3 from t2 where fld3 LIKE 'honeysuckle%'; +select t2.fld3 from t2 where fld3 LIKE 'h%le'; + +select t2.fld3 from t2 where fld3 LIKE 'honeysuckle_'; +select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%'; + +# +# Test using INDEX and IGNORE INDEX +# + +explain select t2.fld3 from t2 where fld3 = 'honeysuckle'; + +explain select fld3 from t2 ignore index (fld3) where fld3 = 'honeysuckle'; +explain select fld3 from t2 use index (fld1) where fld3 = 'honeysuckle'; + +explain select fld3 from t2 use index (fld3) where fld3 = 'honeysuckle'; +explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle'; + +# +# NOTE NOTE NOTE +# The next should give an error +# + +-- error 1072 +explain select fld3 from t2 ignore index (fld3,not_used); +-- error 1072 +explain select fld3 from t2 use index (not_used); + +# +# Test sorting with a used key (there is no need for sorting) +# + +select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3; +explain select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3; +select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3; + +# +# Search with a key having a constant with many occurrences +# The table is read directly with read-next having fld3 to get the +# occurrences +# + +select fld1,fld3 from t2 where companynr = 37 and fld3 = 'appendixes'; + +# +# Search with bunched 'or's. +# If one can limit the key to a certain interval only the possible +# alternatives will be gone through +# + +select fld1 from t2 where fld1=250501 or fld1="250502"; +explain select fld1 from t2 where fld1=250501 or fld1="250502"; +select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502; +explain select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502; + +# +# Search with a key with LIKE constant +# If the like starts with a certain letter key will be used. +# + +select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%'; +select fld3 from t2 where fld3 like "L%" and fld3 = "ok"; +select fld3 from t2 where (fld3 like "C%" and fld3 = "Chantilly"); +select fld1,fld3 from t2 where fld1 like "25050%"; +select fld1,fld3 from t2 where fld1 like "25050_"; + +# +# Search using distinct. An automatic grouping will be done over all the fields, +# if only distinct is used. In any other case a temporary table will always +# be created. If only the field used for sorting is from the main register, +# it will be sorted first before the distinct table is created. +# + +select distinct companynr from t2; +select distinct companynr from t2 order by companynr; +select distinct companynr from t2 order by companynr desc; +select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; + +select distinct fld3 from t2 where companynr = 34 order by fld3; +select distinct fld3 from t2 limit 10; +select distinct fld3 from t2 having fld3 like "A%" limit 10; +select distinct substring(fld3,1,3) from t2 where fld3 like "A%"; +select distinct substring(fld3,1,3) as a from t2 having a like "A%" order by a limit 10; +select distinct substring(fld3,1,3) from t2 where fld3 like "A%" limit 10; +select distinct substring(fld3,1,3) as a from t2 having a like "A%" limit 10; + +# make a big table. + +create table t3 ( + period int not null, + name char(32) not null, + companynr int not null, + price double(11,0), + price2 double(11,0), + key (period), + key (name) +); + +--disable_query_log +INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1001,"Iranizes",37,5987435,234724); +INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1002,"violinist",37,28357832,8723648); +INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1003,"extramarital",37,39654943,235872); +INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1004,"spates",78,726498,72987523); +INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1005,"cloakroom",78,98439034,823742); +INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1006,"gazer",101,834598,27348324); +INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1007,"hand",154,983543950,29837423); +INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1008,"tucked",311,234298,3275892); +INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1009,"gems",447,2374834,9872392); +INSERT INTO t3 (period,name,companynr,price,price2) VALUES (1010,"clinker",512,786542,76234234); +--enable_query_log + +create temporary table tmp engine = myisam select * from t3; + +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +#insert into tmp select * from t3; +#insert into t3 select * from tmp; + +alter table t3 add t2nr int not null auto_increment primary key first; + +drop table tmp; + +# big table done + +SET SQL_BIG_TABLES=1; +select distinct concat(fld3," ",fld3) as namn from t2,t3 where t2.fld1=t3.t2nr order by namn limit 10; +SET SQL_BIG_TABLES=0; +select distinct concat(fld3," ",fld3) from t2,t3 where t2.fld1=t3.t2nr order by fld3 limit 10; +select distinct fld5 from t2 limit 10; + +# +# Force use of remove_dupp +# + +select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10; +SET SQL_BIG_TABLES=1; # Force use of MyISAM +select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10; +SET SQL_BIG_TABLES=0; +select distinct fld3,repeat("a",length(fld3)),count(*) from t2 group by companynr,fld3 limit 100,10; + +# +# A big order by that should trigger a merge in filesort +# + +select distinct companynr,rtrim(space(512+companynr)) from t3 order by 1,2; + +# +# Search with distinct and order by with many table. +# + +select distinct fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by fld3; + +# +# Here the last fld3 is optimized away from the order by +# + +explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3; + +# +# Some test with ORDER BY and limit +# + +explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; + +# +# Search with a constant table. +# + +select period from t1; +select period from t1 where period=1900; +select fld3,period from t1,t2 where fld1 = 011401 order by period; + +# +# Search with a constant table and several keyparts. (Rows are read only once +# in the beginning of the search) +# + +select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; + +explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; + +# +# Search with a constant table and several rows from another table +# + +select fld3,period from t2,t1 where companynr*10 = 37*10; + +# +# Search with a table reference and without a key. +# t3 will be the main table. +# + +select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; + +# +# Search with an interval on a table with full key on reference table. +# Here t2 will be the main table and only records matching the +# t2nr will be checked. +# + +select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; + +# +# We need another table for join stuff.. +# + +create table t4 ( + companynr tinyint(2) unsigned zerofill NOT NULL default '00', + companyname char(30) NOT NULL default '', + PRIMARY KEY (companynr), + UNIQUE KEY companyname(companyname) +) ENGINE=MyISAM MAX_ROWS=50 PACK_KEYS=1 COMMENT='companynames'; + +--disable_query_log +INSERT INTO t4 (companynr, companyname) VALUES (29,'company 1'); +INSERT INTO t4 (companynr, companyname) VALUES (34,'company 2'); +INSERT INTO t4 (companynr, companyname) VALUES (36,'company 3'); +INSERT INTO t4 (companynr, companyname) VALUES (37,'company 4'); +INSERT INTO t4 (companynr, companyname) VALUES (40,'company 5'); +INSERT INTO t4 (companynr, companyname) VALUES (41,'company 6'); +INSERT INTO t4 (companynr, companyname) VALUES (53,'company 7'); +INSERT INTO t4 (companynr, companyname) VALUES (58,'company 8'); +INSERT INTO t4 (companynr, companyname) VALUES (65,'company 9'); +INSERT INTO t4 (companynr, companyname) VALUES (68,'company 10'); +INSERT INTO t4 (companynr, companyname) VALUES (50,'company 11'); +INSERT INTO t4 (companynr, companyname) VALUES (00,'Unknown'); +--enable_query_log + +# +# Test of stright join to force a full join. +# + +select STRAIGHT_JOIN t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr; + +select SQL_SMALL_RESULT t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr; + +# +# Full join (same alias) +# + +select * from t1,t1 t12; +select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; + +# +# Test of left join. +# +insert into t2 (fld1, companynr) values (999999,99); + +select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +select count(*) from t2 left join t4 using (companynr) where t4.companynr is not null; +explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null; + +select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; +select count(*) from t2 left join t4 using (companynr) where companynr is not null; +explain select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr is null; +delete from t2 where fld1=999999; + +# +# Test left join optimization + +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0; + +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0; +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0; +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0; +# Following can't be optimized +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0; + +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null; +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0; +explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0; + +# +# Joins with forms. +# + +select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; +explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; + +# +# Search using 'or' with the same referens group. +# An interval search will be done first with the first table and after that +# the other table is referenced with a key with a 'test if key in use' for +# each record +# + +select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; + +select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; + +select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; + +# +# Test of many parenthesis levels +# + +select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); +select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); + +select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; + +select fld1 from t2 where fld1 in (250502,98005,98006,250503,250605,250606) and fld1 >=250502 and fld1 not in (250605,250606); + +select fld1 from t2 where fld1 between 250502 and 250504; + +select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld3 like "L%" or fld3 like "G%")) and fld3 like "L%" ; + +# +# Group on one table. +# optimizer: sort table by group and send rows. +# + +select count(*) from t1; +select companynr,count(*),sum(fld1) from t2 group by companynr; +select companynr,count(*) from t2 group by companynr order by companynr desc limit 5; +select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>""; +explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>""; +select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3; +select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; +select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; +select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ; +select distinct mod(companynr,10) from t4 group by companynr; +select distinct 1 from t4 group by companynr; +select count(distinct fld1) from t2; +select companynr,count(distinct fld1) from t2 group by companynr; +select companynr,count(*) from t2 group by companynr; +select companynr,count(distinct concat(fld1,repeat(65,1000))) from t2 group by companynr; +select companynr,count(distinct concat(fld1,repeat(65,200))) from t2 group by companynr; +select companynr,count(distinct floor(fld1/100)) from t2 group by companynr; +select companynr,count(distinct concat(repeat(65,1000),floor(fld1/100))) from t2 group by companynr; + +# +# group with where on a key field +# + +select sum(fld1),fld3 from t2 where fld3="Romans" group by fld1 limit 10; +select name,count(*) from t3 where name='cloakroom' group by name; +select name,count(*) from t3 where name='cloakroom' and price>10 group by name; +select count(*) from t3 where name='cloakroom' and price2=823742; +select name,count(*) from t3 where name='cloakroom' and price2=823742 group by name; +select name,count(*) from t3 where name >= "extramarital" and price <= 39654943 group by name; +select t2.fld3,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; + +# +# Group with extra not group fields. +# + +select companynr|0,companyname from t4 group by 1; +select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by t2.companynr order by companyname; +select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; + +# +# Calculation with group functions +# + +select sum(Period)/count(*) from t1; +select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; +select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg; + +# +# Group with order on not first table +# optimizer: sort table by group and write group records to tmp table. +# sort tmp_table and send rows. +# + +select companynr,count(*) from t2 group by companynr order by 2 desc; +select companynr,count(*) from t2 where companynr > 40 group by companynr order by 2 desc; +select t2.fld4,t2.fld1,count(price),sum(price),min(price),max(price),avg(price) from t3,t2 where t3.companynr = 37 and t2.fld1 = t3.t2nr group by fld1,t2.fld4; + +# +# group by with many tables +# optimizer: create tmp table with group-by uniq index. +# write with update to tmp table. +# sort tmp table according to order (or group if no order) +# send rows +# + +select t3.companynr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 group by companynr,fld3; +select t2.companynr,count(*),min(fld3),max(fld3),sum(price),avg(price) from t2,t3 where t3.companynr >= 30 and t3.companynr <= 58 and t3.t2nr = t2.fld1 and 1+1=2 group by t2.companynr; + +# +# group with many tables and long group on many tables. group on formula +# optimizer: create tmp table with neaded fields +# sort tmp table by group and calculate sums to new table +# if different order by than group, sort tmp table +# send rows +# + +select t3.companynr+0,t3.t2nr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 37 group by 1,t3.t2nr,fld3,fld3,fld3,fld3,fld3 order by fld1; + +# +# WHERE const folding +# optimize: If there is a "field = const" part in the where, change all +# instances of field in the and level to const. +# All instances of const = const are checked once and removed. +# + +# +# Where -> t3.t2nr = 98005 and t2.fld1 = 98005 +# + +select sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1= t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008; + +select t2.fld1,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1 = t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008 or t3.t2nr = t2.fld1 and t2.fld1 = 38008 group by t2.fld1; + +explain select fld3 from t2 where 1>2 or 2>3; +explain select fld3 from t2 where fld1=fld1; + +# +# HAVING +# + +select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502; +select companynr,fld1 from t2 WHERE fld1>=250501 HAVING fld1<=250502; +select companynr,count(*) as count,sum(fld1) as sum from t2 group by companynr having count > 40 and sum/count >= 120000; +select companynr from t2 group by companynr having count(*) > 40 and sum(fld1)/count(*) >= 120000 ; +select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by companyname having t2.companynr >= 40; + +# +# MIN(), MAX() and COUNT() optimizing +# + +select count(*) from t2; +select count(*) from t2 where fld1 < 098024; +# PS does correct pre-zero here. MySQL can't do it as it returns a number. +--disable_ps_protocol +select min(fld1) from t2 where fld1>= 098024; +--enable_ps_protocol +select max(fld1) from t2 where fld1>= 098024; +select count(*) from t3 where price2=76234234; +select count(*) from t3 where companynr=512 and price2=76234234; +explain select min(fld1),max(fld1),count(*) from t2; +# PS does correct pre-zero here. MySQL can't do it as it returns a number. +--disable_ps_protocol +select min(fld1),max(fld1),count(*) from t2; +--enable_ps_protocol +select min(t2nr),max(t2nr) from t3 where t2nr=2115 and price2=823742; +select count(*),min(t2nr),max(t2nr) from t3 where name='spates' and companynr=78; +select t2nr,count(*) from t3 where name='gems' group by t2nr limit 20; +select max(t2nr) from t3 where price=983543950; + +# +# Test of alias +# + +select t1.period from t3 = t1 limit 1; +select t1.period from t1 as t1 limit 1; +select t1.period as "Nuvarande period" from t1 as t1 limit 1; +select period as ok_period from t1 limit 1; +select period as ok_period from t1 group by ok_period limit 1; +select 1+1 as summa from t1 group by summa limit 1; +select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; + +# +# Some simple show commands +# + +show tables; +show tables from test like "s%"; +show tables from test like "t?"; +# We mask out the Privileges column because it differs with embedded server +--replace_column 8 # +show full columns from t2; +--replace_column 8 # +show full columns from t2 from test like 'f%'; +--replace_column 8 # +show full columns from t2 from test like 's%'; +show keys from t2; + +drop table t4, t3, t2, t1; + + +CREATE TABLE t1 ( + cont_nr int(11) NOT NULL auto_increment, + ver_nr int(11) NOT NULL default '0', + aufnr int(11) NOT NULL default '0', + username varchar(50) NOT NULL default '', + hdl_nr int(11) NOT NULL default '0', + eintrag date NOT NULL default '0000-00-00', + st_klasse varchar(40) NOT NULL default '', + st_wert varchar(40) NOT NULL default '', + st_zusatz varchar(40) NOT NULL default '', + st_bemerkung varchar(255) NOT NULL default '', + kunden_art varchar(40) NOT NULL default '', + mcbs_knr int(11) default NULL, + mcbs_aufnr int(11) NOT NULL default '0', + schufa_status char(1) default '?', + bemerkung text, + wirknetz text, + wf_igz int(11) NOT NULL default '0', + tarifcode varchar(80) default NULL, + recycle char(1) default NULL, + sim varchar(30) default NULL, + mcbs_tpl varchar(30) default NULL, + emp_nr int(11) NOT NULL default '0', + laufzeit int(11) default NULL, + hdl_name varchar(30) default NULL, + prov_hdl_nr int(11) NOT NULL default '0', + auto_wirknetz varchar(50) default NULL, + auto_billing varchar(50) default NULL, + touch timestamp NOT NULL, + kategorie varchar(50) default NULL, + kundentyp varchar(20) NOT NULL default '', + sammel_rech_msisdn varchar(30) NOT NULL default '', + p_nr varchar(9) NOT NULL default '', + suffix char(3) NOT NULL default '', + PRIMARY KEY (cont_nr), + KEY idx_aufnr(aufnr), + KEY idx_hdl_nr(hdl_nr), + KEY idx_st_klasse(st_klasse), + KEY ver_nr(ver_nr), + KEY eintrag_idx(eintrag), + KEY emp_nr_idx(emp_nr), + KEY wf_igz(wf_igz), + KEY touch(touch), + KEY hdl_tag(eintrag,hdl_nr), + KEY prov_hdl_nr(prov_hdl_nr), + KEY mcbs_aufnr(mcbs_aufnr), + KEY kundentyp(kundentyp), + KEY p_nr(p_nr,suffix) +) ENGINE=MyISAM; + +INSERT INTO t1 VALUES (3359356,405,3359356,'Mustermann Musterfrau',52500,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1485525,2122316,'+','','N',1909160,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',3,24,'MobilCom Shop Koeln',52500,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359357,468,3359357,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1503580,2139699,'+','','P',1909171,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359358,407,3359358,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1501358,2137473,'N','','N',1909159,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359359,468,3359359,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1507831,2143894,'+','','P',1909162,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359360,0,0,'Mustermann Musterfrau',29674907,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1900169997,2414578,'+',NULL,'N',1909148,'',NULL,NULL,'RV99066_2',20,NULL,'POS',29674907,NULL,NULL,20010202105916,'Mobilfunk','','','97317481','007'); +INSERT INTO t1 VALUES (3359361,406,3359361,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag storniert','','(7001-84):Storno, Kd. möchte nicht mehr','privat',NULL,0,'+','','P',1909150,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1509984,2145874,'+','','P',1909154,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); + +--disable_ps_protocol +SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie; +--enable_ps_protocol +drop table t1; diff --git a/mysql-test/include/gis_generic.inc b/mysql-test/include/gis_generic.inc new file mode 100644 index 00000000000..e5e7283e0e6 --- /dev/null +++ b/mysql-test/include/gis_generic.inc @@ -0,0 +1,180 @@ +--source include/have_geometry.inc + +# +# Spatial objects +# + +--disable_warnings +DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +--enable_warnings + +CREATE TABLE gis_point (fid INTEGER, g POINT); +CREATE TABLE gis_line (fid INTEGER, g LINESTRING); +CREATE TABLE gis_polygon (fid INTEGER, g POLYGON); +CREATE TABLE gis_multi_point (fid INTEGER, g MULTIPOINT); +CREATE TABLE gis_multi_line (fid INTEGER, g MULTILINESTRING); +CREATE TABLE gis_multi_polygon (fid INTEGER, g MULTIPOLYGON); +CREATE TABLE gis_geometrycollection (fid INTEGER, g GEOMETRYCOLLECTION); +CREATE TABLE gis_geometry (fid INTEGER, g GEOMETRY); + +SHOW CREATE TABLE gis_point; +SHOW FIELDS FROM gis_point; +SHOW FIELDS FROM gis_line; +SHOW FIELDS FROM gis_polygon; +SHOW FIELDS FROM gis_multi_point; +SHOW FIELDS FROM gis_multi_line; +SHOW FIELDS FROM gis_multi_polygon; +SHOW FIELDS FROM gis_geometrycollection; +SHOW FIELDS FROM gis_geometry; + + +INSERT INTO gis_point VALUES +(101, PointFromText('POINT(10 10)')), +(102, PointFromText('POINT(20 10)')), +(103, PointFromText('POINT(20 20)')), +(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)')))); + +INSERT INTO gis_line VALUES +(105, LineFromText('LINESTRING(0 0,0 10,10 0)')), +(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')), +(107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10)))); + +INSERT INTO gis_polygon VALUES +(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')), +(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')), +(110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))))); + +INSERT INTO gis_multi_point VALUES +(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')), +(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')), +(113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10)))); + +INSERT INTO gis_multi_line VALUES +(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')), +(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')), +(116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7))))); + + +INSERT INTO gis_multi_polygon VALUES +(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))))); + +INSERT INTO gis_geometrycollection VALUES +(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')), +(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))); + +INSERT into gis_geometry SELECT * FROM gis_point; +INSERT into gis_geometry SELECT * FROM gis_line; +INSERT into gis_geometry SELECT * FROM gis_polygon; +INSERT into gis_geometry SELECT * FROM gis_multi_point; +INSERT into gis_geometry SELECT * FROM gis_multi_line; +INSERT into gis_geometry SELECT * FROM gis_multi_polygon; +INSERT into gis_geometry SELECT * FROM gis_geometrycollection; + +SELECT fid, AsText(g) FROM gis_point ORDER by fid; +SELECT fid, AsText(g) FROM gis_line ORDER by fid; +SELECT fid, AsText(g) FROM gis_polygon ORDER by fid; +SELECT fid, AsText(g) FROM gis_multi_point ORDER by fid; +SELECT fid, AsText(g) FROM gis_multi_line ORDER by fid; +SELECT fid, AsText(g) FROM gis_multi_polygon ORDER by fid; +SELECT fid, AsText(g) FROM gis_geometrycollection ORDER by fid; +SELECT fid, AsText(g) FROM gis_geometry ORDER by fid; + +SELECT fid, Dimension(g) FROM gis_geometry ORDER by fid; +SELECT fid, GeometryType(g) FROM gis_geometry ORDER by fid; +SELECT fid, IsEmpty(g) FROM gis_geometry ORDER by fid; +SELECT fid, AsText(Envelope(g)) FROM gis_geometry ORDER by fid; +explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry; + +SELECT fid, X(g) FROM gis_point ORDER by fid; +SELECT fid, Y(g) FROM gis_point ORDER by fid; +explain extended select X(g),Y(g) FROM gis_point; + +SELECT fid, AsText(StartPoint(g)) FROM gis_line ORDER by fid; +SELECT fid, AsText(EndPoint(g)) FROM gis_line ORDER by fid; +SELECT fid, GLength(g) FROM gis_line ORDER by fid; +SELECT fid, NumPoints(g) FROM gis_line ORDER by fid; +SELECT fid, AsText(PointN(g, 2)) FROM gis_line ORDER by fid; +SELECT fid, IsClosed(g) FROM gis_line ORDER by fid; +explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line; + +SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; +SELECT fid, Area(g) FROM gis_polygon ORDER by fid; +SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon ORDER by fid; +SELECT fid, NumInteriorRings(g) FROM gis_polygon ORDER by fid; +SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon ORDER by fid; +explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM gis_polygon; + +SELECT fid, IsClosed(g) FROM gis_multi_line ORDER by fid; + +SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; +SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; + +SELECT fid, NumGeometries(g) from gis_multi_point ORDER by fid; +SELECT fid, NumGeometries(g) from gis_multi_line ORDER by fid; +SELECT fid, NumGeometries(g) from gis_multi_polygon ORDER by fid; +SELECT fid, NumGeometries(g) from gis_geometrycollection ORDER by fid; +explain extended SELECT fid, NumGeometries(g) from gis_multi_point; + +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point ORDER by fid; +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line ORDER by fid; +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon ORDER by fid; +SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection ORDER by fid; +SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection ORDER by fid; +explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point; + +SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +explain extended SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; + +DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; + +# +# Check that ALTER TABLE doesn't loose geometry type +# +CREATE TABLE t1 ( + gp point, + ln linestring, + pg polygon, + mp multipoint, + mln multilinestring, + mpg multipolygon, + gc geometrycollection, + gm geometry +); + +SHOW FIELDS FROM t1; +ALTER TABLE t1 ADD fid INT; +SHOW FIELDS FROM t1; +DROP TABLE t1; + +create table t1 (a geometry not null); +insert into t1 values (GeomFromText('Point(1 2)')); +-- error 1416 +insert into t1 values ('Garbage'); +-- error 1416 +insert IGNORE into t1 values ('Garbage'); + +drop table t1; + +create table t1 (fl geometry); +--error 1416 +insert into t1 values (1); +--error 1416 +insert into t1 values (1.11); +--error 1416 +insert into t1 values ("qwerty"); +--error 1416 +insert into t1 values (pointfromtext('point(1,1)')); + +drop table t1; + +# End of 5.0 tests diff --git a/mysql-test/include/have_archive.inc b/mysql-test/include/have_archive.inc index f7fb942e83e..262f66076a8 100644 --- a/mysql-test/include/have_archive.inc +++ b/mysql-test/include/have_archive.inc @@ -1,4 +1,4 @@ --- require r/have_archive.require -disable_query_log; +--require r/have_archive.require +--disable_query_log show variables like "have_archive"; -enable_query_log; +--enable_query_log diff --git a/mysql-test/include/have_geometry.inc b/mysql-test/include/have_geometry.inc index 169c3a41ee7..f0ec22af172 100644 --- a/mysql-test/include/have_geometry.inc +++ b/mysql-test/include/have_geometry.inc @@ -1,4 +1,4 @@ --- require r/have_geometry.require -disable_query_log; +--require r/have_geometry.require +--disable_query_log show variables like "have_geometry"; -enable_query_log; +--enable_query_log diff --git a/mysql-test/include/have_openssl_1.inc b/mysql-test/include/have_openssl_1.inc deleted file mode 100644 index 887309c7e23..00000000000 --- a/mysql-test/include/have_openssl_1.inc +++ /dev/null @@ -1,4 +0,0 @@ --- require r/have_openssl_1.require -disable_query_log; -SHOW STATUS LIKE 'Ssl_cipher'; -enable_query_log; diff --git a/mysql-test/include/is_debug_build.inc b/mysql-test/include/is_debug_build.inc new file mode 100644 index 00000000000..23a2814e2bb --- /dev/null +++ b/mysql-test/include/is_debug_build.inc @@ -0,0 +1,4 @@ +-- require r/is_debug_build.require +--disable_query_log +select instr(version(), "debug") > 0; +--enable_query_log diff --git a/mysql-test/include/sp-vars.inc b/mysql-test/include/sp-vars.inc new file mode 100644 index 00000000000..3e02c9d1709 --- /dev/null +++ b/mysql-test/include/sp-vars.inc @@ -0,0 +1,122 @@ +delimiter |; + +--------------------------------------------------------------------------- + +CREATE PROCEDURE sp_vars_check_dflt() +BEGIN + DECLARE v1 TINYINT DEFAULT 1e200; + DECLARE v1u TINYINT UNSIGNED DEFAULT 1e200; + DECLARE v2 TINYINT DEFAULT -1e200; + DECLARE v2u TINYINT UNSIGNED DEFAULT -1e200; + DECLARE v3 TINYINT DEFAULT 300; + DECLARE v3u TINYINT UNSIGNED DEFAULT 300; + DECLARE v4 TINYINT DEFAULT -300; + DECLARE v4u TINYINT UNSIGNED DEFAULT -300; + + DECLARE v5 TINYINT DEFAULT 10 * 10 * 10; + DECLARE v5u TINYINT UNSIGNED DEFAULT 10 * 10 * 10; + DECLARE v6 TINYINT DEFAULT -10 * 10 * 10; + DECLARE v6u TINYINT UNSIGNED DEFAULT -10 * 10 * 10; + + DECLARE v7 TINYINT DEFAULT '10'; + DECLARE v8 TINYINT DEFAULT '10 '; + DECLARE v9 TINYINT DEFAULT ' 10 '; + DECLARE v10 TINYINT DEFAULT 'String 10 '; + DECLARE v11 TINYINT DEFAULT 'String10'; + DECLARE v12 TINYINT DEFAULT '10 String'; + DECLARE v13 TINYINT DEFAULT '10String'; + DECLARE v14 TINYINT DEFAULT concat('10', ' '); + DECLARE v15 TINYINT DEFAULT concat(' ', '10'); + DECLARE v16 TINYINT DEFAULT concat('Hello, ', 'world'); + + DECLARE v17 DECIMAL(64, 2) DEFAULT 12; + DECLARE v18 DECIMAL(64, 2) DEFAULT 12.123; + DECLARE v19 DECIMAL(64, 2) DEFAULT 11 + 1; + DECLARE v20 DECIMAL(64, 2) DEFAULT 12 + 0.123; + + SELECT v1, v1u, v2, v2u, v3, v3u, v4, v4u; + SELECT v5, v5u, v6, v6u; + SELECT v7, v8, v9, v10, v11, v12, v13, v14, v15, v16; + SELECT v17, v18, v19, v20; +END| + +--------------------------------------------------------------------------- + +CREATE PROCEDURE sp_vars_check_assignment() +BEGIN + DECLARE i1, i2, i3, i4 TINYINT; + DECLARE u1, u2, u3, u4 TINYINT UNSIGNED; + DECLARE d1, d2, d3 DECIMAL(64, 2); + + SET i1 = 1e200; + SET i2 = -1e200; + SET i3 = 300; + SET i4 = -300; + + SELECT i1, i2, i3, i4; + + SET i1 = 10 * 10 * 10; + SET i2 = -10 * 10 * 10; + SET i3 = sign(10 * 10) * 10 * 20; + SET i4 = sign(-10 * 10) * -10 * 20; + + SELECT i1, i2, i3, i4; + + SET u1 = 1e200; + SET u2 = -1e200; + SET u3 = 300; + SET u4 = -300; + + SELECT u1, u2, u3, u4; + + SET u1 = 10 * 10 * 10; + SET u2 = -10 * 10 * 10; + SET u3 = sign(10 * 10) * 10 * 20; + SET u4 = sign(-10 * 10) * -10 * 20; + + SELECT u1, u2, u3, u4; + + SET d1 = 1234; + SET d2 = 1234.12; + SET d3 = 1234.1234; + + SELECT d1, d2, d3; + + SET d1 = 12 * 100 + 34; + SET d2 = 12 * 100 + 34 + 0.12; + SET d3 = 12 * 100 + 34 + 0.1234; + + SELECT d1, d2, d3; +END| + +--------------------------------------------------------------------------- + +CREATE FUNCTION sp_vars_check_ret1() RETURNS TINYINT +BEGIN + RETURN 1e200; +END| + +--------------------------------------------------------------------------- + +CREATE FUNCTION sp_vars_check_ret2() RETURNS TINYINT +BEGIN + RETURN 10 * 10 * 10; +END| + +--------------------------------------------------------------------------- + +CREATE FUNCTION sp_vars_check_ret3() RETURNS TINYINT +BEGIN + RETURN 'Hello, world'; +END| + +--------------------------------------------------------------------------- + +CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2) +BEGIN + RETURN 12 * 10 + 34 + 0.1234; +END| + +--------------------------------------------------------------------------- + +delimiter ;| diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl index 9a12d842998..a76f1b2d7b1 100644 --- a/mysql-test/lib/mtr_misc.pl +++ b/mysql-test/lib/mtr_misc.pl @@ -9,7 +9,7 @@ use strict; sub mtr_full_hostname (); sub mtr_short_hostname (); sub mtr_init_args ($); -sub mtr_add_arg ($$); +sub mtr_add_arg ($$@); sub mtr_path_exists(@); sub mtr_script_exists(@); sub mtr_exe_exists(@); @@ -51,7 +51,7 @@ sub mtr_init_args ($) { $$args = []; # Empty list } -sub mtr_add_arg ($$) { +sub mtr_add_arg ($$@) { my $args= shift; my $format= shift; my @fargs = @_; diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index b3a243444c1..4d88c9b3322 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -890,7 +890,14 @@ sub mtr_exit ($) { # cluck("Called mtr_exit()"); mtr_timer_stop_all($::glob_timers); local $SIG{HUP} = 'IGNORE'; - kill('HUP', -$$); + # ToDo: Signalling -$$ will only work if we are the process group + # leader (in fact on QNX it will signal our session group leader, + # which might be Do-compile or Pushbuild, causing tests to be + # aborted). So we only do it if we are the group leader. We might + # set ourselves as the group leader at startup (with + # POSIX::setpgrp(0,0)), but then care must be needed to always do + # proper child process cleanup. + kill('HUP', -$$) if $$ == getpgrp(); sleep 2; exit($code); } diff --git a/mysql-test/lib/mtr_stress.pl b/mysql-test/lib/mtr_stress.pl new file mode 100644 index 00000000000..d3ed24db545 --- /dev/null +++ b/mysql-test/lib/mtr_stress.pl @@ -0,0 +1,180 @@ +# -*- cperl -*- + +# This is a library file used by the Perl version of mysql-test-run, +# and is part of the translation of the Bourne shell script with the +# same name. + +use strict; +use File::Spec; + +# These are not to be prefixed with "mtr_" + +sub run_stress_test (); + +############################################################################## +# +# Run tests in the stress mode +# +############################################################################## + +sub run_stress_test () +{ + + my $args; + my $stress_basedir; + my $stress_suitedir; + + mtr_report("Starting stress testing\n"); + + if ( ! $::glob_use_embedded_server and ! $::opt_local_master ) + { + $::master->[0]->{'pid'}= mysqld_start('master',0,[],[]); + if ( ! $::master->[0]->{'pid'} ) + { + mtr_error("Can't start the mysqld server"); + } + } + + my $stress_basedir=File::Spec->catdir($::opt_vardir, "stress"); + + #Clean up stress dir + if ( -d $stress_basedir ) + { + rmtree($stress_basedir); + } + mkpath($stress_basedir); + + if ($::opt_stress_suite ne 'main' && $::opt_stress_suite ne 'default' ) + { + $stress_suitedir=File::Spec->catdir($::glob_mysql_test_dir, "suite", + $::opt_stress_suite); + } + else + { + $stress_suitedir=$::glob_mysql_test_dir; + } + + if ( -d $stress_suitedir ) + { + #$stress_suite_t_dir=File::Spec->catdir($stress_suitedir, "t"); + #$stress_suite_r_dir=File::Spec->catdir($stress_suitedir, "r"); + #FIXME: check dirs above for existence to ensure that test suite + # contains tests and results dirs + } + else + { + mtr_error("Specified test suite $::opt_stress_suite doesn't exist"); + } + + if ( @::opt_cases ) + { + $::opt_stress_test_file=File::Spec->catfile($stress_basedir, "stress_tests.txt"); + open(STRESS_FILE, ">$::opt_stress_test_file"); + print STRESS_FILE join("\n",@::opt_cases),"\n"; + close(STRESS_FILE); + } + elsif ( $::opt_stress_test_file ) + { + $::opt_stress_test_file=File::Spec->catfile($stress_suitedir, + $::opt_stress_test_file); + if ( ! -f $::opt_stress_test_file ) + { + mtr_error("Specified file $::opt_stress_test_file with list of tests does not exist\n", + "Please ensure that file exists and has proper permissions"); + } + } + else + { + $::opt_stress_test_file=File::Spec->catfile($stress_suitedir, + "stress_tests.txt"); + if ( ! -f $::opt_stress_test_file ) + { + mtr_error("Default file $::opt_stress_test_file with list of tests does not exist\n", + "Please use --stress-test-file option to specify custom one or you can\n", + "just specify name of test for testing as last argument in command line"); + + } + } + + if ( $::opt_stress_init_file ) + { + $::opt_stress_init_file=File::Spec->catfile($stress_suitedir, + $::opt_stress_init_file); + if ( ! -f $::opt_stress_init_file ) + { + mtr_error("Specified file $::opt_stress_init_file with list of tests does not exist\n", + "Please ensure that file exists and has proper permissions"); + } + } + else + { + $::opt_stress_init_file=File::Spec->catfile($stress_suitedir, + "stress_init.txt"); + if ( ! -f $::opt_stress_init_file ) + { + $::opt_stress_init_file=''; + } + } + + if ( $::opt_stress_mode ne 'random' && $::opt_stress_mode ne 'seq' ) + { + mtr_error("You specified wrong mode $::opt_stress_mode for stress test\n", + "Correct values are 'random' or 'seq'"); + } + + mtr_init_args(\$args); + + mtr_add_arg($args, "--server-socket=%s", $::master->[0]->{'path_mysock'}); + mtr_add_arg($args, "--server-user=%s", $::opt_user); + mtr_add_arg($args, "--server-database=%s", "test"); + mtr_add_arg($args, "--stress-suite-basedir=%s", $::glob_mysql_test_dir); + mtr_add_arg($args, "--suite=%s", $::opt_stress_suite); + mtr_add_arg($args, "--stress-tests-file=%s", $::opt_stress_test_file); + mtr_add_arg($args, "--stress-basedir=%s", $stress_basedir); + mtr_add_arg($args, "--server-logs-dir=%s", $stress_basedir); + mtr_add_arg($args, "--stress-mode=%s", $::opt_stress_mode); + mtr_add_arg($args, "--mysqltest=%s", $::exe_mysqltest); + mtr_add_arg($args, "--threads=%s", $::opt_stress_threads); + mtr_add_arg($args, "--verbose"); + mtr_add_arg($args, "--cleanup"); + mtr_add_arg($args, "--log-error-details"); + mtr_add_arg($args, "--abort-on-error"); + + if ( $::opt_stress_init_file ) + { + mtr_add_arg($args, "--stress-init-file=%", $::opt_stress_init_file); + } + + if ( !$::opt_stress_loop_count && !$::opt_stress_test_count && + !$::opt_stress_test_duration ) + { + #Limit stress testing with 20 loops in case when any limit parameter + #was specified + $::opt_stress_test_count=20; + } + + if ( $::opt_stress_loop_count ) + { + mtr_add_arg($args, "--loop-count=%s", $::opt_stress_loop_count); + } + + if ( $::opt_stress_test_count ) + { + mtr_add_arg($args, "--test-count=%s", $::opt_stress_test_count); + } + + if ( $::opt_stress_test_duration ) + { + mtr_add_arg($args, "--test-duration=%s", $::opt_stress_test_duration); + } + + #Run stress test + mtr_run("$::glob_mysql_test_dir/mysql-stress-test.pl", $args, "", "", "", ""); + + if ( ! $::glob_use_embedded_server ) + { + stop_masters(); + } +} + +1; diff --git a/mysql-test/my_manage.c b/mysql-test/my_manage.c index 919d3bd0529..e5d1be42f95 100644 --- a/mysql-test/my_manage.c +++ b/mysql-test/my_manage.c @@ -231,9 +231,6 @@ int wait_for_server_start(char *bin_dir __attribute__((unused)), { arg_list_t al; int err= 0; -#ifndef __WIN__ - int i; -#endif char trash[FN_REFLEN]; /* mysqladmin file */ @@ -247,16 +244,11 @@ int wait_for_server_start(char *bin_dir __attribute__((unused)), add_arg(&al, "--user=%s", user); add_arg(&al, "--password=%s", password); add_arg(&al, "--silent"); + add_arg(&al, "--host=localhost"); -/* #ifdef NOT_USED */ #ifndef __NETWARE__ - add_arg(&al, "-O"); - add_arg(&al, "connect_timeout=10"); + add_arg(&al, "--connect_timeout=10"); add_arg(&al, "-w"); -#endif - - add_arg(&al, "--host=localhost"); -#ifndef __NETWARE__ add_arg(&al, "--protocol=tcp"); #endif add_arg(&al, "ping"); @@ -266,9 +258,14 @@ int wait_for_server_start(char *bin_dir __attribute__((unused)), -- we will try the ping multiple times */ #ifndef __WIN__ - for (i= 0; (i < TRY_MAX) - && (err= spawn(mysqladmin_file, &al, TRUE, NULL, - trash, NULL, NULL)); i++) sleep(1); + { + int i; + for (i= 0; + (i < TRY_MAX) && (err= spawn(mysqladmin_file, &al, TRUE, NULL, + trash, NULL, NULL)); + i++) + sleep(1); + } #else err= spawn(mysqladmin_file, &al, TRUE, NULL,trash, NULL, NULL); #endif diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 6ed068c02d3..2c53b94a248 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -96,6 +96,7 @@ require "lib/mtr_report.pl"; require "lib/mtr_diff.pl"; require "lib/mtr_match.pl"; require "lib/mtr_misc.pl"; +require "lib/mtr_stress.pl"; $Devel::Trace::TRACE= 1; @@ -173,6 +174,7 @@ our $exe_mysql_client_test; our $exe_mysqld; our $exe_mysqlcheck; # Called from test case our $exe_mysqldump; # Called from test case +our $exe_mysqlimport; # Called from test case our $exe_mysqlshow; # Called from test case our $exe_mysql_fix_system_tables; our $exe_mysqltest; @@ -187,6 +189,11 @@ our $opt_big_test= 0; # Send --big-test to mysqltest our @opt_extra_mysqld_opt; our $opt_compress; +our $opt_ssl; +our $opt_skip_ssl; +our $opt_ssl_supported; +our $opt_ps_protocol; + our $opt_current_test; our $opt_ddd; our $opt_debug; @@ -237,7 +244,6 @@ our $opt_skip_test; our $opt_skip_im; our $opt_sleep; -our $opt_ps_protocol; our $opt_sleep_time_after_restart= 1; our $opt_sleep_time_for_delete= 10; @@ -266,6 +272,16 @@ our $opt_valgrind_mysqltest; our $opt_valgrind_all; our $opt_valgrind_options; +our $opt_stress= ""; +our $opt_stress_suite= "main"; +our $opt_stress_mode= "random"; +our $opt_stress_threads= 5; +our $opt_stress_test_count= 0; +our $opt_stress_loop_count= 0; +our $opt_stress_test_duration= 0; +our $opt_stress_init_file= ""; +our $opt_stress_test_file= ""; + our $opt_verbose; our $opt_wait_for_master; @@ -278,7 +294,6 @@ our $opt_udiff; our $opt_skip_ndbcluster; our $opt_with_ndbcluster; -our $opt_with_openssl; our $exe_ndb_mgm; our $path_ndb_tools_dir; @@ -299,7 +314,8 @@ sub executable_setup (); sub environment_setup (); sub kill_running_server (); sub kill_and_cleanup (); -sub ndbcluster_support (); +sub check_ssl_support (); +sub check_ndbcluster_support (); sub ndbcluster_install (); sub ndbcluster_start (); sub ndbcluster_stop (); @@ -334,11 +350,9 @@ sub main () { initial_setup(); command_line_setup(); executable_setup(); - - if (! $opt_skip_ndbcluster and ! $opt_with_ndbcluster) - { - $opt_with_ndbcluster= ndbcluster_support(); - } + + check_ndbcluster_support(); + check_ssl_support(); environment_setup(); signal_setup(); @@ -388,6 +402,10 @@ sub main () { { run_benchmarks(shift); # Shift what? Extra arguments?! } + elsif ( $opt_stress ) + { + run_stress_test() + } else { run_tests(); @@ -473,6 +491,16 @@ sub command_line_setup () { my $im_mysqld1_port= 9312; my $im_mysqld2_port= 9314; + if ( $ENV{'MTR_BUILD_THREAD'} ) + { + $opt_master_myport= $ENV{'MTR_BUILD_THREAD'} * 40 + 8120; + $opt_slave_myport= $opt_master_myport + 16; + $opt_ndbcluster_port= $opt_master_myport + 24; + $im_port= $opt_master_myport + 10; + $im_mysqld1_port= $opt_master_myport + 12; + $im_mysqld2_port= $opt_master_myport + 14; + } + # Read the command line # Note: Keep list, and the order, in sync with usage at end of this file @@ -481,6 +509,9 @@ sub command_line_setup () { # Control what engine/variation to run 'embedded-server' => \$opt_embedded_server, 'ps-protocol' => \$opt_ps_protocol, + 'ssl|with-openssl' => \$opt_ssl, + 'skip-ssl' => \$opt_skip_ssl, + 'compress' => \$opt_compress, 'bench' => \$opt_bench, 'small-bench' => \$opt_small_bench, 'no-manager' => \$opt_no_manager, # Currently not used @@ -531,9 +562,19 @@ sub command_line_setup () { 'valgrind-all:s' => \$opt_valgrind_all, 'valgrind-options=s' => \$opt_valgrind_options, + # Stress testing + 'stress' => \$opt_stress, + 'stress-suite=s' => \$opt_stress_suite, + 'stress-threads=i' => \$opt_stress_threads, + 'stress-test-file=s' => \$opt_stress_test_file, + 'stress-init-file=s' => \$opt_stress_init_file, + 'stress-mode=s' => \$opt_stress_mode, + 'stress-loop-count=i' => \$opt_stress_loop_count, + 'stress-test-count=i' => \$opt_stress_test_count, + 'stress-test-duration=i' => \$opt_stress_test_duration, + # Misc 'big-test' => \$opt_big_test, - 'compress' => \$opt_compress, 'debug' => \$opt_debug, 'fast' => \$opt_fast, 'local' => \$opt_local, @@ -558,7 +599,6 @@ sub command_line_setup () { 'testcase-timeout=i' => \$opt_testcase_timeout, 'suite-timeout=i' => \$opt_suite_timeout, 'warnings|log-warnings' => \$opt_warnings, - 'with-openssl' => \$opt_with_openssl, 'help|h' => \$opt_usage, ) or usage("Can't read options"); @@ -764,6 +804,12 @@ sub command_line_setup () { } } + # On QNX, /tmp/dir/master.sock and /tmp/dir//master.sock seem to be + # considered different, so avoid the extra slash (/) in the socket + # paths. + my $sockdir = $opt_tmpdir; + $sockdir =~ s|/+$||; + # Put this into a hash, will be a C struct $master->[0]= @@ -772,7 +818,7 @@ sub command_line_setup () { path_myerr => "$opt_vardir/log/master.err", path_mylog => "$opt_vardir/log/master.log", path_mypid => "$opt_vardir/run/master.pid", - path_mysock => "$opt_tmpdir/master.sock", + path_mysock => "$sockdir/master.sock", path_myport => $opt_master_myport, start_timeout => 400, # enough time create innodb tables @@ -785,7 +831,7 @@ sub command_line_setup () { path_myerr => "$opt_vardir/log/master1.err", path_mylog => "$opt_vardir/log/master1.log", path_mypid => "$opt_vardir/run/master1.pid", - path_mysock => "$opt_tmpdir/master1.sock", + path_mysock => "$sockdir/master1.sock", path_myport => $opt_master_myport + 1, start_timeout => 400, # enough time create innodb tables }; @@ -796,7 +842,7 @@ sub command_line_setup () { path_myerr => "$opt_vardir/log/slave.err", path_mylog => "$opt_vardir/log/slave.log", path_mypid => "$opt_vardir/run/slave.pid", - path_mysock => "$opt_tmpdir/slave.sock", + path_mysock => "$sockdir/slave.sock", path_myport => $opt_slave_myport, start_timeout => 400, }; @@ -807,7 +853,7 @@ sub command_line_setup () { path_myerr => "$opt_vardir/log/slave1.err", path_mylog => "$opt_vardir/log/slave1.log", path_mypid => "$opt_vardir/run/slave1.pid", - path_mysock => "$opt_tmpdir/slave1.sock", + path_mysock => "$sockdir/slave1.sock", path_myport => $opt_slave_myport + 1, start_timeout => 300, }; @@ -818,7 +864,7 @@ sub command_line_setup () { path_myerr => "$opt_vardir/log/slave2.err", path_mylog => "$opt_vardir/log/slave2.log", path_mypid => "$opt_vardir/run/slave2.pid", - path_mysock => "$opt_tmpdir/slave2.sock", + path_mysock => "$sockdir/slave2.sock", path_myport => $opt_slave_myport + 2, start_timeout => 300, }; @@ -828,7 +874,7 @@ sub command_line_setup () { path_err => "$opt_vardir/log/im.err", path_log => "$opt_vardir/log/im.log", path_pid => "$opt_vardir/run/im.pid", - path_sock => "$opt_tmpdir/im.sock", + path_sock => "$sockdir/im.sock", port => $im_port, start_timeout => $master->[0]->{'start_timeout'}, admin_login => 'im_admin', @@ -843,7 +889,7 @@ sub command_line_setup () { server_id => 1, port => $im_mysqld1_port, path_datadir => "$opt_vardir/im_mysqld_1.data", - path_sock => "$opt_tmpdir/mysqld_1.sock", + path_sock => "$sockdir/mysqld_1.sock", path_pid => "$opt_vardir/run/mysqld_1.pid", }; @@ -852,7 +898,7 @@ sub command_line_setup () { server_id => 2, port => $im_mysqld2_port, path_datadir => "$opt_vardir/im_mysqld_2.data", - path_sock => "$opt_tmpdir/mysqld_2.sock", + path_sock => "$sockdir/mysqld_2.sock", path_pid => "$opt_vardir/run/mysqld_2.pid", nonguarded => 1, }; @@ -882,7 +928,9 @@ sub executable_setup () { { $path_client_bindir= mtr_path_exists("$glob_basedir/client_release", "$glob_basedir/bin"); - $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-nt"); + $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-nt", + "$path_client_bindir/mysqld", + "$path_client_bindir/mysqld-debug",); $path_language= mtr_path_exists("$glob_basedir/share/english/"); $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets"); } @@ -914,6 +962,7 @@ sub executable_setup () { } $exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck"); $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump"); + $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport"); $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow"); $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog"); $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin"); @@ -921,7 +970,7 @@ sub executable_setup () { $exe_mysql_fix_system_tables= mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables"); $exe_my_print_defaults= - mtr_script_exists("$glob_basedir/extra/my_print_defaults"); + mtr_exe_exists("$glob_basedir/extra/my_print_defaults"); $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools"); $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm"; } @@ -930,6 +979,7 @@ sub executable_setup () { $path_client_bindir= mtr_path_exists("$glob_basedir/bin"); $exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck"); $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump"); + $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport"); $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow"); $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog"); $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin"); @@ -938,15 +988,24 @@ sub executable_setup () { mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables", "$glob_basedir/scripts/mysql_fix_privilege_tables"); $exe_my_print_defaults= - mtr_script_exists("$path_client_bindir/my_print_defaults"); + mtr_exe_exists("$path_client_bindir/my_print_defaults"); $path_language= mtr_path_exists("$glob_basedir/share/mysql/english/", "$glob_basedir/share/english/"); $path_charsetsdir= mtr_path_exists("$glob_basedir/share/mysql/charsets", "$glob_basedir/share/charsets"); - $exe_mysqld= mtr_exe_exists ("$glob_basedir/libexec/mysqld", - "$glob_basedir/bin/mysqld"); + if ( $glob_win32 ) + { + $exe_mysqld= mtr_exe_exists ("$glob_basedir/bin/mysqld-nt", + "$glob_basedir/bin/mysqld", + "$glob_basedir/bin/mysqld-debug",); + } + else + { + $exe_mysqld= mtr_exe_exists ("$glob_basedir/libexec/mysqld", + "$glob_basedir/bin/mysqld"); + } $exe_im= mtr_exe_exists("$glob_basedir/libexec/mysqlmanager", "$glob_basedir/bin/mysqlmanager"); if ( $glob_use_embedded_server ) @@ -1040,6 +1099,15 @@ sub environment_setup () { chomp($ENV{$key}); } } + + # We are nice and report a bit about our settings + print "Using MTR_BUILD_THREAD = ",$ENV{MTR_BUILD_THREAD} || 0,"\n"; + print "Using MASTER_MYPORT = $ENV{MASTER_MYPORT}\n"; + print "Using MASTER_MYPORT1 = $ENV{MASTER_MYPORT1}\n"; + print "Using SLAVE_MYPORT = $ENV{SLAVE_MYPORT}\n"; + print "Using NDBCLUSTER_PORT = $opt_ndbcluster_port\n"; + print "Using IM_MYSQLD1_PORT = $ENV{'IM_MYSQLD1_PORT'}\n"; + print "Using IM_MYSQLD2_PORT = $ENV{'IM_MYSQLD2_PORT'}\n"; } @@ -1145,13 +1213,59 @@ sub kill_and_cleanup () { } +sub check_ssl_support () { + + if ($opt_skip_ssl) + { + mtr_report("Skipping SSL"); + $opt_ssl_supported= 0; + $opt_ssl= 0; + return; + } + + # check ssl support by testing using a switch + # that is only available in that case + if ( mtr_run($exe_mysqld, + ["--no-defaults", + "--ssl", + "--help"], + "", "/dev/null", "/dev/null", "") != 0 ) + { + if ( $opt_ssl) + { + mtr_error("Couldn't find support for SSL"); + return; + } + mtr_report("Skipping SSL, mysqld not compiled with SSL"); + $opt_ssl_supported= 0; + $opt_ssl= 0; + return; + } + mtr_report("Setting mysqld to support SSL connections"); + $opt_ssl_supported= 1; +} + + ############################################################################## # # Start the ndb cluster # ############################################################################## -sub ndbcluster_support () { +sub check_ndbcluster_support () { + + if ($opt_skip_ndbcluster) + { + mtr_report("Skipping ndbcluster"); + $opt_with_ndbcluster= 0; + return; + } + + if ($opt_with_ndbcluster) + { + mtr_report("Using ndbcluster"); + return; + } # check ndbcluster support by testing using a switch # that is only available in that case @@ -1161,11 +1275,13 @@ sub ndbcluster_support () { "--help"], "", "/dev/null", "/dev/null", "") != 0 ) { - mtr_report("No ndbcluster support"); - return 0; + mtr_report("Skipping ndbcluster, mysqld not compiled with ndbcluster"); + $opt_with_ndbcluster= 0; + return; } - mtr_report("Has ndbcluster support"); - return 1; + mtr_report("Using ndbcluster, mysqld supports it"); + $opt_with_ndbcluster= 1; + return; } # FIXME why is there a different start below?! @@ -1925,7 +2041,7 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--basedir=%s", $prefix, $path_my_basedir); mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir); mtr_add_arg($args, "%s--core", $prefix); - mtr_add_arg($args, "%s--log-bin-trust-routine-creators", $prefix); + mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix); mtr_add_arg($args, "%s--default-character-set=latin1", $prefix); mtr_add_arg($args, "%s--language=%s", $prefix, $path_language); mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix); @@ -2048,9 +2164,9 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--key_buffer_size=1M", $prefix); mtr_add_arg($args, "%s--sort_buffer=256K", $prefix); mtr_add_arg($args, "%s--max_heap_table_size=1M", $prefix); - mtr_add_arg($args, "%s--log-bin-trust-routine-creators", $prefix); + mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix); - if ( $opt_with_openssl ) + if ( $opt_ssl_supported ) { mtr_add_arg($args, "%s--ssl-ca=%s/std_data/cacert.pem", $prefix, $glob_mysql_test_dir); @@ -2374,6 +2490,14 @@ sub run_mysqltest ($) { $cmdline_mysqldump .= " --debug=d:t:A,$opt_vardir/log/mysqldump.trace"; } + my $cmdline_mysqlimport= "$exe_mysqlimport -uroot " . + "--port=$master->[0]->{'path_myport'} " . + "--socket=$master->[0]->{'path_mysock'} --password="; + if ( $opt_debug ) + { + $cmdline_mysqlimport .= + " --debug=d:t:A,$opt_vardir/log/mysqlimport.trace"; + } my $cmdline_mysqlshow= "$exe_mysqlshow -uroot " . "--port=$master->[0]->{'path_myport'} " . @@ -2427,6 +2551,7 @@ sub run_mysqltest ($) { $ENV{'MYSQL'}= $cmdline_mysql; $ENV{'MYSQL_CHECK'}= $cmdline_mysqlcheck; $ENV{'MYSQL_DUMP'}= $cmdline_mysqldump; + $ENV{'MYSQL_IMPORT'}= $cmdline_mysqlimport; $ENV{'MYSQL_SHOW'}= $cmdline_mysqlshow; $ENV{'MYSQL_BINLOG'}= $cmdline_mysqlbinlog; $ENV{'MYSQL_FIX_SYSTEM_TABLES'}= $cmdline_mysql_fix_system_tables; @@ -2511,14 +2636,26 @@ sub run_mysqltest ($) { mtr_add_arg($args, "--debug=d:t:A,%s/log/mysqltest.trace", $opt_vardir); } - if ( $opt_with_openssl ) + if ( $opt_ssl_supported ) { mtr_add_arg($args, "--ssl-ca=%s/std_data/cacert.pem", - $glob_mysql_test_dir); + $glob_mysql_test_dir); mtr_add_arg($args, "--ssl-cert=%s/std_data/client-cert.pem", - $glob_mysql_test_dir); + $glob_mysql_test_dir); mtr_add_arg($args, "--ssl-key=%s/std_data/client-key.pem", - $glob_mysql_test_dir); + $glob_mysql_test_dir); + } + + # Turn on SSL for all test cases + if ( $opt_ssl ) + { + mtr_add_arg($args, "--ssl", + $glob_mysql_test_dir); + } + elsif ( $opt_ssl_supported ) + { + mtr_add_arg($args, "--skip-ssl", + $glob_mysql_test_dir); } # ---------------------------------------------------------------------- @@ -2597,6 +2734,9 @@ Options to control what engine/variation to run embedded-server Use the embedded server, i.e. no mysqld daemons ps-protocol Use the binary protocol between client and server + compress Use the compressed protocol between client and server + ssl Use ssl protocol between client and server + skip-ssl Dont start sterver with support for ssl connections bench Run the benchmark suite FIXME small-bench FIXME @@ -2604,6 +2744,7 @@ Options to control what test suites or cases to run force Continue to run the suite after failure with-ndbcluster Use cluster, and enable test cases that requres it + skip-ndb[cluster] Skip the ndb test cases, don't start cluster do-test=PREFIX Run test cases which name are prefixed with PREFIX start-from=PREFIX Run test cases starting from test prefixed with PREFIX suite=NAME Run the test suite named NAME. The default is "main" @@ -2628,7 +2769,7 @@ Options that pass on options Options to run test on running server extern Use running server for tests FIXME DANGEROUS - ndbconnectstring=STR Use running cluster, and connect using STR + ndbconnectstring=STR Use running cluster, and connect using STR user=USER User for connect to server Options for debugging the product @@ -2656,7 +2797,6 @@ Misc options verbose Verbose output from this script script-debug Debug this script itself - compress Use the compressed protocol between client and server timer Show test case execution time start-and-exit Only initiate and start the "mysqld" servers, use the startup settings for the specified test case if any @@ -2669,6 +2809,9 @@ Misc options testcase-timeout=MINUTES Max test case run time (default 5) suite-timeout=MINUTES Max test suite run time (default 120) +Deprecated options + with-openssl Deprecated option for ssl + Options not yet described, or that I want to look into more @@ -2685,7 +2828,6 @@ Options not yet described, or that I want to look into more wait-timeout=SECONDS warnings log-warnings - with-openssl HERE mtr_exit(1); diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index a4f8f2ac1f9..982aed9c633 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -216,6 +216,25 @@ NDBCLUSTER_PORT=9350 MYSQL_MANAGER_PW_FILE=$MYSQL_TEST_DIR/var/tmp/manager.pwd MYSQL_MANAGER_LOG=$MYSQL_TEST_DIR/var/log/manager.log MYSQL_MANAGER_USER=root + +# +# To make it easier for different devs to work on the same host, +# an environment variable can be used to control all ports. A small +# number is to be used, 0 - 16 or similar. +# +if [ -n "$MTR_BUILD_THREAD" ] ; then + MASTER_MYPORT=`expr $MTR_BUILD_THREAD '*' 5 + 10000` + MYSQL_MANAGER_PORT=`expr $MASTER_MYPORT + 2` + SLAVE_MYPORT=`expr $MASTER_MYPORT + 3` + NDBCLUSTER_PORT=`expr $MASTER_MYPORT + 4` + + echo "Using MTR_BUILD_THREAD = $MTR_BUILD_THREAD" + echo "Using MASTER_MYPORT = $MASTER_MYPORT" + echo "Using MYSQL_MANAGER_PORT = $MYSQL_MANAGER_PORT" + echo "Using SLAVE_MYPORT = $SLAVE_MYPORT" + echo "Using NDBCLUSTER_PORT = $NDBCLUSTER_PORT" +fi + NO_SLAVE=0 USER_TEST= FAILED_CASES= @@ -260,7 +279,7 @@ DO_STRESS="" STRESS_SUITE="main" STRESS_MODE="random" STRESS_THREADS=5 -STRESS_TEST_COUNT=20 +STRESS_TEST_COUNT="" STRESS_LOOP_COUNT="" STRESS_TEST_DURATION="" STRESS_INIT_FILE="" @@ -610,6 +629,11 @@ if [ x$SOURCE_DIST = x1 ] ; then else MYSQL_DUMP="$BASEDIR/client/mysqldump" fi + if [ -f "$BASEDIR/client/.libs/mysqlimport" ] ; then + MYSQL_IMPORT="$BASEDIR/client/.libs/mysqlimport" + else + MYSQL_IMPORT="$BASEDIR/client/mysqlimport" + fi if [ -f "$BASEDIR/client/.libs/mysqlshow" ] ; then MYSQL_SHOW="$BASEDIR/client/.libs/mysqlshow" else @@ -686,6 +710,7 @@ else MYSQL_CHECK="$CLIENT_BINDIR/mysqlcheck" MYSQL_DUMP="$CLIENT_BINDIR/mysqldump" MYSQL_SHOW="$CLIENT_BINDIR/mysqlshow" + MYSQL_IMPORT="$CLIENT_BINDIR/mysqlimport" MYSQL_BINLOG="$CLIENT_BINDIR/mysqlbinlog" MYSQLADMIN="$CLIENT_BINDIR/mysqladmin" WAIT_PID="$CLIENT_BINDIR/mysql_waitpid" @@ -773,9 +798,10 @@ MYSQL_CHECK="$MYSQL_CHECK --no-defaults -uroot --socket=$MASTER_MYSOCK --passwor MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" MYSQL_SHOW="$MYSQL_SHOW -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLSHOW_OPT" MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR --character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT" +MYSQL_IMPORT="$MYSQL_IMPORT -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose" MYSQL="$MYSQL --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD" -export MYSQL MYSQL_CHECK MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES +export MYSQL MYSQL_CHECK MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES MYSQL_IMPORT export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR MYSQL_MY_PRINT_DEFAULTS export NDB_TOOLS_DIR export NDB_MGM @@ -1235,6 +1261,7 @@ start_master() --server-id=$id \ --basedir=$MY_BASEDIR \ --port=$this_master_myport \ + --port-open-timeout=380 \ --local-infile \ --exit-info=256 \ --core \ @@ -1249,7 +1276,7 @@ start_master() --language=$LANGUAGE \ --innodb_data_file_path=ibdata1:128M:autoextend \ --open-files-limit=1024 \ - --log-bin-trust-routine-creators \ + --log-bin-trust-function-creators \ $MASTER_40_ARGS \ $SMALL_SERVER \ $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \ @@ -1259,6 +1286,7 @@ start_master() --server-id=$id --rpl-recovery-rank=1 \ --basedir=$MY_BASEDIR --init-rpl-role=master \ --port=$this_master_myport \ + --port-open-timeout=380 \ --local-infile \ --datadir=$MASTER_MYDDIR$1 \ --pid-file=$MASTER_MYPID$1 \ @@ -1270,7 +1298,7 @@ start_master() --tmpdir=$MYSQL_TMP_DIR \ --language=$LANGUAGE \ --innodb_data_file_path=ibdata1:128M:autoextend \ - --log-bin-trust-routine-creators \ + --log-bin-trust-function-creators \ $MASTER_40_ARGS \ $SMALL_SERVER \ $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \ @@ -1391,6 +1419,7 @@ start_slave() --datadir=$slave_datadir \ --pid-file=$slave_pid \ --port=$slave_port \ + --port-open-timeout=380 \ --socket=$slave_sock \ --character-sets-dir=$CHARSETSDIR \ --default-character-set=$CHARACTER_SET \ @@ -1403,7 +1432,7 @@ start_slave() --report-port=$slave_port \ --master-retry-count=10 \ -O slave_net_timeout=10 \ - --log-bin-trust-routine-creators \ + --log-bin-trust-function-creators \ $SMALL_SERVER \ $EXTRA_SLAVE_OPT $EXTRA_SLAVE_MYSQLD_OPT" CUR_MYERR=$slave_err @@ -1880,7 +1909,7 @@ run_stress_test() --stress-basedir=$STRESS_BASEDIR \ --server-logs-dir=$STRESS_BASEDIR \ --stress-mode=$STRESS_MODE \ - --mysqltest=$BASEDIR/client/mysqltest \ + --mysqltest=$CLIENT_BINDIR/mysqltest \ --threads=$STRESS_THREADS \ --verbose \ --cleanup \ @@ -1891,6 +1920,14 @@ run_stress_test() STRESS_TEST_ARGS="$STRESS_TEST_ARGS --stress-init-file=$STRESS_INIT_FILE" fi + if [ -z "$STRESS_LOOP_COUNT" -a -z "$STRESS_TEST_COUNT" -a + -z "$STRESS_TEST_DURATION" ] ; then + + #Limit stress testing with 20 loops in case when any limit parameter + #was specified + STRESS_TEST_COUNT=20 + fi + if [ -n "$STRESS_LOOP_COUNT" ] ; then STRESS_TEST_ARGS="$STRESS_TEST_ARGS --loop-count=$STRESS_LOOP_COUNT" fi diff --git a/mysql-test/mysql_test_run_new.c b/mysql-test/mysql_test_run_new.c index 33a69eba872..79db71fa274 100644 --- a/mysql-test/mysql_test_run_new.c +++ b/mysql-test/mysql_test_run_new.c @@ -486,7 +486,7 @@ void start_master() #endif add_arg(&al, "--local-infile"); add_arg(&al, "--core"); - add_arg(&al, "--log-bin-trust-routine-creators"); + add_arg(&al, "--log-bin-trust-function-creators"); add_arg(&al, "--datadir=%s", master_dir); #ifndef __WIN__ add_arg(&al, "--pid-file=%s", master_pid); diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 9b60a187d0b..f224a10c9bd 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -556,3 +556,9 @@ ERROR 3D000: No database selected alter table test.t1 rename test.t1; use test; drop table t1; +create table t1 (mycol int(10) not null); +alter table t1 alter column mycol set default 0; +desc t1; +Field Type Null Key Default Extra +mycol int(10) NO 0 +drop table t1; diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result index df524b491f1..f4e547dbc66 100644 --- a/mysql-test/r/analyse.result +++ b/mysql-test/r/analyse.result @@ -107,7 +107,7 @@ insert into t1 values(1.1); insert into t1 values(2.2); select * from t1 procedure analyse(); Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -test.t1.df 1.1 2.2 8 8 0 0 1.650000000 0.302500000 ENUM('1.1','2.2') NOT NULL +test.t1.df 1.1 2.2 13 13 0 0 1.65000 0.55000 ENUM('1.1','2.2') NOT NULL drop table t1; create table t1 (d double); insert into t1 values (100000); @@ -115,3 +115,29 @@ select * from t1 procedure analyse (1,1); Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype test.t1.d 100000 100000 6 6 0 0 100000 0 MEDIUMINT(6) UNSIGNED NOT NULL drop table t1; +create table t1 (product varchar(32), country_id int not null, year int, +profit int); +insert into t1 values ( 'Computer', 2,2000, 1200), +( 'TV', 1, 1999, 150), +( 'Calculator', 1, 1999,50), +( 'Computer', 1, 1999,1500), +( 'Computer', 1, 2000,1500), +( 'TV', 1, 2000, 150), +( 'TV', 2, 2000, 100), +( 'TV', 2, 2000, 100), +( 'Calculator', 1, 2000,75), +( 'Calculator', 2, 2000,75), +( 'TV', 1, 1999, 100), +( 'Computer', 1, 1999,1200), +( 'Computer', 2, 2000,1500), +( 'Calculator', 2, 2000,75), +( 'Phone', 3, 2003,10) +; +create table t2 (country_id int primary key, country char(20) not null); +insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland'); +select product, sum(profit),avg(profit) from t1 group by product with rollup procedure analyse(); +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +test.t1.product Computer TV 2 8 0 0 4.2500 NULL ENUM('Computer','Phone','TV') NOT NULL +sum(profit) 10 6900 11 11 0 0 1946.2500 2867.6719 ENUM('10','275','600','6900') NOT NULL +avg(profit) 10.0000 1380.0000 16 16 0 0 394.68750000 570.20033144 ENUM('10.0000','68.7500','120.0000','1380.0000') NOT NULL +drop table t1,t2; diff --git a/mysql-test/r/analyze.result b/mysql-test/r/analyze.result index 0b44a502b13..17686d597a4 100644 --- a/mysql-test/r/analyze.result +++ b/mysql-test/r/analyze.result @@ -30,3 +30,19 @@ check table t1; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; +create table t1 (a mediumtext, fulltext key key1(a)) charset utf8 collate utf8_general_ci engine myisam; +insert into t1 values ('hello'); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Table is already up to date +drop table t1; +CREATE TABLE t1 (a int); +prepare stmt1 from "SELECT * FROM t1 PROCEDURE ANALYSE()"; +execute stmt1; +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +execute stmt1; +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +deallocate prepare stmt1; diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index 788e1444db4..88bb3126fb6 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -192,8 +192,6 @@ select count(*) from t3; count(*) 1199 rename table t3 to t4; -Warnings: -Error 7 Error on rename of './test/t3.ARN' to './test/t4.ARN' (Errcode: 2) select * from t4 where fld3='bonfire'; auto fld1 companynr fld3 fld4 fld5 fld6 1191 068504 00 bonfire corresponds positively @@ -11121,4 +11119,1231 @@ auto fld1 companynr fld3 fld4 fld5 fld6 3 011402 37 Romans scholastics jarring 4 011403 37 intercepted audiology tinily INSERT DELAYED INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily',''); +ALTER TABLE t2 DROP COLUMN fld6; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `auto` int(11) default NULL, + `fld1` int(6) unsigned zerofill NOT NULL default '000000', + `companynr` tinyint(2) unsigned zerofill NOT NULL default '00', + `fld3` char(30) NOT NULL default '', + `fld4` char(35) NOT NULL default '', + `fld5` char(35) NOT NULL default '' +) ENGINE=ARCHIVE DEFAULT CHARSET=latin1 +SELECT * from t2; +auto fld1 companynr fld3 fld4 fld5 +1 000001 00 Omaha teethe neat +2 011401 37 breaking dreaded Steinberg +3 011402 37 Romans scholastics jarring +4 011403 37 intercepted audiology tinily +5 011501 37 bewilderingly wallet balled +6 011701 37 astound parters persist +7 011702 37 admonishing eschew attainments +8 011703 37 sumac quitter fanatic +9 012001 37 flanking neat measures +10 012003 37 combed Steinberg rightfulness +11 012004 37 subjective jarring capably +12 012005 37 scatterbrain tinily impulsive +13 012301 37 Eulerian balled starlet +14 012302 36 dubbed persist terminators +15 012303 37 Kane attainments untying +16 012304 37 overlay fanatic announces +17 012305 37 perturb measures featherweight +18 012306 37 goblins rightfulness pessimist +19 012501 37 annihilates capably daughter +20 012602 37 Wotan impulsive decliner +21 012603 37 snatching starlet lawgiver +22 012604 37 concludes terminators stated +23 012605 37 laterally untying readable +24 012606 37 yelped announces attrition +25 012701 37 grazing featherweight cascade +26 012702 37 Baird pessimist motors +27 012703 37 celery daughter interrogate +28 012704 37 misunderstander decliner pests +29 013601 37 handgun lawgiver stairway +30 013602 37 foldout stated dopers +31 013603 37 mystic readable testicle +32 013604 37 succumbed attrition Parsifal +33 013605 37 Nabisco cascade leavings +34 013606 37 fingerings motors postulation +35 013607 37 aging interrogate squeaking +36 013608 37 afield pests contrasted +37 013609 37 ammonium stairway leftover +38 013610 37 boat dopers whiteners +39 013801 37 intelligibility testicle erases +40 013802 37 Augustine Parsifal Punjab +41 013803 37 teethe leavings Merritt +42 013804 37 dreaded postulation Quixotism +43 013901 37 scholastics squeaking sweetish +44 016001 37 audiology contrasted dogging +45 016201 37 wallet leftover scornfully +46 016202 37 parters whiteners bellow +47 016301 37 eschew erases bills +48 016302 37 quitter Punjab cupboard +49 016303 37 neat Merritt sureties +50 016304 37 Steinberg Quixotism puddings +51 018001 37 jarring sweetish tapestry +52 018002 37 tinily dogging fetters +53 018003 37 balled scornfully bivalves +54 018004 37 persist bellow incurring +55 018005 37 attainments bills Adolph +56 018007 37 fanatic cupboard pithed +57 018008 37 measures sureties emergency +58 018009 37 rightfulness puddings Miles +59 018010 37 capably tapestry trimmings +60 018012 37 impulsive fetters tragedies +61 018013 37 starlet bivalves skulking +62 018014 37 terminators incurring flint +63 018015 37 untying Adolph flopping +64 018016 37 announces pithed relaxing +65 018017 37 featherweight emergency offload +66 018018 37 pessimist Miles suites +67 018019 37 daughter trimmings lists +68 018020 37 decliner tragedies animized +69 018021 37 lawgiver skulking multilayer +70 018022 37 stated flint standardizes +71 018023 37 readable flopping Judas +72 018024 37 attrition relaxing vacuuming +73 018025 37 cascade offload dentally +74 018026 37 motors suites humanness +75 018027 37 interrogate lists inch +76 018028 37 pests animized Weissmuller +77 018029 37 stairway multilayer irresponsibly +78 018030 37 dopers standardizes luckily +79 018032 37 testicle Judas culled +80 018033 37 Parsifal vacuuming medical +81 018034 37 leavings dentally bloodbath +82 018035 37 postulation humanness subschema +83 018036 37 squeaking inch animals +84 018037 37 contrasted Weissmuller Micronesia +85 018038 37 leftover irresponsibly repetitions +86 018039 37 whiteners luckily Antares +87 018040 37 erases culled ventilate +88 018041 37 Punjab medical pityingly +89 018042 37 Merritt bloodbath interdependent +90 018043 37 Quixotism subschema Graves +91 018044 37 sweetish animals neonatal +92 018045 37 dogging Micronesia scribbled +93 018046 37 scornfully repetitions chafe +94 018048 37 bellow Antares honoring +95 018049 37 bills ventilate realtor +96 018050 37 cupboard pityingly elite +97 018051 37 sureties interdependent funereal +98 018052 37 puddings Graves abrogating +99 018053 50 tapestry neonatal sorters +100 018054 37 fetters scribbled Conley +101 018055 37 bivalves chafe lectured +102 018056 37 incurring honoring Abraham +103 018057 37 Adolph realtor Hawaii +104 018058 37 pithed elite cage +105 018059 36 emergency funereal hushes +106 018060 37 Miles abrogating Simla +107 018061 37 trimmings sorters reporters +108 018101 37 tragedies Conley Dutchman +109 018102 37 skulking lectured descendants +110 018103 37 flint Abraham groupings +111 018104 37 flopping Hawaii dissociate +112 018201 37 relaxing cage coexist +113 018202 37 offload hushes Beebe +114 018402 37 suites Simla Taoism +115 018403 37 lists reporters Connally +116 018404 37 animized Dutchman fetched +117 018405 37 multilayer descendants checkpoints +118 018406 37 standardizes groupings rusting +119 018409 37 Judas dissociate galling +120 018601 37 vacuuming coexist obliterates +121 018602 37 dentally Beebe traitor +122 018603 37 humanness Taoism resumes +123 018801 37 inch Connally analyzable +124 018802 37 Weissmuller fetched terminator +125 018803 37 irresponsibly checkpoints gritty +126 018804 37 luckily rusting firearm +127 018805 37 culled galling minima +128 018806 37 medical obliterates Selfridge +129 018807 37 bloodbath traitor disable +130 018808 37 subschema resumes witchcraft +131 018809 37 animals analyzable betroth +132 018810 37 Micronesia terminator Manhattanize +133 018811 37 repetitions gritty imprint +134 018812 37 Antares firearm peeked +135 019101 37 ventilate minima swelling +136 019102 37 pityingly Selfridge interrelationships +137 019103 37 interdependent disable riser +138 019201 37 Graves witchcraft Gandhian +139 030501 37 neonatal betroth peacock +140 030502 50 scribbled Manhattanize bee +141 030503 37 chafe imprint kanji +142 030504 37 honoring peeked dental +143 031901 37 realtor swelling scarf +144 036001 37 elite interrelationships chasm +145 036002 37 funereal riser insolence +146 036004 37 abrogating Gandhian syndicate +147 036005 37 sorters peacock alike +148 038001 37 Conley bee imperial +149 038002 37 lectured kanji convulsion +150 038003 37 Abraham dental railway +151 038004 37 Hawaii scarf validate +152 038005 37 cage chasm normalizes +153 038006 37 hushes insolence comprehensive +154 038007 37 Simla syndicate chewing +155 038008 37 reporters alike denizen +156 038009 37 Dutchman imperial schemer +157 038010 37 descendants convulsion chronicle +158 038011 37 groupings railway Kline +159 038012 37 dissociate validate Anatole +160 038013 37 coexist normalizes partridges +161 038014 37 Beebe comprehensive brunch +162 038015 37 Taoism chewing recruited +163 038016 37 Connally denizen dimensions +164 038017 37 fetched schemer Chicana +165 038018 37 checkpoints chronicle announced +166 038101 37 rusting Kline praised +167 038102 37 galling Anatole employing +168 038103 37 obliterates partridges linear +169 038104 37 traitor brunch quagmire +170 038201 37 resumes recruited western +171 038202 37 analyzable dimensions relishing +172 038203 37 terminator Chicana serving +173 038204 37 gritty announced scheduling +174 038205 37 firearm praised lore +175 038206 37 minima employing eventful +176 038208 37 Selfridge linear arteriole +177 042801 37 disable quagmire disentangle +178 042802 37 witchcraft western cured +179 046101 37 betroth relishing Fenton +180 048001 37 Manhattanize serving avoidable +181 048002 37 imprint scheduling drains +182 048003 37 peeked lore detectably +183 048004 37 swelling eventful husky +184 048005 37 interrelationships arteriole impelling +185 048006 37 riser disentangle undoes +186 048007 37 Gandhian cured evened +187 048008 37 peacock Fenton squeezes +188 048101 37 bee avoidable destroyer +189 048102 37 kanji drains rudeness +190 048201 37 dental detectably beaner +191 048202 37 scarf husky boorish +192 048203 37 chasm impelling Everhart +193 048204 37 insolence undoes encompass +194 048205 37 syndicate evened mushrooms +195 048301 37 alike squeezes Alison +196 048302 37 imperial destroyer externally +197 048303 37 convulsion rudeness pellagra +198 048304 37 railway beaner cult +199 048305 37 validate boorish creek +200 048401 37 normalizes Everhart Huffman +201 048402 37 comprehensive encompass Majorca +202 048403 37 chewing mushrooms governing +203 048404 37 denizen Alison gadfly +204 048405 37 schemer externally reassigned +205 048406 37 chronicle pellagra intentness +206 048407 37 Kline cult craziness +207 048408 37 Anatole creek psychic +208 048409 37 partridges Huffman squabbled +209 048410 37 brunch Majorca burlesque +210 048411 37 recruited governing capped +211 048412 37 dimensions gadfly extracted +212 048413 37 Chicana reassigned DiMaggio +213 048601 37 announced intentness exclamation +214 048602 37 praised craziness subdirectory +215 048603 37 employing psychic fangs +216 048604 37 linear squabbled buyer +217 048801 37 quagmire burlesque pithing +218 050901 37 western capped transistorizing +219 051201 37 relishing extracted nonbiodegradable +220 056002 37 serving DiMaggio dislocate +221 056003 37 scheduling exclamation monochromatic +222 056004 37 lore subdirectory batting +223 056102 37 eventful fangs postcondition +224 056203 37 arteriole buyer catalog +225 056204 37 disentangle pithing Remus +226 058003 37 cured transistorizing devices +227 058004 37 Fenton nonbiodegradable bike +228 058005 37 avoidable dislocate qualify +229 058006 37 drains monochromatic detained +230 058007 37 detectably batting commended +231 058101 37 husky postcondition civilize +232 058102 37 impelling catalog Elmhurst +233 058103 37 undoes Remus anesthetizing +234 058105 37 evened devices deaf +235 058111 37 squeezes bike Brigham +236 058112 37 destroyer qualify title +237 058113 37 rudeness detained coarse +238 058114 37 beaner commended combinations +239 058115 37 boorish civilize grayness +240 058116 37 Everhart Elmhurst innumerable +241 058117 37 encompass anesthetizing Caroline +242 058118 37 mushrooms deaf fatty +243 058119 37 Alison Brigham eastbound +244 058120 37 externally title inexperienced +245 058121 37 pellagra coarse hoarder +246 058122 37 cult combinations scotch +247 058123 37 creek grayness passport +248 058124 37 Huffman innumerable strategic +249 058125 37 Majorca Caroline gated +250 058126 37 governing fatty flog +251 058127 37 gadfly eastbound Pipestone +252 058128 37 reassigned inexperienced Dar +253 058201 37 intentness hoarder Corcoran +254 058202 37 craziness scotch flyers +255 058303 37 psychic passport competitions +256 058304 37 squabbled strategic suppliers +257 058602 37 burlesque gated skips +258 058603 37 capped flog institutes +259 058604 37 extracted Pipestone troop +260 058605 37 DiMaggio Dar connective +261 058606 37 exclamation Corcoran denies +262 058607 37 subdirectory flyers polka +263 060401 36 fangs competitions observations +264 061701 36 buyer suppliers askers +265 066201 36 pithing skips homeless +266 066501 36 transistorizing institutes Anna +267 068001 36 nonbiodegradable troop subdirectories +268 068002 36 dislocate connective decaying +269 068005 36 monochromatic denies outwitting +270 068006 36 batting polka Harpy +271 068007 36 postcondition observations crazed +272 068008 36 catalog askers suffocate +273 068009 36 Remus homeless provers +274 068010 36 devices Anna technically +275 068011 36 bike subdirectories Franklinizations +276 068202 36 qualify decaying considered +277 068302 36 detained outwitting tinnily +278 068303 36 commended Harpy uninterruptedly +279 068401 36 civilize crazed whistled +280 068501 36 Elmhurst suffocate automate +281 068502 36 anesthetizing provers gutting +282 068503 36 deaf technically surreptitious +283 068602 36 Brigham Franklinizations Choctaw +284 068603 36 title considered cooks +285 068701 36 coarse tinnily millivolt +286 068702 36 combinations uninterruptedly counterpoise +287 068703 36 grayness whistled Gothicism +288 076001 36 innumerable automate feminine +289 076002 36 Caroline gutting metaphysically +290 076101 36 fatty surreptitious sanding +291 076102 36 eastbound Choctaw contributorily +292 076103 36 inexperienced cooks receivers +293 076302 36 hoarder millivolt adjourn +294 076303 36 scotch counterpoise straggled +295 076304 36 passport Gothicism druggists +296 076305 36 strategic feminine thanking +297 076306 36 gated metaphysically ostrich +298 076307 36 flog sanding hopelessness +299 076402 36 Pipestone contributorily Eurydice +300 076501 36 Dar receivers excitation +301 076502 36 Corcoran adjourn presumes +302 076701 36 flyers straggled imaginable +303 078001 36 competitions druggists concoct +304 078002 36 suppliers thanking peering +305 078003 36 skips ostrich Phelps +306 078004 36 institutes hopelessness ferociousness +307 078005 36 troop Eurydice sentences +308 078006 36 connective excitation unlocks +309 078007 36 denies presumes engrossing +310 078008 36 polka imaginable Ruth +311 078101 36 observations concoct tying +312 078103 36 askers peering exclaimers +313 078104 36 homeless Phelps synergy +314 078105 36 Anna ferociousness Huey +315 082101 36 subdirectories sentences merging +316 083401 36 decaying unlocks judges +317 084001 36 outwitting engrossing Shylock +318 084002 36 Harpy Ruth Miltonism +319 086001 36 crazed tying hen +320 086102 36 suffocate exclaimers honeybee +321 086201 36 provers synergy towers +322 088001 36 technically Huey dilutes +323 088002 36 Franklinizations merging numerals +324 088003 36 considered judges democracy +325 088004 36 tinnily Shylock Ibero- +326 088101 36 uninterruptedly Miltonism invalids +327 088102 36 whistled hen behavior +328 088103 36 automate honeybee accruing +329 088104 36 gutting towers relics +330 088105 36 surreptitious dilutes rackets +331 088106 36 Choctaw numerals Fischbein +332 088201 36 cooks democracy phony +333 088203 36 millivolt Ibero- cross +334 088204 36 counterpoise invalids cleanup +335 088302 37 Gothicism behavior conspirator +336 088303 37 feminine accruing label +337 088305 37 metaphysically relics university +338 088402 37 sanding rackets cleansed +339 088501 36 contributorily Fischbein ballgown +340 088502 36 receivers phony starlet +341 088503 36 adjourn cross aqueous +342 098001 58 straggled cleanup portrayal +343 098002 58 druggists conspirator despising +344 098003 58 thanking label distort +345 098004 58 ostrich university palmed +346 098005 58 hopelessness cleansed faced +347 098006 58 Eurydice ballgown silverware +348 141903 29 excitation starlet assessor +349 098008 58 presumes aqueous spiders +350 098009 58 imaginable portrayal artificially +351 098010 58 concoct despising reminiscence +352 098011 58 peering distort Mexican +353 098012 58 Phelps palmed obnoxious +354 098013 58 ferociousness faced fragile +355 098014 58 sentences silverware apprehensible +356 098015 58 unlocks assessor births +357 098016 58 engrossing spiders garages +358 098017 58 Ruth artificially panty +359 098018 58 tying reminiscence anteater +360 098019 58 exclaimers Mexican displacement +361 098020 58 synergy obnoxious drovers +362 098021 58 Huey fragile patenting +363 098022 58 merging apprehensible far +364 098023 58 judges births shrieks +365 098024 58 Shylock garages aligning +366 098025 37 Miltonism panty pragmatism +367 106001 36 hen anteater fevers +368 108001 36 honeybee displacement reexamines +369 108002 36 towers drovers occupancies +370 108003 36 dilutes patenting sweats +371 108004 36 numerals far modulators +372 108005 36 democracy shrieks demand +373 108007 36 Ibero- aligning Madeira +374 108008 36 invalids pragmatism Viennese +375 108009 36 behavior fevers chillier +376 108010 36 accruing reexamines wildcats +377 108011 36 relics occupancies gentle +378 108012 36 rackets sweats Angles +379 108101 36 Fischbein modulators accuracies +380 108102 36 phony demand toggle +381 108103 36 cross Madeira Mendelssohn +382 108111 50 cleanup Viennese behaviorally +383 108105 36 conspirator chillier Rochford +384 108106 36 label wildcats mirror +385 108107 36 university gentle Modula +386 108108 50 cleansed Angles clobbering +387 108109 36 ballgown accuracies chronography +388 108110 36 starlet toggle Eskimoizeds +389 108201 36 aqueous Mendelssohn British +390 108202 36 portrayal behaviorally pitfalls +391 108203 36 despising Rochford verify +392 108204 36 distort mirror scatter +393 108205 36 palmed Modula Aztecan +394 108301 36 faced clobbering acuity +395 108302 36 silverware chronography sinking +396 112101 36 assessor Eskimoizeds beasts +397 112102 36 spiders British Witt +398 113701 36 artificially pitfalls physicists +399 116001 36 reminiscence verify folksong +400 116201 36 Mexican scatter strokes +401 116301 36 obnoxious Aztecan crowder +402 116302 36 fragile acuity merry +403 116601 36 apprehensible sinking cadenced +404 116602 36 births beasts alimony +405 116603 36 garages Witt principled +406 116701 36 panty physicists golfing +407 116702 36 anteater folksong undiscovered +408 118001 36 displacement strokes irritates +409 118002 36 drovers crowder patriots +410 118003 36 patenting merry rooms +411 118004 36 far cadenced towering +412 118005 36 shrieks alimony displease +413 118006 36 aligning principled photosensitive +414 118007 36 pragmatism golfing inking +415 118008 36 fevers undiscovered gainers +416 118101 36 reexamines irritates leaning +417 118102 36 occupancies patriots hydrant +418 118103 36 sweats rooms preserve +419 118202 36 modulators towering blinded +420 118203 36 demand displease interactions +421 118204 36 Madeira photosensitive Barry +422 118302 36 Viennese inking whiteness +423 118304 36 chillier gainers pastimes +424 118305 36 wildcats leaning Edenization +425 118306 36 gentle hydrant Muscat +426 118307 36 Angles preserve assassinated +427 123101 36 accuracies blinded labeled +428 123102 36 toggle interactions glacial +429 123301 36 Mendelssohn Barry implied +430 126001 36 behaviorally whiteness bibliographies +431 126002 36 Rochford pastimes Buchanan +432 126003 36 mirror Edenization forgivably +433 126101 36 Modula Muscat innuendo +434 126301 36 clobbering assassinated den +435 126302 36 chronography labeled submarines +436 126402 36 Eskimoizeds glacial mouthful +437 126601 36 British implied expiring +438 126602 36 pitfalls bibliographies unfulfilled +439 126702 36 verify Buchanan precession +440 128001 36 scatter forgivably nullified +441 128002 36 Aztecan innuendo affects +442 128003 36 acuity den Cynthia +443 128004 36 sinking submarines Chablis +444 128005 36 beasts mouthful betterments +445 128007 36 Witt expiring advertising +446 128008 36 physicists unfulfilled rubies +447 128009 36 folksong precession southwest +448 128010 36 strokes nullified superstitious +449 128011 36 crowder affects tabernacle +450 128012 36 merry Cynthia silk +451 128013 36 cadenced Chablis handsomest +452 128014 36 alimony betterments Persian +453 128015 36 principled advertising analog +454 128016 36 golfing rubies complex +455 128017 36 undiscovered southwest Taoist +456 128018 36 irritates superstitious suspend +457 128019 36 patriots tabernacle relegated +458 128020 36 rooms silk awesome +459 128021 36 towering handsomest Bruxelles +460 128022 36 displease Persian imprecisely +461 128023 36 photosensitive analog televise +462 128101 36 inking complex braking +463 128102 36 gainers Taoist true +464 128103 36 leaning suspend disappointing +465 128104 36 hydrant relegated navally +466 128106 36 preserve awesome circus +467 128107 36 blinded Bruxelles beetles +468 128108 36 interactions imprecisely trumps +469 128202 36 Barry televise fourscore +470 128203 36 whiteness braking Blackfoots +471 128301 36 pastimes true Grady +472 128302 36 Edenization disappointing quiets +473 128303 36 Muscat navally floundered +474 128304 36 assassinated circus profundity +475 128305 36 labeled beetles Garrisonian +476 128307 36 glacial trumps Strauss +477 128401 36 implied fourscore cemented +478 128502 36 bibliographies Blackfoots contrition +479 128503 36 Buchanan Grady mutations +480 128504 36 forgivably quiets exhibits +481 128505 36 innuendo floundered tits +482 128601 36 den profundity mate +483 128603 36 submarines Garrisonian arches +484 128604 36 mouthful Strauss Moll +485 128702 36 expiring cemented ropers +486 128703 36 unfulfilled contrition bombast +487 128704 36 precession mutations difficultly +488 138001 36 nullified exhibits adsorption +489 138002 36 affects tits definiteness +490 138003 36 Cynthia mate cultivation +491 138004 36 Chablis arches heals +492 138005 36 betterments Moll Heusen +493 138006 36 advertising ropers target +494 138007 36 rubies bombast cited +495 138008 36 southwest difficultly congresswoman +496 138009 36 superstitious adsorption Katherine +497 138102 36 tabernacle definiteness titter +498 138103 36 silk cultivation aspire +499 138104 36 handsomest heals Mardis +500 138105 36 Persian Heusen Nadia +501 138201 36 analog target estimating +502 138302 36 complex cited stuck +503 138303 36 Taoist congresswoman fifteenth +504 138304 36 suspend Katherine Colombo +505 138401 29 relegated titter survey +506 140102 29 awesome aspire staffing +507 140103 29 Bruxelles Mardis obtain +508 140104 29 imprecisely Nadia loaded +509 140105 29 televise estimating slaughtered +510 140201 29 braking stuck lights +511 140701 29 true fifteenth circumference +512 141501 29 disappointing Colombo dull +513 141502 29 navally survey weekly +514 141901 29 circus staffing wetness +515 141902 29 beetles obtain visualized +516 142101 29 trumps loaded Tannenbaum +517 142102 29 fourscore slaughtered moribund +518 142103 29 Blackfoots lights demultiplex +519 142701 29 Grady circumference lockings +520 143001 29 quiets dull thugs +521 143501 29 floundered weekly unnerves +522 143502 29 profundity wetness abut +523 148001 29 Garrisonian visualized Chippewa +524 148002 29 Strauss Tannenbaum stratifications +525 148003 29 cemented moribund signaled +526 148004 29 contrition demultiplex Italianizes +527 148005 29 mutations lockings algorithmic +528 148006 29 exhibits thugs paranoid +529 148007 29 tits unnerves camping +530 148009 29 mate abut signifying +531 148010 29 arches Chippewa Patrice +532 148011 29 Moll stratifications search +533 148012 29 ropers signaled Angeles +534 148013 29 bombast Italianizes semblance +535 148023 36 difficultly algorithmic taxed +536 148015 29 adsorption paranoid Beatrice +537 148016 29 definiteness camping retrace +538 148017 29 cultivation signifying lockout +539 148018 29 heals Patrice grammatic +540 148019 29 Heusen search helmsman +541 148020 29 target Angeles uniform +542 148021 29 cited semblance hamming +543 148022 29 congresswoman taxed disobedience +544 148101 29 Katherine Beatrice captivated +545 148102 29 titter retrace transferals +546 148201 29 aspire lockout cartographer +547 148401 29 Mardis grammatic aims +548 148402 29 Nadia helmsman Pakistani +549 148501 29 estimating uniform burglarized +550 148502 29 stuck hamming saucepans +551 148503 29 fifteenth disobedience lacerating +552 148504 29 Colombo captivated corny +553 148601 29 survey transferals megabytes +554 148602 29 staffing cartographer chancellor +555 150701 29 obtain aims bulk +556 152101 29 loaded Pakistani commits +557 152102 29 slaughtered burglarized meson +558 155202 36 lights saucepans deputies +559 155203 29 circumference lacerating northeaster +560 155204 29 dull corny dipole +561 155205 29 weekly megabytes machining +562 156001 29 wetness chancellor therefore +563 156002 29 visualized bulk Telefunken +564 156102 29 Tannenbaum commits salvaging +565 156301 29 moribund meson Corinthianizes +566 156302 29 demultiplex deputies restlessly +567 156303 29 lockings northeaster bromides +568 156304 29 thugs dipole generalized +569 156305 29 unnerves machining mishaps +570 156306 29 abut therefore quelling +571 156501 29 Chippewa Telefunken spiritual +572 158001 29 stratifications salvaging beguiles +573 158002 29 signaled Corinthianizes Trobriand +574 158101 29 Italianizes restlessly fleeing +575 158102 29 algorithmic bromides Armour +576 158103 29 paranoid generalized chin +577 158201 29 camping mishaps provers +578 158202 29 signifying quelling aeronautic +579 158203 29 Patrice spiritual voltage +580 158204 29 search beguiles sash +581 158301 29 Angeles Trobriand anaerobic +582 158302 29 semblance fleeing simultaneous +583 158303 29 taxed Armour accumulating +584 158304 29 Beatrice chin Medusan +585 158305 29 retrace provers shouted +586 158306 29 lockout aeronautic freakish +587 158501 29 grammatic voltage index +588 160301 29 helmsman sash commercially +589 166101 50 uniform anaerobic mistiness +590 166102 50 hamming simultaneous endpoint +591 168001 29 disobedience accumulating straight +592 168002 29 captivated Medusan flurried +593 168003 29 transferals shouted denotative +594 168101 29 cartographer freakish coming +595 168102 29 aims index commencements +596 168103 29 Pakistani commercially gentleman +597 168104 29 burglarized mistiness gifted +598 168202 29 saucepans endpoint Shanghais +599 168301 29 lacerating straight sportswriting +600 168502 29 corny flurried sloping +601 168503 29 megabytes denotative navies +602 168601 29 chancellor coming leaflet +603 173001 40 bulk commencements shooter +604 173701 40 commits gentleman Joplin +605 173702 40 meson gifted babies +606 176001 40 deputies Shanghais subdivision +607 176101 40 northeaster sportswriting burstiness +608 176201 40 dipole sloping belted +609 176401 40 machining navies assails +610 176501 40 therefore leaflet admiring +611 176601 40 Telefunken shooter swaying +612 176602 40 salvaging Joplin Goldstine +613 176603 40 Corinthianizes babies fitting +614 178001 40 restlessly subdivision Norwalk +615 178002 40 bromides burstiness weakening +616 178003 40 generalized belted analogy +617 178004 40 mishaps assails deludes +618 178005 40 quelling admiring cokes +619 178006 40 spiritual swaying Clayton +620 178007 40 beguiles Goldstine exhausts +621 178008 40 Trobriand fitting causality +622 178101 40 fleeing Norwalk sating +623 178102 40 Armour weakening icon +624 178103 40 chin analogy throttles +625 178201 40 provers deludes communicants +626 178202 40 aeronautic cokes dehydrate +627 178301 40 voltage Clayton priceless +628 178302 40 sash exhausts publicly +629 178401 40 anaerobic causality incidentals +630 178402 40 simultaneous sating commonplace +631 178403 40 accumulating icon mumbles +632 178404 40 Medusan throttles furthermore +633 178501 40 shouted communicants cautioned +634 186002 37 freakish dehydrate parametrized +635 186102 37 index priceless registration +636 186201 40 commercially publicly sadly +637 186202 40 mistiness incidentals positioning +638 186203 40 endpoint commonplace babysitting +639 186302 37 straight mumbles eternal +640 188007 37 flurried furthermore hoarder +641 188008 37 denotative cautioned congregates +642 188009 37 coming parametrized rains +643 188010 37 commencements registration workers +644 188011 37 gentleman sadly sags +645 188012 37 gifted positioning unplug +646 188013 37 Shanghais babysitting garage +647 188014 37 sportswriting eternal boulder +648 188015 37 sloping hoarder hollowly +649 188016 37 navies congregates specifics +650 188017 37 leaflet rains Teresa +651 188102 37 shooter workers Winsett +652 188103 37 Joplin sags convenient +653 188202 37 babies unplug buckboards +654 188301 40 subdivision garage amenities +655 188302 40 burstiness boulder resplendent +656 188303 40 belted hollowly priding +657 188401 37 assails specifics configurations +658 188402 37 admiring Teresa untidiness +659 188503 37 swaying Winsett Brice +660 188504 37 Goldstine convenient sews +661 188505 37 fitting buckboards participated +662 190701 37 Norwalk amenities Simon +663 190703 50 weakening resplendent certificates +664 191701 37 analogy priding Fitzpatrick +665 191702 37 deludes configurations Evanston +666 191703 37 cokes untidiness misted +667 196001 37 Clayton Brice textures +668 196002 37 exhausts sews save +669 196003 37 causality participated count +670 196101 37 sating Simon rightful +671 196103 37 icon certificates chaperone +672 196104 37 throttles Fitzpatrick Lizzy +673 196201 37 communicants Evanston clenched +674 196202 37 dehydrate misted effortlessly +675 196203 37 priceless textures accessed +676 198001 37 publicly save beaters +677 198003 37 incidentals count Hornblower +678 198004 37 commonplace rightful vests +679 198005 37 mumbles chaperone indulgences +680 198006 37 furthermore Lizzy infallibly +681 198007 37 cautioned clenched unwilling +682 198008 37 parametrized effortlessly excrete +683 198009 37 registration accessed spools +684 198010 37 sadly beaters crunches +685 198011 37 positioning Hornblower overestimating +686 198012 37 babysitting vests ineffective +687 198013 37 eternal indulgences humiliation +688 198014 37 hoarder infallibly sophomore +689 198015 37 congregates unwilling star +690 198017 37 rains excrete rifles +691 198018 37 workers spools dialysis +692 198019 37 sags crunches arriving +693 198020 37 unplug overestimating indulge +694 198021 37 garage ineffective clockers +695 198022 37 boulder humiliation languages +696 198023 50 hollowly sophomore Antarctica +697 198024 37 specifics star percentage +698 198101 37 Teresa rifles ceiling +699 198103 37 Winsett dialysis specification +700 198105 37 convenient arriving regimented +701 198106 37 buckboards indulge ciphers +702 198201 37 amenities clockers pictures +703 198204 37 resplendent languages serpents +704 198301 53 priding Antarctica allot +705 198302 53 configurations percentage realized +706 198303 53 untidiness ceiling mayoral +707 198304 53 Brice specification opaquely +708 198401 37 sews regimented hostess +709 198402 37 participated ciphers fiftieth +710 198403 37 Simon pictures incorrectly +711 202101 37 certificates serpents decomposition +712 202301 37 Fitzpatrick allot stranglings +713 202302 37 Evanston realized mixture +714 202303 37 misted mayoral electroencephalography +715 202304 37 textures opaquely similarities +716 202305 37 save hostess charges +717 202601 37 count fiftieth freest +718 202602 37 rightful incorrectly Greenberg +719 202605 37 chaperone decomposition tinting +720 202606 37 Lizzy stranglings expelled +721 202607 37 clenched mixture warm +722 202901 37 effortlessly electroencephalography smoothed +723 202902 37 accessed similarities deductions +724 202903 37 beaters charges Romano +725 202904 37 Hornblower freest bitterroot +726 202907 37 vests Greenberg corset +727 202908 37 indulgences tinting securing +728 203101 37 infallibly expelled environing +729 203103 37 unwilling warm cute +730 203104 37 excrete smoothed Crays +731 203105 37 spools deductions heiress +732 203401 37 crunches Romano inform +733 203402 37 overestimating bitterroot avenge +734 203404 37 ineffective corset universals +735 203901 37 humiliation securing Kinsey +736 203902 37 sophomore environing ravines +737 203903 37 star cute bestseller +738 203906 37 rifles Crays equilibrium +739 203907 37 dialysis heiress extents +740 203908 37 arriving inform relatively +741 203909 37 indulge avenge pressure +742 206101 37 clockers universals critiques +743 206201 37 languages Kinsey befouled +744 206202 37 Antarctica ravines rightfully +745 206203 37 percentage bestseller mechanizing +746 206206 37 ceiling equilibrium Latinizes +747 206207 37 specification extents timesharing +748 206208 37 regimented relatively Aden +749 208001 37 ciphers pressure embassies +750 208002 37 pictures critiques males +751 208003 37 serpents befouled shapelessly +752 208004 37 allot rightfully genres +753 208008 37 realized mechanizing mastering +754 208009 37 mayoral Latinizes Newtonian +755 208010 37 opaquely timesharing finishers +756 208011 37 hostess Aden abates +757 208101 37 fiftieth embassies teem +758 208102 37 incorrectly males kiting +759 208103 37 decomposition shapelessly stodgy +760 208104 37 stranglings genres scalps +761 208105 37 mixture mastering feed +762 208110 37 electroencephalography Newtonian guitars +763 208111 37 similarities finishers airships +764 208112 37 charges abates store +765 208113 37 freest teem denounces +766 208201 37 Greenberg kiting Pyle +767 208203 37 tinting stodgy Saxony +768 208301 37 expelled scalps serializations +769 208302 37 warm feed Peruvian +770 208305 37 smoothed guitars taxonomically +771 208401 37 deductions airships kingdom +772 208402 37 Romano store stint +773 208403 37 bitterroot denounces Sault +774 208404 37 corset Pyle faithful +775 208501 37 securing Saxony Ganymede +776 208502 37 environing serializations tidiness +777 208503 37 cute Peruvian gainful +778 208504 37 Crays taxonomically contrary +779 208505 37 heiress kingdom Tipperary +780 210101 37 inform stint tropics +781 210102 37 avenge Sault theorizers +782 210103 37 universals faithful renew +783 210104 37 Kinsey Ganymede already +784 210105 37 ravines tidiness terminal +785 210106 37 bestseller gainful Hegelian +786 210107 37 equilibrium contrary hypothesizer +787 210401 37 extents Tipperary warningly +788 213201 37 relatively tropics journalizing +789 213203 37 pressure theorizers nested +790 213204 37 critiques renew Lars +791 213205 37 befouled already saplings +792 213206 37 rightfully terminal foothill +793 213207 37 mechanizing Hegelian labeled +794 216101 37 Latinizes hypothesizer imperiously +795 216103 37 timesharing warningly reporters +796 218001 37 Aden journalizing furnishings +797 218002 37 embassies nested precipitable +798 218003 37 males Lars discounts +799 218004 37 shapelessly saplings excises +800 143503 50 genres foothill Stalin +801 218006 37 mastering labeled despot +802 218007 37 Newtonian imperiously ripeness +803 218008 37 finishers reporters Arabia +804 218009 37 abates furnishings unruly +805 218010 37 teem precipitable mournfulness +806 218011 37 kiting discounts boom +807 218020 37 stodgy excises slaughter +808 218021 50 scalps Stalin Sabine +809 218022 37 feed despot handy +810 218023 37 guitars ripeness rural +811 218024 37 airships Arabia organizer +812 218101 37 store unruly shipyard +813 218102 37 denounces mournfulness civics +814 218103 37 Pyle boom inaccuracy +815 218201 37 Saxony slaughter rules +816 218202 37 serializations Sabine juveniles +817 218203 37 Peruvian handy comprised +818 218204 37 taxonomically rural investigations +819 218205 37 kingdom organizer stabilizes +820 218301 37 stint shipyard seminaries +821 218302 37 Sault civics Hunter +822 218401 37 faithful inaccuracy sporty +823 218402 37 Ganymede rules test +824 218403 37 tidiness juveniles weasels +825 218404 37 gainful comprised CERN +826 218407 37 contrary investigations tempering +827 218408 37 Tipperary stabilizes afore +828 218409 37 tropics seminaries Galatean +829 218410 37 theorizers Hunter techniques +830 226001 37 renew sporty error +831 226002 37 already test veranda +832 226003 37 terminal weasels severely +833 226004 37 Hegelian CERN Cassites +834 226005 37 hypothesizer tempering forthcoming +835 226006 37 warningly afore guides +836 226007 37 journalizing Galatean vanish +837 226008 37 nested techniques lied +838 226203 37 Lars error sawtooth +839 226204 37 saplings veranda fated +840 226205 37 foothill severely gradually +841 226206 37 labeled Cassites widens +842 226207 37 imperiously forthcoming preclude +843 226208 37 reporters guides Jobrel +844 226209 37 furnishings vanish hooker +845 226210 37 precipitable lied rainstorm +846 226211 37 discounts sawtooth disconnects +847 228001 37 excises fated cruelty +848 228004 37 Stalin gradually exponentials +849 228005 37 despot widens affective +850 228006 37 ripeness preclude arteries +851 228007 37 Arabia Jobrel Crosby +852 228008 37 unruly hooker acquaint +853 228009 37 mournfulness rainstorm evenhandedly +854 228101 37 boom disconnects percentage +855 228108 37 slaughter cruelty disobedience +856 228109 37 Sabine exponentials humility +857 228110 37 handy affective gleaning +858 228111 37 rural arteries petted +859 228112 37 organizer Crosby bloater +860 228113 37 shipyard acquaint minion +861 228114 37 civics evenhandedly marginal +862 228115 37 inaccuracy percentage apiary +863 228116 37 rules disobedience measures +864 228117 37 juveniles humility precaution +865 228118 37 comprised gleaning repelled +866 228119 37 investigations petted primary +867 228120 37 stabilizes bloater coverings +868 228121 37 seminaries minion Artemia +869 228122 37 Hunter marginal navigate +870 228201 37 sporty apiary spatial +871 228206 37 test measures Gurkha +872 228207 37 weasels precaution meanwhile +873 228208 37 CERN repelled Melinda +874 228209 37 tempering primary Butterfield +875 228210 37 afore coverings Aldrich +876 228211 37 Galatean Artemia previewing +877 228212 37 techniques navigate glut +878 228213 37 error spatial unaffected +879 228214 37 veranda Gurkha inmate +880 228301 37 severely meanwhile mineral +881 228305 37 Cassites Melinda impending +882 228306 37 forthcoming Butterfield meditation +883 228307 37 guides Aldrich ideas +884 228308 37 vanish previewing miniaturizes +885 228309 37 lied glut lewdly +886 228310 37 sawtooth unaffected title +887 228311 37 fated inmate youthfulness +888 228312 37 gradually mineral creak +889 228313 37 widens impending Chippewa +890 228314 37 preclude meditation clamored +891 228401 65 Jobrel ideas freezes +892 228402 65 hooker miniaturizes forgivably +893 228403 65 rainstorm lewdly reduce +894 228404 65 disconnects title McGovern +895 228405 65 cruelty youthfulness Nazis +896 228406 65 exponentials creak epistle +897 228407 65 affective Chippewa socializes +898 228408 65 arteries clamored conceptions +899 228409 65 Crosby freezes Kevin +900 228410 65 acquaint forgivably uncovering +901 230301 37 evenhandedly reduce chews +902 230302 37 percentage McGovern appendixes +903 230303 37 disobedience Nazis raining +904 018062 37 humility epistle infest +905 230501 37 gleaning socializes compartment +906 230502 37 petted conceptions minting +907 230503 37 bloater Kevin ducks +908 230504 37 minion uncovering roped +909 230505 37 marginal chews waltz +910 230506 37 apiary appendixes Lillian +911 230507 37 measures raining repressions +912 230508 37 precaution infest chillingly +913 230509 37 repelled compartment noncritical +914 230901 37 primary minting lithograph +915 230902 37 coverings ducks spongers +916 230903 37 Artemia roped parenthood +917 230904 37 navigate waltz posed +918 230905 37 spatial Lillian instruments +919 230906 37 Gurkha repressions filial +920 230907 37 meanwhile chillingly fixedly +921 230908 37 Melinda noncritical relives +922 230909 37 Butterfield lithograph Pandora +923 230910 37 Aldrich spongers watering +924 230911 37 previewing parenthood ungrateful +925 230912 37 glut posed secures +926 230913 37 unaffected instruments chastisers +927 230914 37 inmate filial icon +928 231304 37 mineral fixedly reuniting +929 231305 37 impending relives imagining +930 231306 37 meditation Pandora abiding +931 231307 37 ideas watering omnisciently +932 231308 37 miniaturizes ungrateful Britannic +933 231309 37 lewdly secures scholastics +934 231310 37 title chastisers mechanics +935 231311 37 youthfulness icon humidly +936 231312 37 creak reuniting masterpiece +937 231313 37 Chippewa imagining however +938 231314 37 clamored abiding Mendelian +939 231315 37 freezes omnisciently jarred +940 232102 37 forgivably Britannic scolds +941 232103 37 reduce scholastics infatuate +942 232104 37 McGovern mechanics willed +943 232105 37 Nazis humidly joyfully +944 232106 37 epistle masterpiece Microsoft +945 232107 37 socializes however fibrosities +946 232108 37 conceptions Mendelian Baltimorean +947 232601 37 Kevin jarred equestrian +948 232602 37 uncovering scolds Goodrich +949 232603 37 chews infatuate apish +950 232605 37 appendixes willed Adlerian +5950 1232605 37 appendixes willed Adlerian +5951 1232606 37 appendixes willed Adlerian +5952 1232607 37 appendixes willed Adlerian +5953 1232608 37 appendixes willed Adlerian +5954 1232609 37 appendixes willed Adlerian +951 232606 37 raining joyfully Tropez +952 232607 37 infest Microsoft nouns +953 232608 37 compartment fibrosities distracting +954 232609 37 minting Baltimorean mutton +955 236104 37 ducks equestrian bridgeable +956 236105 37 roped Goodrich stickers +957 236106 37 waltz apish transcontinental +958 236107 37 Lillian Adlerian amateurish +959 236108 37 repressions Tropez Gandhian +960 236109 37 chillingly nouns stratified +961 236110 37 noncritical distracting chamberlains +962 236111 37 lithograph mutton creditably +963 236112 37 spongers bridgeable philosophic +964 236113 37 parenthood stickers ores +965 238005 37 posed transcontinental Carleton +966 238006 37 instruments amateurish tape +967 238007 37 filial Gandhian afloat +968 238008 37 fixedly stratified goodness +969 238009 37 relives chamberlains welcoming +970 238010 37 Pandora creditably Pinsky +971 238011 37 watering philosophic halting +972 238012 37 ungrateful ores bibliography +973 238013 37 secures Carleton decoding +974 240401 41 chastisers tape variance +975 240402 41 icon afloat allowed +976 240901 41 reuniting goodness dire +977 240902 41 imagining welcoming dub +978 241801 41 abiding Pinsky poisoning +979 242101 41 omnisciently halting Iraqis +980 242102 41 Britannic bibliography heaving +981 242201 41 scholastics decoding population +982 242202 41 mechanics variance bomb +983 242501 41 humidly allowed Majorca +984 242502 41 masterpiece dire Gershwins +985 246201 41 however dub explorers +986 246202 41 Mendelian poisoning libretto +987 246203 41 jarred Iraqis occurred +988 246204 41 scolds heaving Lagos +989 246205 41 infatuate population rats +990 246301 41 willed bomb bankruptcies +991 246302 41 joyfully Majorca crying +992 248001 41 Microsoft Gershwins unexpected +993 248002 41 fibrosities explorers accessed +994 248003 41 Baltimorean libretto colorful +995 248004 41 equestrian occurred versatility +996 248005 41 Goodrich Lagos cosy +997 248006 41 apish rats Darius +998 248007 41 Adlerian bankruptcies mastering +999 248008 41 Tropez crying Asiaticizations +1000 248009 41 nouns unexpected offerers +1001 248010 41 distracting accessed uncles +1002 248011 41 mutton colorful sleepwalk +1003 248012 41 bridgeable versatility Ernestine +1004 248013 41 stickers cosy checksumming +1005 248014 41 transcontinental Darius stopped +1006 248015 41 amateurish mastering sicker +1007 248016 41 Gandhian Asiaticizations Italianization +1008 248017 41 stratified offerers alphabetic +1009 248018 41 chamberlains uncles pharmaceutic +1010 248019 41 creditably sleepwalk creator +1011 248020 41 philosophic Ernestine chess +1012 248021 41 ores checksumming charcoal +1013 248101 41 Carleton stopped Epiphany +1014 248102 41 tape sicker bulldozes +1015 248201 41 afloat Italianization Pygmalion +1016 248202 41 goodness alphabetic caressing +1017 248203 41 welcoming pharmaceutic Palestine +1018 248204 41 Pinsky creator regimented +1019 248205 41 halting chess scars +1020 248206 41 bibliography charcoal realest +1021 248207 41 decoding Epiphany diffusing +1022 248208 41 variance bulldozes clubroom +1023 248209 41 allowed Pygmalion Blythe +1024 248210 41 dire caressing ahead +1025 248211 50 dub Palestine reviver +1026 250501 34 poisoning regimented retransmitting +1027 250502 34 Iraqis scars landslide +1028 250503 34 heaving realest Eiffel +1029 250504 34 population diffusing absentee +1030 250505 34 bomb clubroom aye +1031 250601 34 Majorca Blythe forked +1032 250602 34 Gershwins ahead Peruvianizes +1033 250603 34 explorers reviver clerked +1034 250604 34 libretto retransmitting tutor +1035 250605 34 occurred landslide boulevard +1036 251001 34 Lagos Eiffel shuttered +1037 251002 34 rats absentee quotes +1038 251003 34 bankruptcies aye Caltech +1039 251004 34 crying forked Mossberg +1040 251005 34 unexpected Peruvianizes kept +1041 251301 34 accessed clerked roundly +1042 251302 34 colorful tutor features +1043 251303 34 versatility boulevard imaginable +1044 251304 34 cosy shuttered controller +1045 251305 34 Darius quotes racial +1046 251401 34 mastering Caltech uprisings +1047 251402 34 Asiaticizations Mossberg narrowed +1048 251403 34 offerers kept cannot +1049 251404 34 uncles roundly vest +1050 251405 34 sleepwalk features famine +1051 251406 34 Ernestine imaginable sugars +1052 251801 34 checksumming controller exterminated +1053 251802 34 stopped racial belays +1054 252101 34 sicker uprisings Hodges +1055 252102 34 Italianization narrowed translatable +1056 252301 34 alphabetic cannot duality +1057 252302 34 pharmaceutic vest recording +1058 252303 34 creator famine rouses +1059 252304 34 chess sugars poison +1060 252305 34 charcoal exterminated attitude +1061 252306 34 Epiphany belays dusted +1062 252307 34 bulldozes Hodges encompasses +1063 252308 34 Pygmalion translatable presentation +1064 252309 34 caressing duality Kantian +1065 256001 34 Palestine recording imprecision +1066 256002 34 regimented rouses saving +1067 256003 34 scars poison maternal +1068 256004 34 realest attitude hewed +1069 256005 34 diffusing dusted kerosene +1070 258001 34 clubroom encompasses Cubans +1071 258002 34 Blythe presentation photographers +1072 258003 34 ahead Kantian nymph +1073 258004 34 reviver imprecision bedlam +1074 258005 34 retransmitting saving north +1075 258006 34 landslide maternal Schoenberg +1076 258007 34 Eiffel hewed botany +1077 258008 34 absentee kerosene curs +1078 258009 34 aye Cubans solidification +1079 258010 34 forked photographers inheritresses +1080 258011 34 Peruvianizes nymph stiller +1081 258101 68 clerked bedlam t1 +1082 258102 68 tutor north suite +1083 258103 34 boulevard Schoenberg ransomer +1084 258104 68 shuttered botany Willy +1085 258105 68 quotes curs Rena +1086 258106 68 Caltech solidification Seattle +1087 258107 68 Mossberg inheritresses relaxes +1088 258108 68 kept stiller exclaim +1089 258109 68 roundly t1 implicated +1090 258110 68 features suite distinguish +1091 258111 68 imaginable ransomer assayed +1092 258112 68 controller Willy homeowner +1093 258113 68 racial Rena and +1094 258201 34 uprisings Seattle stealth +1095 258202 34 narrowed relaxes coinciding +1096 258203 34 cannot exclaim founder +1097 258204 34 vest implicated environing +1098 258205 34 famine distinguish jewelry +1099 258301 34 sugars assayed lemons +1100 258401 34 exterminated homeowner brokenness +1101 258402 34 belays and bedpost +1102 258403 34 Hodges stealth assurers +1103 258404 34 translatable coinciding annoyers +1104 258405 34 duality founder affixed +1105 258406 34 recording environing warbling +1106 258407 34 rouses jewelry seriously +1107 228123 37 poison lemons boasted +1108 250606 34 attitude brokenness Chantilly +1109 208405 37 dusted bedpost Iranizes +1110 212101 37 encompasses assurers violinist +1111 218206 37 presentation annoyers extramarital +1112 150401 37 Kantian affixed spates +1113 248212 41 imprecision warbling cloakroom +1114 128026 00 saving seriously gazer +1115 128024 00 maternal boasted hand +1116 128027 00 hewed Chantilly tucked +1117 128025 00 kerosene Iranizes gems +1118 128109 00 Cubans violinist clinker +1119 128705 00 photographers extramarital refiner +1120 126303 00 nymph spates callus +1121 128308 00 bedlam cloakroom leopards +1122 128204 00 north gazer comfortingly +1123 128205 00 Schoenberg hand generically +1124 128206 00 botany tucked getters +1125 128207 00 curs gems sexually +1126 118205 00 solidification clinker spear +1127 116801 00 inheritresses refiner serums +1128 116803 00 stiller callus Italianization +1129 116804 00 t1 leopards attendants +1130 116802 00 suite comfortingly spies +1131 128605 00 ransomer generically Anthony +1132 118308 00 Willy getters planar +1133 113702 00 Rena sexually cupped +1134 113703 00 Seattle spear cleanser +1135 112103 00 relaxes serums commuters +1136 118009 00 exclaim Italianization honeysuckle +5136 1118009 00 exclaim Italianization honeysuckle +1137 138011 00 implicated attendants orphanage +1138 138010 00 distinguish spies skies +1139 138012 00 assayed Anthony crushers +1140 068304 00 homeowner planar Puritan +1141 078009 00 and cupped squeezer +1142 108013 00 stealth cleanser bruises +1143 084004 00 coinciding commuters bonfire +1144 083402 00 founder honeysuckle Colombo +1145 084003 00 environing orphanage nondecreasing +1146 088504 00 jewelry skies innocents +1147 088005 00 lemons crushers masked +1148 088007 00 brokenness Puritan file +1149 088006 00 bedpost squeezer brush +1150 148025 00 assurers bruises mutilate +1151 148024 00 annoyers bonfire mommy +1152 138305 00 affixed Colombo bulkheads +1153 138306 00 warbling nondecreasing undeclared +1154 152701 00 seriously innocents displacements +1155 148505 00 boasted masked nieces +1156 158003 00 Chantilly file coeducation +1157 156201 00 Iranizes brush brassy +1158 156202 00 violinist mutilate authenticator +1159 158307 00 extramarital mommy Washoe +1160 158402 00 spates bulkheads penny +1161 158401 00 cloakroom undeclared Flagler +1162 068013 00 gazer displacements stoned +1163 068012 00 hand nieces cranes +1164 068203 00 tucked coeducation masterful +1165 088205 00 gems brassy biracial +1166 068704 00 clinker authenticator steamships +1167 068604 00 refiner Washoe windmills +1168 158502 00 callus penny exploit +1169 123103 00 leopards Flagler riverfront +1170 148026 00 comfortingly stoned sisterly +1171 123302 00 generically cranes sharpshoot +1172 076503 00 getters masterful mittens +1173 126304 00 sexually biracial interdependency +1174 068306 00 spear steamships policy +1175 143504 00 serums windmills unleashing +1176 160201 00 Italianization exploit pretenders +1177 148028 00 attendants riverfront overstatements +1178 148027 00 spies sisterly birthed +1179 143505 00 Anthony sharpshoot opportunism +1180 108014 00 planar mittens showroom +1181 076104 00 cupped interdependency compromisingly +1182 078106 00 cleanser policy Medicare +1183 126102 00 commuters unleashing corresponds +1184 128029 00 honeysuckle pretenders hardware +1185 128028 00 orphanage overstatements implant +1186 018410 00 skies birthed Alicia +1187 128110 00 crushers opportunism requesting +1188 148506 00 Puritan showroom produced +1189 123303 00 squeezer compromisingly criticizes +1190 123304 00 bruises Medicare backer +1191 068504 00 bonfire corresponds positively +1192 068305 00 Colombo hardware colicky +1193 000000 00 nondecreasing implant thrillingly +1 000001 00 Omaha teethe neat +2 011401 37 breaking dreaded Steinberg +3 011402 37 Romans scholastics jarring +4 011403 37 intercepted audiology tinily +2 011401 37 breaking dreaded Steinberg +3 011402 37 Romans scholastics jarring +4 011403 37 intercepted audiology tinily +1 000001 00 Omaha teethe neat +2 011401 37 breaking dreaded Steinberg +3 011402 37 Romans scholastics jarring +4 011403 37 intercepted audiology tinily +2 011401 37 breaking dreaded Steinberg +3 011402 37 Romans scholastics jarring +4 011403 37 intercepted audiology tinily +4 011403 37 intercepted audiology tinily drop table t1, t2, t4; diff --git a/mysql-test/r/archive_gis.result b/mysql-test/r/archive_gis.result new file mode 100644 index 00000000000..25a77bc9c75 --- /dev/null +++ b/mysql-test/r/archive_gis.result @@ -0,0 +1,458 @@ +SET storage_engine=archive; +DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE gis_point (fid INTEGER, g POINT); +CREATE TABLE gis_line (fid INTEGER, g LINESTRING); +CREATE TABLE gis_polygon (fid INTEGER, g POLYGON); +CREATE TABLE gis_multi_point (fid INTEGER, g MULTIPOINT); +CREATE TABLE gis_multi_line (fid INTEGER, g MULTILINESTRING); +CREATE TABLE gis_multi_polygon (fid INTEGER, g MULTIPOLYGON); +CREATE TABLE gis_geometrycollection (fid INTEGER, g GEOMETRYCOLLECTION); +CREATE TABLE gis_geometry (fid INTEGER, g GEOMETRY); +SHOW CREATE TABLE gis_point; +Table Create Table +gis_point CREATE TABLE `gis_point` ( + `fid` int(11) default NULL, + `g` point default NULL +) ENGINE=ARCHIVE DEFAULT CHARSET=latin1 +SHOW FIELDS FROM gis_point; +Field Type Null Key Default Extra +fid int(11) YES NULL +g point YES NULL +SHOW FIELDS FROM gis_line; +Field Type Null Key Default Extra +fid int(11) YES NULL +g linestring YES NULL +SHOW FIELDS FROM gis_polygon; +Field Type Null Key Default Extra +fid int(11) YES NULL +g polygon YES NULL +SHOW FIELDS FROM gis_multi_point; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multipoint YES NULL +SHOW FIELDS FROM gis_multi_line; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multilinestring YES NULL +SHOW FIELDS FROM gis_multi_polygon; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multipolygon YES NULL +SHOW FIELDS FROM gis_geometrycollection; +Field Type Null Key Default Extra +fid int(11) YES NULL +g geometrycollection YES NULL +SHOW FIELDS FROM gis_geometry; +Field Type Null Key Default Extra +fid int(11) YES NULL +g geometry YES NULL +INSERT INTO gis_point VALUES +(101, PointFromText('POINT(10 10)')), +(102, PointFromText('POINT(20 10)')), +(103, PointFromText('POINT(20 20)')), +(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)')))); +INSERT INTO gis_line VALUES +(105, LineFromText('LINESTRING(0 0,0 10,10 0)')), +(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')), +(107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10)))); +INSERT INTO gis_polygon VALUES +(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')), +(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')), +(110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))))); +INSERT INTO gis_multi_point VALUES +(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')), +(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')), +(113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10)))); +INSERT INTO gis_multi_line VALUES +(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')), +(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')), +(116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7))))); +INSERT INTO gis_multi_polygon VALUES +(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))))); +INSERT INTO gis_geometrycollection VALUES +(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')), +(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))); +INSERT into gis_geometry SELECT * FROM gis_point; +INSERT into gis_geometry SELECT * FROM gis_line; +INSERT into gis_geometry SELECT * FROM gis_polygon; +INSERT into gis_geometry SELECT * FROM gis_multi_point; +INSERT into gis_geometry SELECT * FROM gis_multi_line; +INSERT into gis_geometry SELECT * FROM gis_multi_polygon; +INSERT into gis_geometry SELECT * FROM gis_geometrycollection; +SELECT fid, AsText(g) FROM gis_point ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +SELECT fid, AsText(g) FROM gis_line ORDER by fid; +fid AsText(g) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +SELECT fid, AsText(g) FROM gis_polygon ORDER by fid; +fid AsText(g) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +SELECT fid, AsText(g) FROM gis_multi_point ORDER by fid; +fid AsText(g) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +SELECT fid, AsText(g) FROM gis_multi_line ORDER by fid; +fid AsText(g) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +SELECT fid, AsText(g) FROM gis_multi_polygon ORDER by fid; +fid AsText(g) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +SELECT fid, AsText(g) FROM gis_geometrycollection ORDER by fid; +fid AsText(g) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, AsText(g) FROM gis_geometry ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, Dimension(g) FROM gis_geometry ORDER by fid; +fid Dimension(g) +101 0 +102 0 +103 0 +104 0 +105 1 +106 1 +107 1 +108 2 +109 2 +110 2 +111 0 +112 0 +113 0 +114 1 +115 1 +116 1 +117 2 +118 2 +119 2 +120 1 +121 1 +SELECT fid, GeometryType(g) FROM gis_geometry ORDER by fid; +fid GeometryType(g) +101 POINT +102 POINT +103 POINT +104 POINT +105 LINESTRING +106 LINESTRING +107 LINESTRING +108 POLYGON +109 POLYGON +110 POLYGON +111 MULTIPOINT +112 MULTIPOINT +113 MULTIPOINT +114 MULTILINESTRING +115 MULTILINESTRING +116 MULTILINESTRING +117 MULTIPOLYGON +118 MULTIPOLYGON +119 MULTIPOLYGON +120 GEOMETRYCOLLECTION +121 GEOMETRYCOLLECTION +SELECT fid, IsEmpty(g) FROM gis_geometry ORDER by fid; +fid IsEmpty(g) +101 0 +102 0 +103 0 +104 0 +105 0 +106 0 +107 0 +108 0 +109 0 +110 0 +111 0 +112 0 +113 0 +114 0 +115 0 +116 0 +117 0 +118 0 +119 0 +120 0 +121 0 +SELECT fid, AsText(Envelope(g)) FROM gis_geometry ORDER by fid; +fid AsText(Envelope(g)) +101 POLYGON((10 10,10 10,10 10,10 10,10 10)) +102 POLYGON((20 10,20 10,20 10,20 10,20 10)) +103 POLYGON((20 20,20 20,20 20,20 20,20 20)) +104 POLYGON((10 20,10 20,10 20,10 20,10 20)) +105 POLYGON((0 0,10 0,10 10,0 10,0 0)) +106 POLYGON((10 10,20 10,20 20,10 20,10 10)) +107 POLYGON((10 10,40 10,40 10,10 10,10 10)) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0)) +110 POLYGON((0 0,30 0,30 30,0 30,0 0)) +111 POLYGON((0 0,20 0,20 20,0 20,0 0)) +112 POLYGON((1 1,21 1,21 21,1 21,1 1)) +113 POLYGON((3 6,4 6,4 10,3 10,3 6)) +114 POLYGON((10 0,16 0,16 48,10 48,10 0)) +115 POLYGON((10 0,10 0,10 48,10 48,10 0)) +116 POLYGON((1 2,21 2,21 8,1 8,1 2)) +117 POLYGON((28 0,84 0,84 42,28 42,28 0)) +118 POLYGON((28 0,84 0,84 42,28 42,28 0)) +119 POLYGON((0 0,3 0,3 3,0 3,0 0)) +120 POLYGON((0 0,10 0,10 10,0 10,0 0)) +121 POLYGON((3 6,44 6,44 9,3 9,3 6)) +explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21 +Warnings: +Note 1003 select dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,astext(envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry` +SELECT fid, X(g) FROM gis_point ORDER by fid; +fid X(g) +101 10 +102 20 +103 20 +104 10 +SELECT fid, Y(g) FROM gis_point ORDER by fid; +fid Y(g) +101 10 +102 10 +103 20 +104 20 +explain extended select X(g),Y(g) FROM gis_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_point ALL NULL NULL NULL NULL 4 +Warnings: +Note 1003 select x(`test`.`gis_point`.`g`) AS `X(g)`,y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point` +SELECT fid, AsText(StartPoint(g)) FROM gis_line ORDER by fid; +fid AsText(StartPoint(g)) +105 POINT(0 0) +106 POINT(10 10) +107 POINT(10 10) +SELECT fid, AsText(EndPoint(g)) FROM gis_line ORDER by fid; +fid AsText(EndPoint(g)) +105 POINT(10 0) +106 POINT(10 10) +107 POINT(40 10) +SELECT fid, GLength(g) FROM gis_line ORDER by fid; +fid GLength(g) +105 24.142135623731 +106 40 +107 30 +SELECT fid, NumPoints(g) FROM gis_line ORDER by fid; +fid NumPoints(g) +105 3 +106 5 +107 2 +SELECT fid, AsText(PointN(g, 2)) FROM gis_line ORDER by fid; +fid AsText(PointN(g, 2)) +105 POINT(0 10) +106 POINT(20 10) +107 POINT(40 10) +SELECT fid, IsClosed(g) FROM gis_line ORDER by fid; +fid IsClosed(g) +105 0 +106 1 +107 0 +explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_line ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,astext(endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,glength(`test`.`gis_line`.`g`) AS `GLength(g)`,numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,astext(pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line` +SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; +fid AsText(Centroid(g)) +108 POINT(15 15) +109 POINT(25.416666666667 25.416666666667) +110 POINT(20 10) +SELECT fid, Area(g) FROM gis_polygon ORDER by fid; +fid Area(g) +108 100 +109 2400 +110 450 +SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon ORDER by fid; +fid AsText(ExteriorRing(g)) +108 LINESTRING(10 10,20 10,20 20,10 20,10 10) +109 LINESTRING(0 0,50 0,50 50,0 50,0 0) +110 LINESTRING(0 0,30 0,30 30,0 0) +SELECT fid, NumInteriorRings(g) FROM gis_polygon ORDER by fid; +fid NumInteriorRings(g) +108 0 +109 1 +110 0 +SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon ORDER by fid; +fid AsText(InteriorRingN(g, 1)) +108 NULL +109 LINESTRING(10 10,20 10,20 20,10 20,10 10) +110 NULL +explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM gis_polygon; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select astext(centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,area(`test`.`gis_polygon`.`g`) AS `Area(g)`,astext(exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,astext(interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon` +SELECT fid, IsClosed(g) FROM gis_multi_line ORDER by fid; +fid IsClosed(g) +114 0 +115 0 +116 0 +SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; +fid AsText(Centroid(g)) +117 POINT(55.588527753042 17.426536064114) +118 POINT(55.588527753042 17.426536064114) +119 POINT(2 2) +SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; +fid Area(g) +117 1684.5 +118 1684.5 +119 4.5 +SELECT fid, NumGeometries(g) from gis_multi_point ORDER by fid; +fid NumGeometries(g) +111 4 +112 4 +113 2 +SELECT fid, NumGeometries(g) from gis_multi_line ORDER by fid; +fid NumGeometries(g) +114 2 +115 1 +116 2 +SELECT fid, NumGeometries(g) from gis_multi_polygon ORDER by fid; +fid NumGeometries(g) +117 2 +118 2 +119 1 +SELECT fid, NumGeometries(g) from gis_geometrycollection ORDER by fid; +fid NumGeometries(g) +120 2 +121 2 +explain extended SELECT fid, NumGeometries(g) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point` +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point ORDER by fid; +fid AsText(GeometryN(g, 2)) +111 POINT(10 10) +112 POINT(11 11) +113 POINT(4 10) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line ORDER by fid; +fid AsText(GeometryN(g, 2)) +114 LINESTRING(16 0,16 23,16 48) +115 NULL +116 LINESTRING(2 5,5 8,21 7) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon ORDER by fid; +fid AsText(GeometryN(g, 2)) +117 POLYGON((59 18,67 18,67 13,59 13,59 18)) +118 POLYGON((59 18,67 18,67 13,59 13,59 18)) +119 NULL +SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 2)) +120 LINESTRING(0 0,10 10) +121 LINESTRING(3 6,7 9) +SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 1)) +120 POINT(0 0) +121 POINT(44 6) +explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,astext(geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point` +SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +first second w c o e d t i r +120 120 1 1 0 1 0 0 1 0 +120 121 0 0 0 0 0 0 1 0 +121 120 0 0 1 0 0 0 1 0 +121 121 1 1 0 1 0 0 1 0 +explain extended SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE g1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +1 SIMPLE g2 ALL NULL NULL NULL NULL 2 +Warnings: +Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,overlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,disjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,intersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid` +DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE t1 ( +gp point, +ln linestring, +pg polygon, +mp multipoint, +mln multilinestring, +mpg multipolygon, +gc geometrycollection, +gm geometry +); +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +ALTER TABLE t1 ADD fid INT; +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +fid int(11) YES NULL +DROP TABLE t1; +create table t1 (a geometry not null); +insert into t1 values (GeomFromText('Point(1 2)')); +insert into t1 values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert IGNORE into t1 values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; +create table t1 (fl geometry); +insert into t1 values (1); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values (1.11); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values ("qwerty"); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values (pointfromtext('point(1,1)')); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index dd251eed0f0..af6319afe99 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -1289,6 +1289,25 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd"); id 4 DROP TABLE t1; +create table t1 (a int, key(a)) engine=bdb; +create table t2 (b int, key(b)) engine=bdb; +insert into t1 values (1),(1),(2),(3),(4); +insert into t2 values (1),(5),(6),(7); +delete from t1 where (a in (select b from t2)); +select count(*) from t1; +count(*) +3 +insert into t1 set a=(select b from t2); +ERROR 21000: Subquery returns more than 1 row +select count(*) from t1; +count(*) +3 +update t1 set a = a + 1 where (a in (select b from t2)); +select count(*) from t1; +count(*) +3 +drop table t1, t2; +End of 4.1 tests create temporary table t1 (a int, primary key(a)) engine=bdb; select * from t1; a @@ -1584,8 +1603,6 @@ g 10 h 10 i 10 alter table t1 modify v varchar(300), drop key v, drop key v_2, add key v (v); -Warnings: -Warning 1071 Specified key was too long; max key length is 255 bytes show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -1594,7 +1611,7 @@ t1 CREATE TABLE `t1` ( `t` text, KEY `c` (`c`), KEY `t` (`t`(10)), - KEY `v` (`v`(255)) + KEY `v` (`v`) ) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1 select count(*) from t1 where v='a'; count(*) @@ -1616,19 +1633,19 @@ count(*) 9 explain select count(*) from t1 where v='a '; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 258 const # Using where +1 SIMPLE t1 ref v v 303 const # Using where explain select count(*) from t1 where v like 'a%'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 258 NULL # Using where +1 SIMPLE t1 range v v 303 NULL # Using where explain select count(*) from t1 where v between 'a' and 'a '; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 258 const # Using where +1 SIMPLE t1 ref v v 303 const # Using where explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 258 const # Using where +1 SIMPLE t1 ref v v 303 const # Using where explain select * from t1 where v='a'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 258 const # Using where +1 SIMPLE t1 ref v v 303 const # Using where select v,count(*) from t1 group by v limit 10; v count(*) a 1 @@ -1656,15 +1673,15 @@ i 10 select sql_big_result v,count(t) from t1 group by v limit 10; v count(t) a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 +a 10 +b 10 +c 10 +d 10 +e 10 +f 10 +g 10 +h 10 +i 10 alter table t1 drop key v, add key v (v(30)); show create table t1; Table Create Table @@ -1746,8 +1763,6 @@ g 10 h 10 i 10 alter table t1 modify v varchar(600), drop key v, add key v (v); -Warnings: -Warning 1071 Specified key was too long; max key length is 255 bytes show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -1756,7 +1771,7 @@ t1 CREATE TABLE `t1` ( `t` text, KEY `c` (`c`), KEY `t` (`t`(10)), - KEY `v` (`v`(255)) + KEY `v` (`v`) ) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1 select v,count(*) from t1 group by v limit 10; v count(*) @@ -1785,15 +1800,15 @@ i 10 select sql_big_result v,count(t) from t1 group by v limit 10; v count(t) a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 +a 10 +b 10 +c 10 +d 10 +e 10 +f 10 +g 10 +h 10 +i 10 drop table t1; create table t1 (a char(10), unique (a)); insert into t1 values ('a '); @@ -1874,7 +1889,7 @@ a b drop table t1; create table t1 (v varchar(65530), key(v)); Warnings: -Warning 1071 Specified key was too long; max key length is 255 bytes +Warning 1071 Specified key was too long; max key length is MAX_KEY_LENGTH bytes drop table if exists t1; create table t1 (v varchar(65536)); Warnings: @@ -1895,8 +1910,22 @@ t1 CREATE TABLE `t1` ( ) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1 drop table t1; set storage_engine=MyISAM; +create table t1 (a varchar(255) character set utf8, +b varchar(255) character set utf8, +c varchar(255) character set utf8, +d varchar(255) character set utf8, +key (a,b,c,d)) engine=bdb; +drop table t1; +create table t1 (a varchar(255) character set utf8, +b varchar(255) character set utf8, +c varchar(255) character set utf8, +d varchar(255) character set utf8, +e varchar(255) character set utf8, +key (a,b,c,d,e)) engine=bdb; +ERROR 42000: Specified key was too long; max key length is 3072 bytes set autocommit=0; create table t1 (a int) engine=bdb; commit; alter table t1 add primary key(a); drop table t1; +End of 5.0 tests diff --git a/mysql-test/r/bdb_gis.result b/mysql-test/r/bdb_gis.result new file mode 100644 index 00000000000..c0e1682e485 --- /dev/null +++ b/mysql-test/r/bdb_gis.result @@ -0,0 +1,458 @@ +SET storage_engine=bdb; +DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE gis_point (fid INTEGER, g POINT); +CREATE TABLE gis_line (fid INTEGER, g LINESTRING); +CREATE TABLE gis_polygon (fid INTEGER, g POLYGON); +CREATE TABLE gis_multi_point (fid INTEGER, g MULTIPOINT); +CREATE TABLE gis_multi_line (fid INTEGER, g MULTILINESTRING); +CREATE TABLE gis_multi_polygon (fid INTEGER, g MULTIPOLYGON); +CREATE TABLE gis_geometrycollection (fid INTEGER, g GEOMETRYCOLLECTION); +CREATE TABLE gis_geometry (fid INTEGER, g GEOMETRY); +SHOW CREATE TABLE gis_point; +Table Create Table +gis_point CREATE TABLE `gis_point` ( + `fid` int(11) default NULL, + `g` point default NULL +) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1 +SHOW FIELDS FROM gis_point; +Field Type Null Key Default Extra +fid int(11) YES NULL +g point YES NULL +SHOW FIELDS FROM gis_line; +Field Type Null Key Default Extra +fid int(11) YES NULL +g linestring YES NULL +SHOW FIELDS FROM gis_polygon; +Field Type Null Key Default Extra +fid int(11) YES NULL +g polygon YES NULL +SHOW FIELDS FROM gis_multi_point; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multipoint YES NULL +SHOW FIELDS FROM gis_multi_line; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multilinestring YES NULL +SHOW FIELDS FROM gis_multi_polygon; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multipolygon YES NULL +SHOW FIELDS FROM gis_geometrycollection; +Field Type Null Key Default Extra +fid int(11) YES NULL +g geometrycollection YES NULL +SHOW FIELDS FROM gis_geometry; +Field Type Null Key Default Extra +fid int(11) YES NULL +g geometry YES NULL +INSERT INTO gis_point VALUES +(101, PointFromText('POINT(10 10)')), +(102, PointFromText('POINT(20 10)')), +(103, PointFromText('POINT(20 20)')), +(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)')))); +INSERT INTO gis_line VALUES +(105, LineFromText('LINESTRING(0 0,0 10,10 0)')), +(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')), +(107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10)))); +INSERT INTO gis_polygon VALUES +(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')), +(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')), +(110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))))); +INSERT INTO gis_multi_point VALUES +(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')), +(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')), +(113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10)))); +INSERT INTO gis_multi_line VALUES +(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')), +(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')), +(116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7))))); +INSERT INTO gis_multi_polygon VALUES +(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))))); +INSERT INTO gis_geometrycollection VALUES +(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')), +(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))); +INSERT into gis_geometry SELECT * FROM gis_point; +INSERT into gis_geometry SELECT * FROM gis_line; +INSERT into gis_geometry SELECT * FROM gis_polygon; +INSERT into gis_geometry SELECT * FROM gis_multi_point; +INSERT into gis_geometry SELECT * FROM gis_multi_line; +INSERT into gis_geometry SELECT * FROM gis_multi_polygon; +INSERT into gis_geometry SELECT * FROM gis_geometrycollection; +SELECT fid, AsText(g) FROM gis_point ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +SELECT fid, AsText(g) FROM gis_line ORDER by fid; +fid AsText(g) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +SELECT fid, AsText(g) FROM gis_polygon ORDER by fid; +fid AsText(g) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +SELECT fid, AsText(g) FROM gis_multi_point ORDER by fid; +fid AsText(g) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +SELECT fid, AsText(g) FROM gis_multi_line ORDER by fid; +fid AsText(g) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +SELECT fid, AsText(g) FROM gis_multi_polygon ORDER by fid; +fid AsText(g) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +SELECT fid, AsText(g) FROM gis_geometrycollection ORDER by fid; +fid AsText(g) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, AsText(g) FROM gis_geometry ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, Dimension(g) FROM gis_geometry ORDER by fid; +fid Dimension(g) +101 0 +102 0 +103 0 +104 0 +105 1 +106 1 +107 1 +108 2 +109 2 +110 2 +111 0 +112 0 +113 0 +114 1 +115 1 +116 1 +117 2 +118 2 +119 2 +120 1 +121 1 +SELECT fid, GeometryType(g) FROM gis_geometry ORDER by fid; +fid GeometryType(g) +101 POINT +102 POINT +103 POINT +104 POINT +105 LINESTRING +106 LINESTRING +107 LINESTRING +108 POLYGON +109 POLYGON +110 POLYGON +111 MULTIPOINT +112 MULTIPOINT +113 MULTIPOINT +114 MULTILINESTRING +115 MULTILINESTRING +116 MULTILINESTRING +117 MULTIPOLYGON +118 MULTIPOLYGON +119 MULTIPOLYGON +120 GEOMETRYCOLLECTION +121 GEOMETRYCOLLECTION +SELECT fid, IsEmpty(g) FROM gis_geometry ORDER by fid; +fid IsEmpty(g) +101 0 +102 0 +103 0 +104 0 +105 0 +106 0 +107 0 +108 0 +109 0 +110 0 +111 0 +112 0 +113 0 +114 0 +115 0 +116 0 +117 0 +118 0 +119 0 +120 0 +121 0 +SELECT fid, AsText(Envelope(g)) FROM gis_geometry ORDER by fid; +fid AsText(Envelope(g)) +101 POLYGON((10 10,10 10,10 10,10 10,10 10)) +102 POLYGON((20 10,20 10,20 10,20 10,20 10)) +103 POLYGON((20 20,20 20,20 20,20 20,20 20)) +104 POLYGON((10 20,10 20,10 20,10 20,10 20)) +105 POLYGON((0 0,10 0,10 10,0 10,0 0)) +106 POLYGON((10 10,20 10,20 20,10 20,10 10)) +107 POLYGON((10 10,40 10,40 10,10 10,10 10)) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0)) +110 POLYGON((0 0,30 0,30 30,0 30,0 0)) +111 POLYGON((0 0,20 0,20 20,0 20,0 0)) +112 POLYGON((1 1,21 1,21 21,1 21,1 1)) +113 POLYGON((3 6,4 6,4 10,3 10,3 6)) +114 POLYGON((10 0,16 0,16 48,10 48,10 0)) +115 POLYGON((10 0,10 0,10 48,10 48,10 0)) +116 POLYGON((1 2,21 2,21 8,1 8,1 2)) +117 POLYGON((28 0,84 0,84 42,28 42,28 0)) +118 POLYGON((28 0,84 0,84 42,28 42,28 0)) +119 POLYGON((0 0,3 0,3 3,0 3,0 0)) +120 POLYGON((0 0,10 0,10 10,0 10,0 0)) +121 POLYGON((3 6,44 6,44 9,3 9,3 6)) +explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21 +Warnings: +Note 1003 select dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,astext(envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry` +SELECT fid, X(g) FROM gis_point ORDER by fid; +fid X(g) +101 10 +102 20 +103 20 +104 10 +SELECT fid, Y(g) FROM gis_point ORDER by fid; +fid Y(g) +101 10 +102 10 +103 20 +104 20 +explain extended select X(g),Y(g) FROM gis_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_point ALL NULL NULL NULL NULL 4 +Warnings: +Note 1003 select x(`test`.`gis_point`.`g`) AS `X(g)`,y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point` +SELECT fid, AsText(StartPoint(g)) FROM gis_line ORDER by fid; +fid AsText(StartPoint(g)) +105 POINT(0 0) +106 POINT(10 10) +107 POINT(10 10) +SELECT fid, AsText(EndPoint(g)) FROM gis_line ORDER by fid; +fid AsText(EndPoint(g)) +105 POINT(10 0) +106 POINT(10 10) +107 POINT(40 10) +SELECT fid, GLength(g) FROM gis_line ORDER by fid; +fid GLength(g) +105 24.142135623731 +106 40 +107 30 +SELECT fid, NumPoints(g) FROM gis_line ORDER by fid; +fid NumPoints(g) +105 3 +106 5 +107 2 +SELECT fid, AsText(PointN(g, 2)) FROM gis_line ORDER by fid; +fid AsText(PointN(g, 2)) +105 POINT(0 10) +106 POINT(20 10) +107 POINT(40 10) +SELECT fid, IsClosed(g) FROM gis_line ORDER by fid; +fid IsClosed(g) +105 0 +106 1 +107 0 +explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_line ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,astext(endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,glength(`test`.`gis_line`.`g`) AS `GLength(g)`,numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,astext(pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line` +SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; +fid AsText(Centroid(g)) +108 POINT(15 15) +109 POINT(25.416666666667 25.416666666667) +110 POINT(20 10) +SELECT fid, Area(g) FROM gis_polygon ORDER by fid; +fid Area(g) +108 100 +109 2400 +110 450 +SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon ORDER by fid; +fid AsText(ExteriorRing(g)) +108 LINESTRING(10 10,20 10,20 20,10 20,10 10) +109 LINESTRING(0 0,50 0,50 50,0 50,0 0) +110 LINESTRING(0 0,30 0,30 30,0 0) +SELECT fid, NumInteriorRings(g) FROM gis_polygon ORDER by fid; +fid NumInteriorRings(g) +108 0 +109 1 +110 0 +SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon ORDER by fid; +fid AsText(InteriorRingN(g, 1)) +108 NULL +109 LINESTRING(10 10,20 10,20 20,10 20,10 10) +110 NULL +explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM gis_polygon; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select astext(centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,area(`test`.`gis_polygon`.`g`) AS `Area(g)`,astext(exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,astext(interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon` +SELECT fid, IsClosed(g) FROM gis_multi_line ORDER by fid; +fid IsClosed(g) +114 0 +115 0 +116 0 +SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; +fid AsText(Centroid(g)) +117 POINT(55.588527753042 17.426536064114) +118 POINT(55.588527753042 17.426536064114) +119 POINT(2 2) +SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; +fid Area(g) +117 1684.5 +118 1684.5 +119 4.5 +SELECT fid, NumGeometries(g) from gis_multi_point ORDER by fid; +fid NumGeometries(g) +111 4 +112 4 +113 2 +SELECT fid, NumGeometries(g) from gis_multi_line ORDER by fid; +fid NumGeometries(g) +114 2 +115 1 +116 2 +SELECT fid, NumGeometries(g) from gis_multi_polygon ORDER by fid; +fid NumGeometries(g) +117 2 +118 2 +119 1 +SELECT fid, NumGeometries(g) from gis_geometrycollection ORDER by fid; +fid NumGeometries(g) +120 2 +121 2 +explain extended SELECT fid, NumGeometries(g) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point` +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point ORDER by fid; +fid AsText(GeometryN(g, 2)) +111 POINT(10 10) +112 POINT(11 11) +113 POINT(4 10) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line ORDER by fid; +fid AsText(GeometryN(g, 2)) +114 LINESTRING(16 0,16 23,16 48) +115 NULL +116 LINESTRING(2 5,5 8,21 7) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon ORDER by fid; +fid AsText(GeometryN(g, 2)) +117 POLYGON((59 18,67 18,67 13,59 13,59 18)) +118 POLYGON((59 18,67 18,67 13,59 13,59 18)) +119 NULL +SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 2)) +120 LINESTRING(0 0,10 10) +121 LINESTRING(3 6,7 9) +SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 1)) +120 POINT(0 0) +121 POINT(44 6) +explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,astext(geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point` +SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +first second w c o e d t i r +120 120 1 1 0 1 0 0 1 0 +120 121 0 0 0 0 0 0 1 0 +121 120 0 0 1 0 0 0 1 0 +121 121 1 1 0 1 0 0 1 0 +explain extended SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE g1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +1 SIMPLE g2 ALL NULL NULL NULL NULL 2 +Warnings: +Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,overlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,disjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,intersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid` +DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE t1 ( +gp point, +ln linestring, +pg polygon, +mp multipoint, +mln multilinestring, +mpg multipolygon, +gc geometrycollection, +gm geometry +); +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +ALTER TABLE t1 ADD fid INT; +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +fid int(11) YES NULL +DROP TABLE t1; +create table t1 (a geometry not null); +insert into t1 values (GeomFromText('Point(1 2)')); +insert into t1 values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert IGNORE into t1 values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; +create table t1 (fl geometry); +insert into t1 values (1); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values (1.11); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values ("qwerty"); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values (pointfromtext('point(1,1)')); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result index ca9a2662f94..84779858b75 100644 --- a/mysql-test/r/bigint.result +++ b/mysql-test/r/bigint.result @@ -1,4 +1,4 @@ -drop table if exists t1; +drop table if exists t1, t2; select 0,256,00000000000000065536,2147483647,-2147483648,2147483648,+4294967296; 0 256 00000000000000065536 2147483647 -2147483648 2147483648 4294967296 0 256 65536 2147483647 -2147483648 2147483648 4294967296 diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index 817be3a2e7c..8da18df1954 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -68,12 +68,12 @@ select CONVERT(DATE "2004-01-22 21:45:33",BINARY(4)); CONVERT(DATE "2004-01-22 21:45:33",BINARY(4)) 2004 Warnings: -Warning 1292 Truncated incorrect CHAR(4) value: '2004-01-22 21:45:33' +Warning 1292 Truncated incorrect BINARY(4) value: '2004-01-22 21:45:33' select CAST(DATE "2004-01-22 21:45:33" AS BINARY(4)); CAST(DATE "2004-01-22 21:45:33" AS BINARY(4)) 2004 Warnings: -Warning 1292 Truncated incorrect CHAR(4) value: '2004-01-22 21:45:33' +Warning 1292 Truncated incorrect BINARY(4) value: '2004-01-22 21:45:33' select CAST(0xb3 as signed); CAST(0xb3 as signed) 179 @@ -165,17 +165,17 @@ cast(_latin1'ab' AS char) as c1, cast(_latin1'a ' AS char) as c2, cast(_latin1'abc' AS char(2)) as c3, cast(_latin1'a ' AS char(2)) as c4, -cast(_latin1'a' AS char(2)) as c5; +hex(cast(_latin1'a' AS char(2))) as c5; c1 c2 c3 c4 c5 -ab a ab a a +ab a ab a 6100 Warnings: -Warning 1292 Truncated incorrect CHAR(2) value: 'abc' -Warning 1292 Truncated incorrect CHAR(2) value: 'a ' +Warning 1292 Truncated incorrect BINARY(2) value: 'abc' +Warning 1292 Truncated incorrect BINARY(2) value: 'a ' select cast(1000 as CHAR(3)); cast(1000 as CHAR(3)) 100 Warnings: -Warning 1292 Truncated incorrect CHAR(3) value: '1000' +Warning 1292 Truncated incorrect BINARY(3) value: '1000' create table t1 select cast(_latin1'ab' AS char) as c1, cast(_latin1'a ' AS char) as c2, @@ -183,11 +183,11 @@ cast(_latin1'abc' AS char(2)) as c3, cast(_latin1'a ' AS char(2)) as c4, cast(_latin1'a' AS char(2)) as c5; Warnings: -Warning 1292 Truncated incorrect CHAR(2) value: 'abc' -Warning 1292 Truncated incorrect CHAR(2) value: 'a ' -select * from t1; -c1 c2 c3 c4 c5 -ab a ab a a +Warning 1292 Truncated incorrect BINARY(2) value: 'abc' +Warning 1292 Truncated incorrect BINARY(2) value: 'a ' +select c1,c2,c3,c4,hex(c5) from t1; +c1 c2 c3 c4 hex(c5) +ab a ab a 6100 show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -274,9 +274,9 @@ aac aac aab aab aaa aaa Warnings: -Warning 1292 Truncated incorrect CHAR(2) value: 'aaa' -Warning 1292 Truncated incorrect CHAR(2) value: 'aab' -Warning 1292 Truncated incorrect CHAR(2) value: 'aac' +Warning 1292 Truncated incorrect BINARY(2) value: 'aaa' +Warning 1292 Truncated incorrect BINARY(2) value: 'aab' +Warning 1292 Truncated incorrect BINARY(2) value: 'aac' SELECT a, CAST(a AS UNSIGNED) FROM t1 ORDER BY CAST(a AS CHAR) ; a CAST(a AS UNSIGNED) aaa 3 @@ -288,9 +288,9 @@ aaa aa aab aa aac aa Warnings: -Warning 1292 Truncated incorrect CHAR(2) value: 'aaa' -Warning 1292 Truncated incorrect CHAR(2) value: 'aab' -Warning 1292 Truncated incorrect CHAR(2) value: 'aac' +Warning 1292 Truncated incorrect BINARY(2) value: 'aaa' +Warning 1292 Truncated incorrect BINARY(2) value: 'aab' +Warning 1292 Truncated incorrect BINARY(2) value: 'aac' DROP TABLE t1; select date_add(cast('2004-12-30 12:00:00' as date), interval 0 hour); date_add(cast('2004-12-30 12:00:00' as date), interval 0 hour) diff --git a/mysql-test/r/compress.result b/mysql-test/r/compress.result new file mode 100644 index 00000000000..efcafbbe736 --- /dev/null +++ b/mysql-test/r/compress.result @@ -0,0 +1,2159 @@ +SHOW STATUS LIKE 'Compression'; +Variable_name Value +Compression ON +drop table if exists t1,t2,t3,t4; +CREATE TABLE t1 ( +Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL +); +INSERT INTO t1 VALUES (9410,9412); +select period from t1; +period +9410 +select * from t1; +Period Varor_period +9410 9412 +select t1.* from t1; +Period Varor_period +9410 9412 +CREATE TABLE t2 ( +auto int not null auto_increment, +fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL, +companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL, +fld3 char(30) DEFAULT '' NOT NULL, +fld4 char(35) DEFAULT '' NOT NULL, +fld5 char(35) DEFAULT '' NOT NULL, +fld6 char(4) DEFAULT '' NOT NULL, +UNIQUE fld1 (fld1), +KEY fld3 (fld3), +PRIMARY KEY (auto) +); +select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%"; +fld3 +imaginable +select fld3 from t2 where fld3 like "%cultivation" ; +fld3 +cultivation +select t2.fld3,companynr from t2 where companynr = 57+1 order by fld3; +fld3 companynr +concoct 58 +druggists 58 +engrossing 58 +Eurydice 58 +exclaimers 58 +ferociousness 58 +hopelessness 58 +Huey 58 +imaginable 58 +judges 58 +merging 58 +ostrich 58 +peering 58 +Phelps 58 +presumes 58 +Ruth 58 +sentences 58 +Shylock 58 +straggled 58 +synergy 58 +thanking 58 +tying 58 +unlocks 58 +select fld3,companynr from t2 where companynr = 58 order by fld3; +fld3 companynr +concoct 58 +druggists 58 +engrossing 58 +Eurydice 58 +exclaimers 58 +ferociousness 58 +hopelessness 58 +Huey 58 +imaginable 58 +judges 58 +merging 58 +ostrich 58 +peering 58 +Phelps 58 +presumes 58 +Ruth 58 +sentences 58 +Shylock 58 +straggled 58 +synergy 58 +thanking 58 +tying 58 +unlocks 58 +select fld3 from t2 order by fld3 desc limit 10; +fld3 +youthfulness +yelped +Wotan +workers +Witt +witchcraft +Winsett +Willy +willed +wildcats +select fld3 from t2 order by fld3 desc limit 5; +fld3 +youthfulness +yelped +Wotan +workers +Witt +select fld3 from t2 order by fld3 desc limit 5,5; +fld3 +witchcraft +Winsett +Willy +willed +wildcats +select t2.fld3 from t2 where fld3 = 'honeysuckle'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'honeysuckl_'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'hon_ysuckl_'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'honeysuckle%'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'h%le'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'honeysuckle_'; +fld3 +select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%'; +fld3 +explain select t2.fld3 from t2 where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index +explain select fld3 from t2 ignore index (fld3) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select fld3 from t2 use index (fld1) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select fld3 from t2 use index (fld3) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index +explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index +explain select fld3 from t2 ignore index (fld3,not_used); +ERROR 42000: Key column 'not_used' doesn't exist in table +explain select fld3 from t2 use index (not_used); +ERROR 42000: Key column 'not_used' doesn't exist in table +select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3; +fld3 +honeysuckle +honoring +explain select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range fld3 fld3 30 NULL 2 Using where; Using index +select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3; +fld1 fld3 +148504 Colombo +068305 Colombo +000000 nondecreasing +select fld1,fld3 from t2 where companynr = 37 and fld3 = 'appendixes'; +fld1 fld3 +232605 appendixes +1232605 appendixes +1232606 appendixes +1232607 appendixes +1232608 appendixes +1232609 appendixes +select fld1 from t2 where fld1=250501 or fld1="250502"; +fld1 +250501 +250502 +explain select fld1 from t2 where fld1=250501 or fld1="250502"; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range fld1 fld1 4 NULL 2 Using where; Using index +select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502; +fld1 +250501 +250502 +250505 +250601 +explain select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range fld1 fld1 4 NULL 4 Using where; Using index +select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%'; +fld1 fld3 +218401 faithful +018007 fanatic +228311 fated +018017 featherweight +218022 feed +088303 feminine +058004 Fenton +038017 fetched +018054 fetters +208101 fiftieth +238007 filial +013606 fingerings +218008 finishers +038205 firearm +188505 fitting +202301 Fitzpatrick +238008 fixedly +012001 flanking +018103 flint +018104 flopping +188007 flurried +013602 foldout +226205 foothill +232102 forgivably +228306 forthcoming +186002 freakish +208113 freest +231315 freezes +036002 funereal +226209 furnishings +198006 furthermore +select fld3 from t2 where fld3 like "L%" and fld3 = "ok"; +fld3 +select fld3 from t2 where (fld3 like "C%" and fld3 = "Chantilly"); +fld3 +Chantilly +select fld1,fld3 from t2 where fld1 like "25050%"; +fld1 fld3 +250501 poisoning +250502 Iraqis +250503 heaving +250504 population +250505 bomb +select fld1,fld3 from t2 where fld1 like "25050_"; +fld1 fld3 +250501 poisoning +250502 Iraqis +250503 heaving +250504 population +250505 bomb +select distinct companynr from t2; +companynr +00 +37 +36 +50 +58 +29 +40 +53 +65 +41 +34 +68 +select distinct companynr from t2 order by companynr; +companynr +00 +29 +34 +36 +37 +40 +41 +50 +53 +58 +65 +68 +select distinct companynr from t2 order by companynr desc; +companynr +68 +65 +58 +53 +50 +41 +40 +37 +36 +34 +29 +00 +select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period +obliterates 9410 +offload 9410 +opaquely 9410 +organizer 9410 +overestimating 9410 +overlay 9410 +select distinct fld3 from t2 where companynr = 34 order by fld3; +fld3 +absentee +accessed +ahead +alphabetic +Asiaticizations +attitude +aye +bankruptcies +belays +Blythe +bomb +boulevard +bulldozes +cannot +caressing +charcoal +checksumming +chess +clubroom +colorful +cosy +creator +crying +Darius +diffusing +duality +Eiffel +Epiphany +Ernestine +explorers +exterminated +famine +forked +Gershwins +heaving +Hodges +Iraqis +Italianization +Lagos +landslide +libretto +Majorca +mastering +narrowed +occurred +offerers +Palestine +Peruvianizes +pharmaceutic +poisoning +population +Pygmalion +rats +realest +recording +regimented +retransmitting +reviver +rouses +scars +sicker +sleepwalk +stopped +sugars +translatable +uncles +unexpected +uprisings +versatility +vest +select distinct fld3 from t2 limit 10; +fld3 +abates +abiding +Abraham +abrogating +absentee +abut +accessed +accruing +accumulating +accuracies +select distinct fld3 from t2 having fld3 like "A%" limit 10; +fld3 +abates +abiding +Abraham +abrogating +absentee +abut +accessed +accruing +accumulating +accuracies +select distinct substring(fld3,1,3) from t2 where fld3 like "A%"; +substring(fld3,1,3) +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +Adl +adm +Ado +ads +adv +aer +aff +afi +afl +afo +agi +ahe +aim +air +Ald +alg +ali +all +alp +alr +ama +ame +amm +ana +and +ane +Ang +ani +Ann +Ant +api +app +aqu +Ara +arc +Arm +arr +Art +Asi +ask +asp +ass +ast +att +aud +Aug +aut +ave +avo +awe +aye +Azt +select distinct substring(fld3,1,3) as a from t2 having a like "A%" order by a limit 10; +a +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +select distinct substring(fld3,1,3) from t2 where fld3 like "A%" limit 10; +substring(fld3,1,3) +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +select distinct substring(fld3,1,3) as a from t2 having a like "A%" limit 10; +a +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +create table t3 ( +period int not null, +name char(32) not null, +companynr int not null, +price double(11,0), +price2 double(11,0), +key (period), +key (name) +); +create temporary table tmp engine = myisam select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +alter table t3 add t2nr int not null auto_increment primary key first; +drop table tmp; +SET SQL_BIG_TABLES=1; +select distinct concat(fld3," ",fld3) as namn from t2,t3 where t2.fld1=t3.t2nr order by namn limit 10; +namn +Abraham Abraham +abrogating abrogating +admonishing admonishing +Adolph Adolph +afield afield +aging aging +ammonium ammonium +analyzable analyzable +animals animals +animized animized +SET SQL_BIG_TABLES=0; +select distinct concat(fld3," ",fld3) from t2,t3 where t2.fld1=t3.t2nr order by fld3 limit 10; +concat(fld3," ",fld3) +Abraham Abraham +abrogating abrogating +admonishing admonishing +Adolph Adolph +afield afield +aging aging +ammonium ammonium +analyzable analyzable +animals animals +animized animized +select distinct fld5 from t2 limit 10; +fld5 +neat +Steinberg +jarring +tinily +balled +persist +attainments +fanatic +measures +rightfulness +select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10; +fld3 count(*) +affixed 1 +and 1 +annoyers 1 +Anthony 1 +assayed 1 +assurers 1 +attendants 1 +bedlam 1 +bedpost 1 +boasted 1 +SET SQL_BIG_TABLES=1; +select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10; +fld3 count(*) +affixed 1 +and 1 +annoyers 1 +Anthony 1 +assayed 1 +assurers 1 +attendants 1 +bedlam 1 +bedpost 1 +boasted 1 +SET SQL_BIG_TABLES=0; +select distinct fld3,repeat("a",length(fld3)),count(*) from t2 group by companynr,fld3 limit 100,10; +fld3 repeat("a",length(fld3)) count(*) +circus aaaaaa 1 +cited aaaaa 1 +Colombo aaaaaaa 1 +congresswoman aaaaaaaaaaaaa 1 +contrition aaaaaaaaaa 1 +corny aaaaa 1 +cultivation aaaaaaaaaaa 1 +definiteness aaaaaaaaaaaa 1 +demultiplex aaaaaaaaaaa 1 +disappointing aaaaaaaaaaaaa 1 +select distinct companynr,rtrim(space(512+companynr)) from t3 order by 1,2; +companynr rtrim(space(512+companynr)) +37 +78 +101 +154 +311 +447 +512 +select distinct fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by fld3; +fld3 +explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index +explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort +1 SIMPLE t3 ref period period 4 test.t1.period 4181 +explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 index period period 4 NULL 41810 +1 SIMPLE t1 ref period period 4 test.t3.period 4181 +explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index period period 4 NULL 41810 +1 SIMPLE t3 ref period period 4 test.t1.period 4181 +select period from t1; +period +9410 +select period from t1 where period=1900; +period +select fld3,period from t1,t2 where fld1 = 011401 order by period; +fld3 period +breaking 9410 +select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; +fld3 period +breaking 1001 +explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 const fld1 fld1 4 const 1 +1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 +select fld3,period from t2,t1 where companynr*10 = 37*10; +fld3 period +breaking 9410 +Romans 9410 +intercepted 9410 +bewilderingly 9410 +astound 9410 +admonishing 9410 +sumac 9410 +flanking 9410 +combed 9410 +subjective 9410 +scatterbrain 9410 +Eulerian 9410 +Kane 9410 +overlay 9410 +perturb 9410 +goblins 9410 +annihilates 9410 +Wotan 9410 +snatching 9410 +concludes 9410 +laterally 9410 +yelped 9410 +grazing 9410 +Baird 9410 +celery 9410 +misunderstander 9410 +handgun 9410 +foldout 9410 +mystic 9410 +succumbed 9410 +Nabisco 9410 +fingerings 9410 +aging 9410 +afield 9410 +ammonium 9410 +boat 9410 +intelligibility 9410 +Augustine 9410 +teethe 9410 +dreaded 9410 +scholastics 9410 +audiology 9410 +wallet 9410 +parters 9410 +eschew 9410 +quitter 9410 +neat 9410 +Steinberg 9410 +jarring 9410 +tinily 9410 +balled 9410 +persist 9410 +attainments 9410 +fanatic 9410 +measures 9410 +rightfulness 9410 +capably 9410 +impulsive 9410 +starlet 9410 +terminators 9410 +untying 9410 +announces 9410 +featherweight 9410 +pessimist 9410 +daughter 9410 +decliner 9410 +lawgiver 9410 +stated 9410 +readable 9410 +attrition 9410 +cascade 9410 +motors 9410 +interrogate 9410 +pests 9410 +stairway 9410 +dopers 9410 +testicle 9410 +Parsifal 9410 +leavings 9410 +postulation 9410 +squeaking 9410 +contrasted 9410 +leftover 9410 +whiteners 9410 +erases 9410 +Punjab 9410 +Merritt 9410 +Quixotism 9410 +sweetish 9410 +dogging 9410 +scornfully 9410 +bellow 9410 +bills 9410 +cupboard 9410 +sureties 9410 +puddings 9410 +fetters 9410 +bivalves 9410 +incurring 9410 +Adolph 9410 +pithed 9410 +Miles 9410 +trimmings 9410 +tragedies 9410 +skulking 9410 +flint 9410 +flopping 9410 +relaxing 9410 +offload 9410 +suites 9410 +lists 9410 +animized 9410 +multilayer 9410 +standardizes 9410 +Judas 9410 +vacuuming 9410 +dentally 9410 +humanness 9410 +inch 9410 +Weissmuller 9410 +irresponsibly 9410 +luckily 9410 +culled 9410 +medical 9410 +bloodbath 9410 +subschema 9410 +animals 9410 +Micronesia 9410 +repetitions 9410 +Antares 9410 +ventilate 9410 +pityingly 9410 +interdependent 9410 +Graves 9410 +neonatal 9410 +chafe 9410 +honoring 9410 +realtor 9410 +elite 9410 +funereal 9410 +abrogating 9410 +sorters 9410 +Conley 9410 +lectured 9410 +Abraham 9410 +Hawaii 9410 +cage 9410 +hushes 9410 +Simla 9410 +reporters 9410 +Dutchman 9410 +descendants 9410 +groupings 9410 +dissociate 9410 +coexist 9410 +Beebe 9410 +Taoism 9410 +Connally 9410 +fetched 9410 +checkpoints 9410 +rusting 9410 +galling 9410 +obliterates 9410 +traitor 9410 +resumes 9410 +analyzable 9410 +terminator 9410 +gritty 9410 +firearm 9410 +minima 9410 +Selfridge 9410 +disable 9410 +witchcraft 9410 +betroth 9410 +Manhattanize 9410 +imprint 9410 +peeked 9410 +swelling 9410 +interrelationships 9410 +riser 9410 +Gandhian 9410 +peacock 9410 +bee 9410 +kanji 9410 +dental 9410 +scarf 9410 +chasm 9410 +insolence 9410 +syndicate 9410 +alike 9410 +imperial 9410 +convulsion 9410 +railway 9410 +validate 9410 +normalizes 9410 +comprehensive 9410 +chewing 9410 +denizen 9410 +schemer 9410 +chronicle 9410 +Kline 9410 +Anatole 9410 +partridges 9410 +brunch 9410 +recruited 9410 +dimensions 9410 +Chicana 9410 +announced 9410 +praised 9410 +employing 9410 +linear 9410 +quagmire 9410 +western 9410 +relishing 9410 +serving 9410 +scheduling 9410 +lore 9410 +eventful 9410 +arteriole 9410 +disentangle 9410 +cured 9410 +Fenton 9410 +avoidable 9410 +drains 9410 +detectably 9410 +husky 9410 +impelling 9410 +undoes 9410 +evened 9410 +squeezes 9410 +destroyer 9410 +rudeness 9410 +beaner 9410 +boorish 9410 +Everhart 9410 +encompass 9410 +mushrooms 9410 +Alison 9410 +externally 9410 +pellagra 9410 +cult 9410 +creek 9410 +Huffman 9410 +Majorca 9410 +governing 9410 +gadfly 9410 +reassigned 9410 +intentness 9410 +craziness 9410 +psychic 9410 +squabbled 9410 +burlesque 9410 +capped 9410 +extracted 9410 +DiMaggio 9410 +exclamation 9410 +subdirectory 9410 +Gothicism 9410 +feminine 9410 +metaphysically 9410 +sanding 9410 +Miltonism 9410 +freakish 9410 +index 9410 +straight 9410 +flurried 9410 +denotative 9410 +coming 9410 +commencements 9410 +gentleman 9410 +gifted 9410 +Shanghais 9410 +sportswriting 9410 +sloping 9410 +navies 9410 +leaflet 9410 +shooter 9410 +Joplin 9410 +babies 9410 +assails 9410 +admiring 9410 +swaying 9410 +Goldstine 9410 +fitting 9410 +Norwalk 9410 +analogy 9410 +deludes 9410 +cokes 9410 +Clayton 9410 +exhausts 9410 +causality 9410 +sating 9410 +icon 9410 +throttles 9410 +communicants 9410 +dehydrate 9410 +priceless 9410 +publicly 9410 +incidentals 9410 +commonplace 9410 +mumbles 9410 +furthermore 9410 +cautioned 9410 +parametrized 9410 +registration 9410 +sadly 9410 +positioning 9410 +babysitting 9410 +eternal 9410 +hoarder 9410 +congregates 9410 +rains 9410 +workers 9410 +sags 9410 +unplug 9410 +garage 9410 +boulder 9410 +specifics 9410 +Teresa 9410 +Winsett 9410 +convenient 9410 +buckboards 9410 +amenities 9410 +resplendent 9410 +sews 9410 +participated 9410 +Simon 9410 +certificates 9410 +Fitzpatrick 9410 +Evanston 9410 +misted 9410 +textures 9410 +save 9410 +count 9410 +rightful 9410 +chaperone 9410 +Lizzy 9410 +clenched 9410 +effortlessly 9410 +accessed 9410 +beaters 9410 +Hornblower 9410 +vests 9410 +indulgences 9410 +infallibly 9410 +unwilling 9410 +excrete 9410 +spools 9410 +crunches 9410 +overestimating 9410 +ineffective 9410 +humiliation 9410 +sophomore 9410 +star 9410 +rifles 9410 +dialysis 9410 +arriving 9410 +indulge 9410 +clockers 9410 +languages 9410 +Antarctica 9410 +percentage 9410 +ceiling 9410 +specification 9410 +regimented 9410 +ciphers 9410 +pictures 9410 +serpents 9410 +allot 9410 +realized 9410 +mayoral 9410 +opaquely 9410 +hostess 9410 +fiftieth 9410 +incorrectly 9410 +decomposition 9410 +stranglings 9410 +mixture 9410 +electroencephalography 9410 +similarities 9410 +charges 9410 +freest 9410 +Greenberg 9410 +tinting 9410 +expelled 9410 +warm 9410 +smoothed 9410 +deductions 9410 +Romano 9410 +bitterroot 9410 +corset 9410 +securing 9410 +environing 9410 +cute 9410 +Crays 9410 +heiress 9410 +inform 9410 +avenge 9410 +universals 9410 +Kinsey 9410 +ravines 9410 +bestseller 9410 +equilibrium 9410 +extents 9410 +relatively 9410 +pressure 9410 +critiques 9410 +befouled 9410 +rightfully 9410 +mechanizing 9410 +Latinizes 9410 +timesharing 9410 +Aden 9410 +embassies 9410 +males 9410 +shapelessly 9410 +mastering 9410 +Newtonian 9410 +finishers 9410 +abates 9410 +teem 9410 +kiting 9410 +stodgy 9410 +feed 9410 +guitars 9410 +airships 9410 +store 9410 +denounces 9410 +Pyle 9410 +Saxony 9410 +serializations 9410 +Peruvian 9410 +taxonomically 9410 +kingdom 9410 +stint 9410 +Sault 9410 +faithful 9410 +Ganymede 9410 +tidiness 9410 +gainful 9410 +contrary 9410 +Tipperary 9410 +tropics 9410 +theorizers 9410 +renew 9410 +already 9410 +terminal 9410 +Hegelian 9410 +hypothesizer 9410 +warningly 9410 +journalizing 9410 +nested 9410 +Lars 9410 +saplings 9410 +foothill 9410 +labeled 9410 +imperiously 9410 +reporters 9410 +furnishings 9410 +precipitable 9410 +discounts 9410 +excises 9410 +Stalin 9410 +despot 9410 +ripeness 9410 +Arabia 9410 +unruly 9410 +mournfulness 9410 +boom 9410 +slaughter 9410 +Sabine 9410 +handy 9410 +rural 9410 +organizer 9410 +shipyard 9410 +civics 9410 +inaccuracy 9410 +rules 9410 +juveniles 9410 +comprised 9410 +investigations 9410 +stabilizes 9410 +seminaries 9410 +Hunter 9410 +sporty 9410 +test 9410 +weasels 9410 +CERN 9410 +tempering 9410 +afore 9410 +Galatean 9410 +techniques 9410 +error 9410 +veranda 9410 +severely 9410 +Cassites 9410 +forthcoming 9410 +guides 9410 +vanish 9410 +lied 9410 +sawtooth 9410 +fated 9410 +gradually 9410 +widens 9410 +preclude 9410 +evenhandedly 9410 +percentage 9410 +disobedience 9410 +humility 9410 +gleaning 9410 +petted 9410 +bloater 9410 +minion 9410 +marginal 9410 +apiary 9410 +measures 9410 +precaution 9410 +repelled 9410 +primary 9410 +coverings 9410 +Artemia 9410 +navigate 9410 +spatial 9410 +Gurkha 9410 +meanwhile 9410 +Melinda 9410 +Butterfield 9410 +Aldrich 9410 +previewing 9410 +glut 9410 +unaffected 9410 +inmate 9410 +mineral 9410 +impending 9410 +meditation 9410 +ideas 9410 +miniaturizes 9410 +lewdly 9410 +title 9410 +youthfulness 9410 +creak 9410 +Chippewa 9410 +clamored 9410 +freezes 9410 +forgivably 9410 +reduce 9410 +McGovern 9410 +Nazis 9410 +epistle 9410 +socializes 9410 +conceptions 9410 +Kevin 9410 +uncovering 9410 +chews 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +raining 9410 +infest 9410 +compartment 9410 +minting 9410 +ducks 9410 +roped 9410 +waltz 9410 +Lillian 9410 +repressions 9410 +chillingly 9410 +noncritical 9410 +lithograph 9410 +spongers 9410 +parenthood 9410 +posed 9410 +instruments 9410 +filial 9410 +fixedly 9410 +relives 9410 +Pandora 9410 +watering 9410 +ungrateful 9410 +secures 9410 +poison 9410 +dusted 9410 +encompasses 9410 +presentation 9410 +Kantian 9410 +select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; +fld3 period price price2 +admonishing 1002 28357832 8723648 +analyzable 1002 28357832 8723648 +annihilates 1001 5987435 234724 +Antares 1002 28357832 8723648 +astound 1001 5987435 234724 +audiology 1001 5987435 234724 +Augustine 1002 28357832 8723648 +Baird 1002 28357832 8723648 +bewilderingly 1001 5987435 234724 +breaking 1001 5987435 234724 +Conley 1001 5987435 234724 +dentally 1002 28357832 8723648 +dissociate 1002 28357832 8723648 +elite 1001 5987435 234724 +eschew 1001 5987435 234724 +Eulerian 1001 5987435 234724 +flanking 1001 5987435 234724 +foldout 1002 28357832 8723648 +funereal 1002 28357832 8723648 +galling 1002 28357832 8723648 +Graves 1001 5987435 234724 +grazing 1001 5987435 234724 +groupings 1001 5987435 234724 +handgun 1001 5987435 234724 +humility 1002 28357832 8723648 +impulsive 1002 28357832 8723648 +inch 1001 5987435 234724 +intelligibility 1001 5987435 234724 +jarring 1001 5987435 234724 +lawgiver 1001 5987435 234724 +lectured 1002 28357832 8723648 +Merritt 1002 28357832 8723648 +neonatal 1001 5987435 234724 +offload 1002 28357832 8723648 +parters 1002 28357832 8723648 +pityingly 1002 28357832 8723648 +puddings 1002 28357832 8723648 +Punjab 1001 5987435 234724 +quitter 1002 28357832 8723648 +realtor 1001 5987435 234724 +relaxing 1001 5987435 234724 +repetitions 1001 5987435 234724 +resumes 1001 5987435 234724 +Romans 1002 28357832 8723648 +rusting 1001 5987435 234724 +scholastics 1001 5987435 234724 +skulking 1002 28357832 8723648 +stated 1002 28357832 8723648 +suites 1002 28357832 8723648 +sureties 1001 5987435 234724 +testicle 1002 28357832 8723648 +tinily 1002 28357832 8723648 +tragedies 1001 5987435 234724 +trimmings 1001 5987435 234724 +vacuuming 1001 5987435 234724 +ventilate 1001 5987435 234724 +wallet 1001 5987435 234724 +Weissmuller 1002 28357832 8723648 +Wotan 1002 28357832 8723648 +select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; +fld1 fld3 period price price2 +018201 relaxing 1001 5987435 234724 +018601 vacuuming 1001 5987435 234724 +018801 inch 1001 5987435 234724 +018811 repetitions 1001 5987435 234724 +create table t4 ( +companynr tinyint(2) unsigned zerofill NOT NULL default '00', +companyname char(30) NOT NULL default '', +PRIMARY KEY (companynr), +UNIQUE KEY companyname(companyname) +) ENGINE=MyISAM MAX_ROWS=50 PACK_KEYS=1 COMMENT='companynames'; +select STRAIGHT_JOIN t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr; +companynr companyname +00 Unknown +29 company 1 +34 company 2 +36 company 3 +37 company 4 +40 company 5 +41 company 6 +50 company 11 +53 company 7 +58 company 8 +65 company 9 +68 company 10 +select SQL_SMALL_RESULT t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr; +companynr companyname +00 Unknown +29 company 1 +34 company 2 +36 company 3 +37 company 4 +40 company 5 +41 company 6 +50 company 11 +53 company 7 +58 company 8 +65 company 9 +68 company 10 +select * from t1,t1 t12; +Period Varor_period Period Varor_period +9410 9412 9410 9412 +select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; +fld1 fld1 +250501 250501 +250502 250501 +250503 250501 +250504 250501 +250505 250501 +250501 250502 +250502 250502 +250503 250502 +250504 250502 +250505 250502 +250501 250503 +250502 250503 +250503 250503 +250504 250503 +250505 250503 +250501 250504 +250502 250504 +250503 250504 +250504 250504 +250505 250504 +250501 250505 +250502 250505 +250503 250505 +250504 250505 +250505 250505 +insert into t2 (fld1, companynr) values (999999,99); +select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +companynr companyname +99 NULL +select count(*) from t2 left join t4 using (companynr) where t4.companynr is not null; +count(*) +1199 +explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 Using where; Not exists +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Not exists +select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; +companynr companyname +select count(*) from t2 left join t4 using (companynr) where companynr is not null; +count(*) +1200 +explain select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +delete from t2 where fld1=999999; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; +companynr companynr +37 36 +41 40 +explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; +fld1 companynr fld3 period +038008 37 reporters 1008 +038208 37 Selfridge 1008 +select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; +fld1 companynr fld3 period +038008 37 reporters 1008 +038208 37 Selfridge 1008 +select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; +fld1 companynr fld3 period +038008 37 reporters 1008 +038208 37 Selfridge 1008 +select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); +period +9410 +select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); +period +9410 +select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; +fld1 +250501 +250502 +250503 +250505 +select fld1 from t2 where fld1 in (250502,98005,98006,250503,250605,250606) and fld1 >=250502 and fld1 not in (250605,250606); +fld1 +250502 +250503 +select fld1 from t2 where fld1 between 250502 and 250504; +fld1 +250502 +250503 +250504 +select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld3 like "L%" or fld3 like "G%")) and fld3 like "L%" ; +fld3 +label +labeled +labeled +landslide +laterally +leaflet +lewdly +Lillian +luckily +select count(*) from t1; +count(*) +1 +select companynr,count(*),sum(fld1) from t2 group by companynr; +companynr count(*) sum(fld1) +00 82 10355753 +29 95 14473298 +34 70 17788966 +36 215 22786296 +37 588 83602098 +40 37 6618386 +41 52 12816335 +50 11 1595438 +53 4 793210 +58 23 2254293 +65 10 2284055 +68 12 3097288 +select companynr,count(*) from t2 group by companynr order by companynr desc limit 5; +companynr count(*) +68 12 +65 10 +58 23 +53 4 +50 11 +select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>""; +count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1) +70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069 +explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>""; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +Warnings: +Note 1003 select count(0) AS `count(*)`,min(`test`.`t2`.`fld4`) AS `min(fld4)`,max(`test`.`t2`.`fld4`) AS `max(fld4)`,sum(`test`.`t2`.`fld1`) AS `sum(fld1)`,avg(`test`.`t2`.`fld1`) AS `avg(fld1)`,std(`test`.`t2`.`fld1`) AS `std(fld1)`,variance(`test`.`t2`.`fld1`) AS `variance(fld1)` from `test`.`t2` where ((`test`.`t2`.`companynr` = 34) and (`test`.`t2`.`fld4` <> _latin1'')) +select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3; +companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1) +00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087 +29 95 abut wetness 14473298 152350.5053 8368.5480 70032594.9026 +34 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069 +select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; +companynr t2nr count(price) sum(price) min(price) max(price) avg(price) +37 1 1 5987435 5987435 5987435 5987435.0000 +37 2 1 28357832 28357832 28357832 28357832.0000 +37 3 1 39654943 39654943 39654943 39654943.0000 +37 11 1 5987435 5987435 5987435 5987435.0000 +37 12 1 28357832 28357832 28357832 28357832.0000 +37 13 1 39654943 39654943 39654943 39654943.0000 +37 21 1 5987435 5987435 5987435 5987435.0000 +37 22 1 28357832 28357832 28357832 28357832.0000 +37 23 1 39654943 39654943 39654943 39654943.0000 +37 31 1 5987435 5987435 5987435 5987435.0000 +select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; +companynr t2nr count(price) sum(price) min(price) max(price) avg(price) +37 1 1 5987435 5987435 5987435 5987435.0000 +37 2 1 28357832 28357832 28357832 28357832.0000 +37 3 1 39654943 39654943 39654943 39654943.0000 +37 11 1 5987435 5987435 5987435 5987435.0000 +37 12 1 28357832 28357832 28357832 28357832.0000 +37 13 1 39654943 39654943 39654943 39654943.0000 +37 21 1 5987435 5987435 5987435 5987435.0000 +37 22 1 28357832 28357832 28357832 28357832.0000 +37 23 1 39654943 39654943 39654943 39654943.0000 +37 31 1 5987435 5987435 5987435 5987435.0000 +select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ; +companynr count(price) sum(price) min(price) max(price) avg(price) +37 12543 309394878010 5987435 39654943 24666736.6667 +78 8362 414611089292 726498 98439034 49582766.0000 +101 4181 3489454238 834598 834598 834598.0000 +154 4181 4112197254950 983543950 983543950 983543950.0000 +311 4181 979599938 234298 234298 234298.0000 +447 4181 9929180954 2374834 2374834 2374834.0000 +512 4181 3288532102 786542 786542 786542.0000 +select distinct mod(companynr,10) from t4 group by companynr; +mod(companynr,10) +0 +9 +4 +6 +7 +1 +3 +8 +5 +select distinct 1 from t4 group by companynr; +1 +1 +select count(distinct fld1) from t2; +count(distinct fld1) +1199 +select companynr,count(distinct fld1) from t2 group by companynr; +companynr count(distinct fld1) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(*) from t2 group by companynr; +companynr count(*) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(distinct concat(fld1,repeat(65,1000))) from t2 group by companynr; +companynr count(distinct concat(fld1,repeat(65,1000))) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(distinct concat(fld1,repeat(65,200))) from t2 group by companynr; +companynr count(distinct concat(fld1,repeat(65,200))) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(distinct floor(fld1/100)) from t2 group by companynr; +companynr count(distinct floor(fld1/100)) +00 47 +29 35 +34 14 +36 69 +37 108 +40 16 +41 11 +50 9 +53 1 +58 1 +65 1 +68 1 +select companynr,count(distinct concat(repeat(65,1000),floor(fld1/100))) from t2 group by companynr; +companynr count(distinct concat(repeat(65,1000),floor(fld1/100))) +00 47 +29 35 +34 14 +36 69 +37 108 +40 16 +41 11 +50 9 +53 1 +58 1 +65 1 +68 1 +select sum(fld1),fld3 from t2 where fld3="Romans" group by fld1 limit 10; +sum(fld1) fld3 +11402 Romans +select name,count(*) from t3 where name='cloakroom' group by name; +name count(*) +cloakroom 4181 +select name,count(*) from t3 where name='cloakroom' and price>10 group by name; +name count(*) +cloakroom 4181 +select count(*) from t3 where name='cloakroom' and price2=823742; +count(*) +4181 +select name,count(*) from t3 where name='cloakroom' and price2=823742 group by name; +name count(*) +cloakroom 4181 +select name,count(*) from t3 where name >= "extramarital" and price <= 39654943 group by name; +name count(*) +extramarital 4181 +gazer 4181 +gems 4181 +Iranizes 4181 +spates 4181 +tucked 4181 +violinist 4181 +select t2.fld3,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; +fld3 count(*) +spates 4181 +select companynr|0,companyname from t4 group by 1; +companynr|0 companyname +0 Unknown +29 company 1 +34 company 2 +36 company 3 +37 company 4 +40 company 5 +41 company 6 +50 company 11 +53 company 7 +58 company 8 +65 company 9 +68 company 10 +select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by t2.companynr order by companyname; +companynr companyname count(*) +29 company 1 95 +68 company 10 12 +50 company 11 11 +34 company 2 70 +36 company 3 215 +37 company 4 588 +40 company 5 37 +41 company 6 52 +53 company 7 4 +58 company 8 23 +65 company 9 10 +00 Unknown 82 +select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; +fld1 count(*) +158402 4181 +select sum(Period)/count(*) from t1; +sum(Period)/count(*) +9410.0000 +select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; +companynr count sum diff func +37 12543 309394878010 0.0000 464091 +78 8362 414611089292 0.0000 652236 +101 4181 3489454238 0.0000 422281 +154 4181 4112197254950 0.0000 643874 +311 4181 979599938 0.0000 1300291 +447 4181 9929180954 0.0000 1868907 +512 4181 3288532102 0.0000 2140672 +select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg; +companynr avg +154 983543950.0000 +select companynr,count(*) from t2 group by companynr order by 2 desc; +companynr count(*) +37 588 +36 215 +29 95 +00 82 +34 70 +41 52 +40 37 +58 23 +68 12 +50 11 +65 10 +53 4 +select companynr,count(*) from t2 where companynr > 40 group by companynr order by 2 desc; +companynr count(*) +41 52 +58 23 +68 12 +50 11 +65 10 +53 4 +select t2.fld4,t2.fld1,count(price),sum(price),min(price),max(price),avg(price) from t3,t2 where t3.companynr = 37 and t2.fld1 = t3.t2nr group by fld1,t2.fld4; +fld4 fld1 count(price) sum(price) min(price) max(price) avg(price) +teethe 000001 1 5987435 5987435 5987435 5987435.0000 +dreaded 011401 1 5987435 5987435 5987435 5987435.0000 +scholastics 011402 1 28357832 28357832 28357832 28357832.0000 +audiology 011403 1 39654943 39654943 39654943 39654943.0000 +wallet 011501 1 5987435 5987435 5987435 5987435.0000 +parters 011701 1 5987435 5987435 5987435 5987435.0000 +eschew 011702 1 28357832 28357832 28357832 28357832.0000 +quitter 011703 1 39654943 39654943 39654943 39654943.0000 +neat 012001 1 5987435 5987435 5987435 5987435.0000 +Steinberg 012003 1 39654943 39654943 39654943 39654943.0000 +balled 012301 1 5987435 5987435 5987435 5987435.0000 +persist 012302 1 28357832 28357832 28357832 28357832.0000 +attainments 012303 1 39654943 39654943 39654943 39654943.0000 +capably 012501 1 5987435 5987435 5987435 5987435.0000 +impulsive 012602 1 28357832 28357832 28357832 28357832.0000 +starlet 012603 1 39654943 39654943 39654943 39654943.0000 +featherweight 012701 1 5987435 5987435 5987435 5987435.0000 +pessimist 012702 1 28357832 28357832 28357832 28357832.0000 +daughter 012703 1 39654943 39654943 39654943 39654943.0000 +lawgiver 013601 1 5987435 5987435 5987435 5987435.0000 +stated 013602 1 28357832 28357832 28357832 28357832.0000 +readable 013603 1 39654943 39654943 39654943 39654943.0000 +testicle 013801 1 5987435 5987435 5987435 5987435.0000 +Parsifal 013802 1 28357832 28357832 28357832 28357832.0000 +leavings 013803 1 39654943 39654943 39654943 39654943.0000 +squeaking 013901 1 5987435 5987435 5987435 5987435.0000 +contrasted 016001 1 5987435 5987435 5987435 5987435.0000 +leftover 016201 1 5987435 5987435 5987435 5987435.0000 +whiteners 016202 1 28357832 28357832 28357832 28357832.0000 +erases 016301 1 5987435 5987435 5987435 5987435.0000 +Punjab 016302 1 28357832 28357832 28357832 28357832.0000 +Merritt 016303 1 39654943 39654943 39654943 39654943.0000 +sweetish 018001 1 5987435 5987435 5987435 5987435.0000 +dogging 018002 1 28357832 28357832 28357832 28357832.0000 +scornfully 018003 1 39654943 39654943 39654943 39654943.0000 +fetters 018012 1 28357832 28357832 28357832 28357832.0000 +bivalves 018013 1 39654943 39654943 39654943 39654943.0000 +skulking 018021 1 5987435 5987435 5987435 5987435.0000 +flint 018022 1 28357832 28357832 28357832 28357832.0000 +flopping 018023 1 39654943 39654943 39654943 39654943.0000 +Judas 018032 1 28357832 28357832 28357832 28357832.0000 +vacuuming 018033 1 39654943 39654943 39654943 39654943.0000 +medical 018041 1 5987435 5987435 5987435 5987435.0000 +bloodbath 018042 1 28357832 28357832 28357832 28357832.0000 +subschema 018043 1 39654943 39654943 39654943 39654943.0000 +interdependent 018051 1 5987435 5987435 5987435 5987435.0000 +Graves 018052 1 28357832 28357832 28357832 28357832.0000 +neonatal 018053 1 39654943 39654943 39654943 39654943.0000 +sorters 018061 1 5987435 5987435 5987435 5987435.0000 +epistle 018062 1 28357832 28357832 28357832 28357832.0000 +Conley 018101 1 5987435 5987435 5987435 5987435.0000 +lectured 018102 1 28357832 28357832 28357832 28357832.0000 +Abraham 018103 1 39654943 39654943 39654943 39654943.0000 +cage 018201 1 5987435 5987435 5987435 5987435.0000 +hushes 018202 1 28357832 28357832 28357832 28357832.0000 +Simla 018402 1 28357832 28357832 28357832 28357832.0000 +reporters 018403 1 39654943 39654943 39654943 39654943.0000 +coexist 018601 1 5987435 5987435 5987435 5987435.0000 +Beebe 018602 1 28357832 28357832 28357832 28357832.0000 +Taoism 018603 1 39654943 39654943 39654943 39654943.0000 +Connally 018801 1 5987435 5987435 5987435 5987435.0000 +fetched 018802 1 28357832 28357832 28357832 28357832.0000 +checkpoints 018803 1 39654943 39654943 39654943 39654943.0000 +gritty 018811 1 5987435 5987435 5987435 5987435.0000 +firearm 018812 1 28357832 28357832 28357832 28357832.0000 +minima 019101 1 5987435 5987435 5987435 5987435.0000 +Selfridge 019102 1 28357832 28357832 28357832 28357832.0000 +disable 019103 1 39654943 39654943 39654943 39654943.0000 +witchcraft 019201 1 5987435 5987435 5987435 5987435.0000 +betroth 030501 1 5987435 5987435 5987435 5987435.0000 +Manhattanize 030502 1 28357832 28357832 28357832 28357832.0000 +imprint 030503 1 39654943 39654943 39654943 39654943.0000 +swelling 031901 1 5987435 5987435 5987435 5987435.0000 +interrelationships 036001 1 5987435 5987435 5987435 5987435.0000 +riser 036002 1 28357832 28357832 28357832 28357832.0000 +bee 038001 1 5987435 5987435 5987435 5987435.0000 +kanji 038002 1 28357832 28357832 28357832 28357832.0000 +dental 038003 1 39654943 39654943 39654943 39654943.0000 +railway 038011 1 5987435 5987435 5987435 5987435.0000 +validate 038012 1 28357832 28357832 28357832 28357832.0000 +normalizes 038013 1 39654943 39654943 39654943 39654943.0000 +Kline 038101 1 5987435 5987435 5987435 5987435.0000 +Anatole 038102 1 28357832 28357832 28357832 28357832.0000 +partridges 038103 1 39654943 39654943 39654943 39654943.0000 +recruited 038201 1 5987435 5987435 5987435 5987435.0000 +dimensions 038202 1 28357832 28357832 28357832 28357832.0000 +Chicana 038203 1 39654943 39654943 39654943 39654943.0000 +select t3.companynr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 group by companynr,fld3; +companynr fld3 sum(price) +512 boat 786542 +512 capably 786542 +512 cupboard 786542 +512 decliner 786542 +512 descendants 786542 +512 dopers 786542 +512 erases 786542 +512 Micronesia 786542 +512 Miles 786542 +512 skies 786542 +select t2.companynr,count(*),min(fld3),max(fld3),sum(price),avg(price) from t2,t3 where t3.companynr >= 30 and t3.companynr <= 58 and t3.t2nr = t2.fld1 and 1+1=2 group by t2.companynr; +companynr count(*) min(fld3) max(fld3) sum(price) avg(price) +00 1 Omaha Omaha 5987435 5987435.0000 +36 1 dubbed dubbed 28357832 28357832.0000 +37 83 Abraham Wotan 1908978016 22999735.1325 +50 2 scribbled tapestry 68012775 34006387.5000 +select t3.companynr+0,t3.t2nr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 37 group by 1,t3.t2nr,fld3,fld3,fld3,fld3,fld3 order by fld1; +t3.companynr+0 t2nr fld3 sum(price) +37 1 Omaha 5987435 +37 11401 breaking 5987435 +37 11402 Romans 28357832 +37 11403 intercepted 39654943 +37 11501 bewilderingly 5987435 +37 11701 astound 5987435 +37 11702 admonishing 28357832 +37 11703 sumac 39654943 +37 12001 flanking 5987435 +37 12003 combed 39654943 +37 12301 Eulerian 5987435 +37 12302 dubbed 28357832 +37 12303 Kane 39654943 +37 12501 annihilates 5987435 +37 12602 Wotan 28357832 +37 12603 snatching 39654943 +37 12701 grazing 5987435 +37 12702 Baird 28357832 +37 12703 celery 39654943 +37 13601 handgun 5987435 +37 13602 foldout 28357832 +37 13603 mystic 39654943 +37 13801 intelligibility 5987435 +37 13802 Augustine 28357832 +37 13803 teethe 39654943 +37 13901 scholastics 5987435 +37 16001 audiology 5987435 +37 16201 wallet 5987435 +37 16202 parters 28357832 +37 16301 eschew 5987435 +37 16302 quitter 28357832 +37 16303 neat 39654943 +37 18001 jarring 5987435 +37 18002 tinily 28357832 +37 18003 balled 39654943 +37 18012 impulsive 28357832 +37 18013 starlet 39654943 +37 18021 lawgiver 5987435 +37 18022 stated 28357832 +37 18023 readable 39654943 +37 18032 testicle 28357832 +37 18033 Parsifal 39654943 +37 18041 Punjab 5987435 +37 18042 Merritt 28357832 +37 18043 Quixotism 39654943 +37 18051 sureties 5987435 +37 18052 puddings 28357832 +37 18053 tapestry 39654943 +37 18061 trimmings 5987435 +37 18062 humility 28357832 +37 18101 tragedies 5987435 +37 18102 skulking 28357832 +37 18103 flint 39654943 +37 18201 relaxing 5987435 +37 18202 offload 28357832 +37 18402 suites 28357832 +37 18403 lists 39654943 +37 18601 vacuuming 5987435 +37 18602 dentally 28357832 +37 18603 humanness 39654943 +37 18801 inch 5987435 +37 18802 Weissmuller 28357832 +37 18803 irresponsibly 39654943 +37 18811 repetitions 5987435 +37 18812 Antares 28357832 +37 19101 ventilate 5987435 +37 19102 pityingly 28357832 +37 19103 interdependent 39654943 +37 19201 Graves 5987435 +37 30501 neonatal 5987435 +37 30502 scribbled 28357832 +37 30503 chafe 39654943 +37 31901 realtor 5987435 +37 36001 elite 5987435 +37 36002 funereal 28357832 +37 38001 Conley 5987435 +37 38002 lectured 28357832 +37 38003 Abraham 39654943 +37 38011 groupings 5987435 +37 38012 dissociate 28357832 +37 38013 coexist 39654943 +37 38101 rusting 5987435 +37 38102 galling 28357832 +37 38103 obliterates 39654943 +37 38201 resumes 5987435 +37 38202 analyzable 28357832 +37 38203 terminator 39654943 +select sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1= t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008; +sum(price) +234298 +select t2.fld1,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1 = t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008 or t3.t2nr = t2.fld1 and t2.fld1 = 38008 group by t2.fld1; +fld1 sum(price) +038008 234298 +explain select fld3 from t2 where 1>2 or 2>3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +explain select fld3 from t2 where fld1=fld1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502; +companynr fld1 +34 250501 +34 250502 +select companynr,fld1 from t2 WHERE fld1>=250501 HAVING fld1<=250502; +companynr fld1 +34 250501 +34 250502 +select companynr,count(*) as count,sum(fld1) as sum from t2 group by companynr having count > 40 and sum/count >= 120000; +companynr count sum +00 82 10355753 +29 95 14473298 +34 70 17788966 +37 588 83602098 +41 52 12816335 +select companynr from t2 group by companynr having count(*) > 40 and sum(fld1)/count(*) >= 120000 ; +companynr +00 +29 +34 +37 +41 +select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by companyname having t2.companynr >= 40; +companynr companyname count(*) +68 company 10 12 +50 company 11 11 +40 company 5 37 +41 company 6 52 +53 company 7 4 +58 company 8 23 +65 company 9 10 +select count(*) from t2; +count(*) +1199 +select count(*) from t2 where fld1 < 098024; +count(*) +387 +select min(fld1) from t2 where fld1>= 098024; +min(fld1) +98024 +select max(fld1) from t2 where fld1>= 098024; +max(fld1) +1232609 +select count(*) from t3 where price2=76234234; +count(*) +4181 +select count(*) from t3 where companynr=512 and price2=76234234; +count(*) +4181 +explain select min(fld1),max(fld1),count(*) from t2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +select min(fld1),max(fld1),count(*) from t2; +min(fld1) max(fld1) count(*) +0 1232609 1199 +select min(t2nr),max(t2nr) from t3 where t2nr=2115 and price2=823742; +min(t2nr) max(t2nr) +2115 2115 +select count(*),min(t2nr),max(t2nr) from t3 where name='spates' and companynr=78; +count(*) min(t2nr) max(t2nr) +4181 4 41804 +select t2nr,count(*) from t3 where name='gems' group by t2nr limit 20; +t2nr count(*) +9 1 +19 1 +29 1 +39 1 +49 1 +59 1 +69 1 +79 1 +89 1 +99 1 +109 1 +119 1 +129 1 +139 1 +149 1 +159 1 +169 1 +179 1 +189 1 +199 1 +select max(t2nr) from t3 where price=983543950; +max(t2nr) +41807 +select t1.period from t3 = t1 limit 1; +period +1001 +select t1.period from t1 as t1 limit 1; +period +9410 +select t1.period as "Nuvarande period" from t1 as t1 limit 1; +Nuvarande period +9410 +select period as ok_period from t1 limit 1; +ok_period +9410 +select period as ok_period from t1 group by ok_period limit 1; +ok_period +9410 +select 1+1 as summa from t1 group by summa limit 1; +summa +2 +select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; +Nuvarande period +9410 +show tables; +Tables_in_test +t1 +t2 +t3 +t4 +show tables from test like "s%"; +Tables_in_test (s%) +show tables from test like "t?"; +Tables_in_test (t?) +show full columns from t2; +Field Type Collation Null Key Default Extra Privileges Comment +auto int(11) NULL NO PRI NULL auto_increment # +fld1 int(6) unsigned zerofill NULL NO UNI 000000 # +companynr tinyint(2) unsigned zerofill NULL NO 00 # +fld3 char(30) latin1_swedish_ci NO MUL # +fld4 char(35) latin1_swedish_ci NO # +fld5 char(35) latin1_swedish_ci NO # +fld6 char(4) latin1_swedish_ci NO # +show full columns from t2 from test like 'f%'; +Field Type Collation Null Key Default Extra Privileges Comment +fld1 int(6) unsigned zerofill NULL NO UNI 000000 # +fld3 char(30) latin1_swedish_ci NO MUL # +fld4 char(35) latin1_swedish_ci NO # +fld5 char(35) latin1_swedish_ci NO # +fld6 char(4) latin1_swedish_ci NO # +show full columns from t2 from test like 's%'; +Field Type Collation Null Key Default Extra Privileges Comment +show keys from t2; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE +t2 0 fld1 1 fld1 A 1199 NULL NULL BTREE +t2 1 fld3 1 fld3 A NULL NULL NULL BTREE +drop table t4, t3, t2, t1; +CREATE TABLE t1 ( +cont_nr int(11) NOT NULL auto_increment, +ver_nr int(11) NOT NULL default '0', +aufnr int(11) NOT NULL default '0', +username varchar(50) NOT NULL default '', +hdl_nr int(11) NOT NULL default '0', +eintrag date NOT NULL default '0000-00-00', +st_klasse varchar(40) NOT NULL default '', +st_wert varchar(40) NOT NULL default '', +st_zusatz varchar(40) NOT NULL default '', +st_bemerkung varchar(255) NOT NULL default '', +kunden_art varchar(40) NOT NULL default '', +mcbs_knr int(11) default NULL, +mcbs_aufnr int(11) NOT NULL default '0', +schufa_status char(1) default '?', +bemerkung text, +wirknetz text, +wf_igz int(11) NOT NULL default '0', +tarifcode varchar(80) default NULL, +recycle char(1) default NULL, +sim varchar(30) default NULL, +mcbs_tpl varchar(30) default NULL, +emp_nr int(11) NOT NULL default '0', +laufzeit int(11) default NULL, +hdl_name varchar(30) default NULL, +prov_hdl_nr int(11) NOT NULL default '0', +auto_wirknetz varchar(50) default NULL, +auto_billing varchar(50) default NULL, +touch timestamp NOT NULL, +kategorie varchar(50) default NULL, +kundentyp varchar(20) NOT NULL default '', +sammel_rech_msisdn varchar(30) NOT NULL default '', +p_nr varchar(9) NOT NULL default '', +suffix char(3) NOT NULL default '', +PRIMARY KEY (cont_nr), +KEY idx_aufnr(aufnr), +KEY idx_hdl_nr(hdl_nr), +KEY idx_st_klasse(st_klasse), +KEY ver_nr(ver_nr), +KEY eintrag_idx(eintrag), +KEY emp_nr_idx(emp_nr), +KEY wf_igz(wf_igz), +KEY touch(touch), +KEY hdl_tag(eintrag,hdl_nr), +KEY prov_hdl_nr(prov_hdl_nr), +KEY mcbs_aufnr(mcbs_aufnr), +KEY kundentyp(kundentyp), +KEY p_nr(p_nr,suffix) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES (3359356,405,3359356,'Mustermann Musterfrau',52500,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1485525,2122316,'+','','N',1909160,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',3,24,'MobilCom Shop Koeln',52500,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359357,468,3359357,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1503580,2139699,'+','','P',1909171,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359358,407,3359358,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1501358,2137473,'N','','N',1909159,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359359,468,3359359,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1507831,2143894,'+','','P',1909162,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359360,0,0,'Mustermann Musterfrau',29674907,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1900169997,2414578,'+',NULL,'N',1909148,'',NULL,NULL,'RV99066_2',20,NULL,'POS',29674907,NULL,NULL,20010202105916,'Mobilfunk','','','97317481','007'); +INSERT INTO t1 VALUES (3359361,406,3359361,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag storniert','','(7001-84):Storno, Kd. möchte nicht mehr','privat',NULL,0,'+','','P',1909150,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1509984,2145874,'+','','P',1909154,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie; +Kundentyp kategorie +Privat (Private Nutzung) Mobilfunk +Warnings: +Warning 1052 Column 'kundentyp' in group statement is ambiguous +drop table t1; +SHOW STATUS LIKE 'Compression'; +Variable_name Value +Compression ON diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result index 2508d751b46..4f49f77d46c 100644 --- a/mysql-test/r/connect.result +++ b/mysql-test/r/connect.result @@ -20,6 +20,10 @@ time_zone_transition_type user show tables; Tables_in_test +connect(localhost,root,z,test2,MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'root'@'localhost' (using password: YES) +connect(localhost,root,z,test,MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'root'@'localhost' (using password: YES) grant ALL on *.* to test@localhost identified by "gambling"; grant ALL on *.* to test@127.0.0.1 identified by "gambling"; show tables; @@ -43,6 +47,14 @@ time_zone_transition_type user show tables; Tables_in_test +connect(localhost,test,,test2,MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'test'@'localhost' (using password: NO) +connect(localhost,test,,"",MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'test'@'localhost' (using password: NO) +connect(localhost,test,zorro,test2,MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) +connect(localhost,test,zorro,test,MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) update mysql.user set password=old_password("gambling2") where user=_binary"test"; flush privileges; set password=""; @@ -70,6 +82,14 @@ time_zone_transition_type user show tables; Tables_in_test +connect(localhost,test,,test2,MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'test'@'localhost' (using password: NO) +connect(localhost,test,,test,MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'test'@'localhost' (using password: NO) +connect(localhost,test,zorro,test2,MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) +connect(localhost,test,zorro,test,MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) delete from mysql.user where user=_binary"test"; flush privileges; create table t1 (id integer not null auto_increment primary key); diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 3e7c9d6eb4a..bbd4a60c5b1 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1,4 +1,4 @@ -drop table if exists t1,t2,t3; +drop table if exists t1,t2,t3,t4,t5; drop database if exists mysqltest; create table t1 (b char(0)); insert into t1 values (""),(null); @@ -259,21 +259,6 @@ select * from t1; 0 1 2 0 0 1 drop table t1; -create table t1 select 1,2,3; -create table if not exists t1 select 1,2; -Warnings: -Note 1050 Table 't1' already exists -create table if not exists t1 select 1,2,3,4; -ERROR 21S01: Column count doesn't match value count at row 1 -create table if not exists t1 select 1; -Warnings: -Note 1050 Table 't1' already exists -select * from t1; -1 2 3 -1 2 3 -0 1 2 -0 0 1 -drop table t1; create table t1 (a int not null, b int, primary key (a)); insert into t1 values (1,1); create table if not exists t1 select 2; @@ -287,7 +272,6 @@ a b create table if not exists t1 select 3 as 'a',4 as 'b'; Warnings: Note 1050 Table 't1' already exists -Warning 1364 Field 'a' doesn't have a default value create table if not exists t1 select 3 as 'a',3 as 'b'; ERROR 23000: Duplicate entry '3' for key 1 select * from t1; @@ -641,3 +625,138 @@ create table if not exists t1 (a int); Warnings: Note 1050 Table 't1' already exists drop table t1; +create table t1 ( +a varchar(112) charset utf8 collate utf8_bin not null, +primary key (a) +) select 'test' as a ; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(112) character set utf8 collate utf8_bin NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +CREATE TABLE t2 ( +a int(11) default NULL +); +insert into t2 values(111); +create table t1 ( +a varchar(12) charset utf8 collate utf8_bin not null, +b int not null, primary key (a) +) select a, 1 as b from t2 ; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(12) character set utf8 collate utf8_bin NOT NULL, + `b` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1 ( +a varchar(12) charset utf8 collate utf8_bin not null, +b int not null, primary key (a) +) select a, 1 as c from t2 ; +Warnings: +Warning 1364 Field 'b' doesn't have a default value +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` int(11) NOT NULL, + `a` varchar(12) character set utf8 collate utf8_bin NOT NULL, + `c` bigint(1) NOT NULL default '0', + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1 ( +a varchar(12) charset utf8 collate utf8_bin not null, +b int null, primary key (a) +) select a, 1 as c from t2 ; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `b` int(11) default NULL, + `a` varchar(12) character set utf8 collate utf8_bin NOT NULL, + `c` bigint(1) NOT NULL default '0', + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1 ( +a varchar(12) charset utf8 collate utf8_bin not null, +b int not null, primary key (a) +) select 'a' as a , 1 as b from t2 ; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(12) character set utf8 collate utf8_bin NOT NULL, + `b` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1 ( +a varchar(12) charset utf8 collate utf8_bin, +b int not null, primary key (a) +) select 'a' as a , 1 as b from t2 ; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(12) character set utf8 collate utf8_bin NOT NULL default '', + `b` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1, t2; +create table t1 ( +a1 int not null, +a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int +); +insert into t1 values (1,1,1, 1,1,1, 1,1,1); +create table t2 ( +a1 varchar(12) charset utf8 collate utf8_bin not null, +a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int, +primary key (a1) +) select a1,a2,a3,a4,a5,a6,a7,a8,a9 from t1 ; +drop table t2; +create table t2 ( +a1 varchar(12) charset utf8 collate utf8_bin, +a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int +) select a1,a2,a3,a4,a5,a6,a7,a8,a9 from t1; +drop table t1, t2; +create table t1 ( +a1 int, a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int +); +insert into t1 values (1,1,1, 1,1,1, 1,1,1); +create table t2 ( +a1 varchar(12) charset utf8 collate utf8_bin not null, +a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int, +primary key (a1) +) select a1,a2,a3,a4,a5,a6,a7,a8,a9 from t1 ; +drop table t2; +create table t2 ( a int default 3, b int default 3) +select a1,a2 from t1; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` int(11) default '3', + `b` int(11) default '3', + `a1` int(11) default NULL, + `a2` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1, t2; +create table t1 (i int) engine=myisam max_rows=100000000000; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 MAX_ROWS=4294967295 +alter table t1 max_rows=100; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 MAX_ROWS=100 +alter table t1 max_rows=100000000000; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 MAX_ROWS=4294967295 +drop table t1; diff --git a/mysql-test/r/csv.result b/mysql-test/r/csv.result index ea0d34271b5..3c87c1f4b92 100644 --- a/mysql-test/r/csv.result +++ b/mysql-test/r/csv.result @@ -4929,3 +4929,74 @@ Warnings: Note 1051 Unknown table 't2' Note 1051 Unknown table 't3' Note 1051 Unknown table 't4' +DROP TABLE IF EXISTS bug13894; +CREATE TABLE bug13894 ( val integer ) ENGINE = CSV; +INSERT INTO bug13894 VALUES (5); +INSERT INTO bug13894 VALUES (10); +INSERT INTO bug13894 VALUES (11); +INSERT INTO bug13894 VALUES (10); +SELECT * FROM bug13894; +val +5 +10 +11 +10 +UPDATE bug13894 SET val=6 WHERE val=10; +SELECT * FROM bug13894; +val +5 +11 +6 +6 +DROP TABLE bug13894; +DROP TABLE IF EXISTS bug14672; +CREATE TABLE bug14672 (c1 integer) engine = CSV; +INSERT INTO bug14672 VALUES (1), (2), (3); +SELECT * FROM bug14672; +c1 +1 +2 +3 +DELETE FROM bug14672 WHERE c1 = 2; +SELECT * FROM bug14672; +c1 +1 +3 +INSERT INTO bug14672 VALUES (4); +SELECT * FROM bug14672; +c1 +1 +3 +4 +INSERT INTO bug14672 VALUES (5); +SELECT * FROM bug14672; +c1 +1 +3 +4 +5 +DROP TABLE bug14672; +create table t1 (a int) engine=csv; +insert t1 values (1); +delete from t1; +affected rows: 1 +delete from t1; +affected rows: 0 +insert t1 values (1),(2); +delete from t1; +affected rows: 2 +insert t1 values (1),(2),(3); +flush tables; +delete from t1; +affected rows: 3 +insert t1 values (1),(2),(3),(4); +flush tables; +select count(*) from t1; +count(*) +4 +delete from t1; +affected rows: 4 +insert t1 values (1),(2),(3),(4),(5); +truncate table t1; +affected rows: 0 +drop table t1; diff --git a/mysql-test/r/ctype_cp1250_ch.result b/mysql-test/r/ctype_cp1250_ch.result index 7b2ca7d7e0e..533bfb8cb53 100644 --- a/mysql-test/r/ctype_cp1250_ch.result +++ b/mysql-test/r/ctype_cp1250_ch.result @@ -19,3 +19,26 @@ SELECT * FROM t1 WHERE popisek LIKE '2005-01-1'; popisek 2005-01-1 drop table t1; +set names cp1250; +CREATE TABLE t1 +( +id INT AUTO_INCREMENT PRIMARY KEY, +str VARCHAR(32) CHARACTER SET cp1250 COLLATE cp1250_czech_cs NOT NULL default '', +UNIQUE KEY (str) +); +INSERT INTO t1 VALUES (NULL, 'a'); +INSERT INTO t1 VALUES (NULL, 'aa'); +INSERT INTO t1 VALUES (NULL, 'aaa'); +INSERT INTO t1 VALUES (NULL, 'aaaa'); +INSERT INTO t1 VALUES (NULL, 'aaaaa'); +INSERT INTO t1 VALUES (NULL, 'aaaaaa'); +INSERT INTO t1 VALUES (NULL, 'aaaaaaa'); +select * from t1 where str like 'aa%'; +id str +2 aa +3 aaa +4 aaaa +5 aaaaa +6 aaaaaa +7 aaaaaaa +drop table t1; diff --git a/mysql-test/r/ctype_cp932_binlog.result b/mysql-test/r/ctype_cp932_binlog.result new file mode 100644 index 00000000000..d04fce7738c --- /dev/null +++ b/mysql-test/r/ctype_cp932_binlog.result @@ -0,0 +1,17 @@ +drop table if exists t1; +set names cp932; +set character_set_database = cp932; +RESET MASTER; +CREATE TABLE t1(f1 blob); +PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)'; +SET @var1= x'8300'; +EXECUTE stmt1 USING @var1; +SHOW BINLOG EVENTS FROM 98; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 98 Query 1 185 use `test`; CREATE TABLE t1(f1 blob) +master-bin.000001 185 User var 1 224 @`var1`=_binary 0x8300 COLLATE binary +master-bin.000001 224 Query 1 317 use `test`; INSERT INTO t1 VALUES(@'var1') +SELECT HEX(f1) FROM t1; +HEX(f1) +8300 +DROP table t1; diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index da0007fdfbe..1b92da2a7a3 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -181,11 +181,18 @@ select * from t1 where a=_koi8r'×ÁÓÑ'; a ×ÁÓÑ select * from t1 where a=concat(_koi8r'×ÁÓÑ'); -ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (koi8r_general_ci,COERCIBLE) for operation '=' +a +×ÁÓÑ select * from t1 where a=_latin1'×ÁÓÑ'; ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE) for operation '=' drop table t1; set names latin1; +create table t1 (a char(10) character set utf8 collate utf8_bin); +insert into t1 values (' xxx'); +select * from t1 where a=lpad('xxx',10,' '); +a + xxx +drop table t1; set names koi8r; create table t1 (c1 char(10) character set cp1251); insert into t1 values ('ß'); diff --git a/mysql-test/r/ctype_uca.result b/mysql-test/r/ctype_uca.result index 4b245c69d2a..3e286c77c00 100644 --- a/mysql-test/r/ctype_uca.result +++ b/mysql-test/r/ctype_uca.result @@ -2015,6 +2015,112 @@ Z,z,Ź,ź,Å»,ż,Ž,ž Ç Ç‚ ǃ +select group_concat(c1 order by c1) from t1 group by c1 collate utf8_hungarian_ci; +group_concat(c1 order by c1) +÷ +× +A,a,À,Ã,Â,Ã,Ä,Ã…,à ,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç» +AA,Aa,aA,aa +Æ,æ,Ç¢,Ç£,Ǽ,ǽ +B,b +Æ€ +Æ +Æ‚,ƃ +C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä +CH,Ch,cH,ch +Ƈ,ƈ +D,d,ÄŽ,Ä +DZ,Dz,dZ,dz,Ç„,Ç…,dž,DZ,Dz,dz +Ä,Ä‘ +Ɖ +ÆŠ +Æ‹,ÆŒ +Ã,ð +E,e,È,É,Ê,Ë,è,é,ê,ë,Ä’,Ä“,Ä”,Ä•,Ä–,Ä—,Ę,Ä™,Äš,Ä› +ÆŽ,Ç +Æ +Æ +F,f +Æ‘,Æ’ +G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ +Ǥ,Ç¥ +Æ“ +Æ” +Æ¢,Æ£ +H,h,Ĥ,Ä¥ +Æ•,Ƕ +Ħ,ħ +I,i,ÃŒ,Ã,ÃŽ,Ã,ì,Ã,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä,Ä®,į,Ä°,Ç,Ç +IJ,Ij,iJ,ij,IJ,ij +ı +Æ— +Æ– +J,j,Ä´,ĵ,Ç° +K,k,Ķ,Ä·,Ǩ,Ç© +Ƙ,Æ™ +L,l,Ĺ,ĺ,Ä»,ļ,Ľ,ľ +Ä¿,Å€ +LJ,Lj,lJ,lj,LJ,Lj,lj +LL,Ll,lL,ll +Å,Å‚ +Æš +Æ› +M,m +N,n,Ñ,ñ,Ń,Å„,Å…,ņ,Ň,ň,Ǹ,ǹ +NJ,Nj,nJ,nj,ÇŠ,Ç‹,ÇŒ +Æ +Æž +ÅŠ,Å‹ +O,o,Ã’,Ó,Ô,Õ,ò,ó,ô,õ,ÅŒ,Å,ÅŽ,Å,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç +OE,Oe,oE,oe,Å’,Å“ +Ö,ö,Å,Å‘ +Ø,ø,Ǿ,Ç¿ +Ɔ +ÆŸ +P,p +Ƥ,Æ¥ +Q,q +ĸ +R,r,Å”,Å•,Å–,Å—,Ř,Å™ +RR,Rr,rR,rr +Ʀ +S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿ +SS,Ss,sS,ss,ß +Æ© +ƪ +T,t,Å¢,Å£,Ť,Å¥ +ƾ +Ŧ,ŧ +Æ« +Ƭ,Æ +Æ® +U,u,Ù,Ú,Û,ù,ú,û,Ũ,Å©,Ū,Å«,Ŭ,Å,Å®,ů,Ų,ų,Ư,Æ°,Ç“,Ç”,Ç•,Ç–,Ç—,ǘ,Ç™,Çš,Ç›,Çœ +Ãœ,ü,Å°,ű +Æœ +Ʊ +V,v +Ʋ +W,w,Å´,ŵ +X,x +Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ +Ƴ,Æ´ +Z,z,Ź,ź,Å»,ż,Ž,ž +Æ +Ƶ,ƶ +Æ·,Ç®,ǯ +Ƹ,ƹ +ƺ +Þ,þ +Æ¿,Ç· +Æ» +Ƨ,ƨ +Ƽ,ƽ +Æ„,Æ… +ʼn +Ç€ +Ç +Ç‚ +ǃ drop table t1; SET NAMES utf8; CREATE TABLE t1 (c varchar(255) NOT NULL COLLATE utf8_general_ci, INDEX (c)); diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 65b5a1cbba8..d11d25f9b35 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -685,6 +685,13 @@ hex(a) 005B 803D drop table t1; +create table t1(f1 varchar(5) CHARACTER SET ucs2 COLLATE ucs2_bin NOT NULL) engine=InnoDB; +insert into t1 values('a'); +create index t1f1 on t1(f1); +select f1 from t1 where f1 like 'a%'; +f1 +a +drop table t1; CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3)); INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0); update t1 set b=a; diff --git a/mysql-test/r/ctype_ujis.result b/mysql-test/r/ctype_ujis.result index 15de93440fc..2e14fe34430 100644 --- a/mysql-test/r/ctype_ujis.result +++ b/mysql-test/r/ctype_ujis.result @@ -2317,7 +2317,7 @@ CREATE TABLE t2(c2 char(2)) default charset = ujis; INSERT INTO t1 VALUES(_ujis 0xA4A2); CREATE PROCEDURE sp1() BEGIN -DECLARE a CHAR(1); +DECLARE a CHAR(2) CHARSET ujis; DECLARE cur1 CURSOR FOR SELECT c1 FROM t1; OPEN cur1; FETCH cur1 INTO a; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 874983daff2..c57b06f4895 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1095,6 +1095,11 @@ char(0xff,0x8f using utf8) ÿ Warnings: Warning 1300 Invalid utf8 character string: 'FF8F' +select convert(char(0xff,0x8f) using utf8); +convert(char(0xff,0x8f) using utf8) +ÿ +Warnings: +Warning 1300 Invalid utf8 character string: 'FF8F' set sql_mode=traditional; select char(0xff,0x8f using utf8); char(0xff,0x8f using utf8) @@ -1116,6 +1121,11 @@ char(2557 using utf8) NULL Warnings: Error 1300 Invalid utf8 character string: 'FD' +select convert(char(0xff,0x8f) using utf8); +convert(char(0xff,0x8f) using utf8) +NULL +Warnings: +Error 1300 Invalid utf8 character string: 'FF8F' select hex(convert(char(2557 using latin1) using utf8)); hex(convert(char(2557 using latin1) using utf8)) 09C3BD diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result index 74ab1e35534..f8189266e50 100644 --- a/mysql-test/r/date_formats.result +++ b/mysql-test/r/date_formats.result @@ -495,3 +495,11 @@ f1 f2 Warnings: Warning 1292 Truncated incorrect date value: '2003-04-05 g' Warning 1292 Truncated incorrect datetime value: '2003-04-05 10:11:12.101010234567' +create table t1 (f1 datetime); +insert into t1 (f1) values ("2005-01-01"); +insert into t1 (f1) values ("2005-02-01"); +select date_format(f1, "%m") as d1, date_format(f1, "%M") as d2 from t1 order by date_format(f1, "%M"); +d1 d2 +02 February +01 January +drop table t1; diff --git a/mysql-test/r/drop_temp_table.result b/mysql-test/r/drop_temp_table.result index 26b8511661a..96481341bd6 100644 --- a/mysql-test/r/drop_temp_table.result +++ b/mysql-test/r/drop_temp_table.result @@ -1,3 +1,4 @@ +drop database if exists `drop-temp+table-test`; reset master; create database `drop-temp+table-test`; use `drop-temp+table-test`; diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index 7e18cb9f75f..f9b13beb6e5 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -40,14 +40,14 @@ CREATE TABLE federated.t1 ( ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t3'; -ERROR HY000: Can't create federated table. Foreign data src error : ': 1146 : Table 'federated.t3' doesn't exist' +ERROR HY000: Can't create federated table. Foreign data src error: error: 1146 'Table 'federated.t3' doesn't exist' CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, `name` varchar(32) NOT NULL default '' ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1'; -ERROR HY000: Unable to connect to foreign data source - database ' database federated username user hostname 127.0.0.1'! +ERROR HY000: Unable to connect to foreign data source: database: 'federated' username: 'user' hostname: '127.0.0.1' DROP TABLE IF EXISTS federated.t1; Warnings: Note 1051 Unknown table 't1' @@ -1490,6 +1490,33 @@ id name DROP TABLE federated.alter_me; DROP TABLE federated.normal_table; DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`bitty` bit(3) +) DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`bitty` bit(3) +) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +INSERT INTO federated.t1 VALUES (b'001'); +INSERT INTO federated.t1 VALUES (b'010'); +INSERT INTO federated.t1 VALUES (b'011'); +INSERT INTO federated.t1 VALUES (b'100'); +INSERT INTO federated.t1 VALUES (b'101'); +INSERT INTO federated.t1 VALUES (b'110'); +INSERT INTO federated.t1 VALUES (b'111'); +select * FROM federated.t1; +bitty + + + + + + + +drop table federated.t1; +drop table federated.t1; +DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index ea0ffe9d7dd..7e2e0a56212 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -429,4 +429,11 @@ REPAIR TABLE t1; Table Op Msg_type Msg_text test.t1 repair status OK SET myisam_repair_threads=@@global.myisam_repair_threads; +INSERT INTO t1 VALUES('testword\'\''); +SELECT a FROM t1 WHERE MATCH a AGAINST('testword' IN BOOLEAN MODE); +a +testword'' +SELECT a FROM t1 WHERE MATCH a AGAINST('testword\'\'' IN BOOLEAN MODE); +a +testword'' DROP TABLE t1; diff --git a/mysql-test/r/fulltext2.result b/mysql-test/r/fulltext2.result index 0b1d8eb9a15..72c6b2d22ed 100644 --- a/mysql-test/r/fulltext2.result +++ b/mysql-test/r/fulltext2.result @@ -215,3 +215,24 @@ select count(*) from t1 where match a against ('aaazzz' in boolean mode); count(*) 262 drop table t1; +set names utf8; +create table t1(a text,fulltext(a)) collate=utf8_swedish_ci; +insert into t1 values('test test '),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'); +delete from t1 limit 1; +drop table t1; +set names latin1; diff --git a/mysql-test/r/func_equal.result b/mysql-test/r/func_equal.result index fe5e5b1b371..4750af6e8d8 100644 --- a/mysql-test/r/func_equal.result +++ b/mysql-test/r/func_equal.result @@ -33,3 +33,12 @@ id value select * from t1 where id <=> value or value<=>id; id value drop table t1,t2; +create table t1 (a bigint unsigned); +insert into t1 values (4828532208463511553); +select * from t1 where a = '4828532208463511553'; +a +4828532208463511553 +select * from t1 where a in ('4828532208463511553'); +a +4828532208463511553 +drop table t1; diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 6461c393d51..2a36e6fe17b 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -93,7 +93,7 @@ explain extended select grp,group_concat(distinct c order by c desc) from t1 gro id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 9 Using filesort Warnings: -Note 1003 select `test`.`t1`.`grp` AS `grp`,group_concat(distinct `test`.`t1`.`c` order by `test`.`t1`.`c` separator ',') AS `group_concat(distinct c order by c desc)` from `test`.`t1` group by `test`.`t1`.`grp` +Note 1003 select `test`.`t1`.`grp` AS `grp`,group_concat(distinct `test`.`t1`.`c` order by `test`.`t1`.`c` DESC separator ',') AS `group_concat(distinct c order by c desc)` from `test`.`t1` group by `test`.`t1`.`grp` select grp,group_concat(c order by c separator ",") from t1 group by grp; grp group_concat(c order by c separator ",") 1 a @@ -113,7 +113,7 @@ explain extended select grp,group_concat(distinct c order by c separator ",") fr id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 9 Using filesort Warnings: -Note 1003 select `test`.`t1`.`grp` AS `grp`,group_concat(distinct `test`.`t1`.`c` order by `test`.`t1`.`c` separator ',') AS `group_concat(distinct c order by c separator ",")` from `test`.`t1` group by `test`.`t1`.`grp` +Note 1003 select `test`.`t1`.`grp` AS `grp`,group_concat(distinct `test`.`t1`.`c` order by `test`.`t1`.`c` ASC separator ',') AS `group_concat(distinct c order by c separator ",")` from `test`.`t1` group by `test`.`t1`.`grp` select grp,group_concat(distinct c order by c desc separator ",") from t1 group by grp; grp group_concat(distinct c order by c desc separator ",") 1 a @@ -163,7 +163,7 @@ show warnings; Level Code Message Warning 1260 1 line(s) were cut by GROUP_CONCAT() set group_concat_max_len = 1024; -select group_concat(sum(a)) from t1 group by grp; +select group_concat(sum(c)) 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 'order clause' @@ -596,3 +596,18 @@ GROUP_CONCAT(a ORDER BY a) ,x ,z DROP TABLE t1; +set names latin1; +create table t1 (a char, b char); +insert into t1 values ('a', 'a'), ('a', 'b'), ('b', 'a'), ('b', 'b'); +create table t2 select group_concat(b) as a from t1 where a = 'a'; +create table t3 (select group_concat(a) as a from t1 where a = 'a') union +(select group_concat(b) as a from t1 where a = 'b'); +select charset(a) from t2; +charset(a) +latin1 +select charset(a) from t3; +charset(a) +latin1 +latin1 +drop table t1, t2, t3; +set names default; diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index b7ba2273956..fba274b9bb1 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -170,6 +170,12 @@ insert into t1 values (1); select rand(i) from t1; ERROR HY000: Incorrect arguments to RAND drop table t1; +create table t1 (a varchar(90), ts datetime not null, index (a)) engine=innodb default charset=utf8; +insert into t1 values ('http://www.foo.com/', now()); +select a from t1 where a='http://www.foo.com/' order by abs(timediff(ts, 0)); +a +http://www.foo.com/ +drop table t1; set sql_mode='traditional'; select ln(-1); ln(-1) diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result index f209866d953..d984eee80fa 100644 --- a/mysql-test/r/func_sapdb.result +++ b/mysql-test/r/func_sapdb.result @@ -180,8 +180,8 @@ Field Type Null Key Default Extra f1 date NO 0000-00-00 f2 datetime YES NULL f3 time YES NULL -f4 time NO 00:00:00 -f5 time NO 00:00:00 +f4 time YES NULL +f5 time YES NULL f6 time NO 00:00:00 f7 datetime YES NULL f8 date YES NULL diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 90857ecfc6d..049ba784dc9 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -665,6 +665,12 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (pointfromtext('point(1,1)')); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field drop table t1; +select (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))); +(asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))) +POINT(10 10) +select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))); +(asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))) +POINT(10 10) create table t1 (s1 geometry not null,s2 char(100)); create trigger t1_bu before update on t1 for each row set new.s1 = null; insert into t1 values (null,null); diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 14393be1cc8..448847bc919 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -238,7 +238,7 @@ Grants for drop_user@localhost GRANT USAGE ON *.* TO 'drop_user'@'localhost' drop user drop_user@localhost; revoke all privileges, grant option from drop_user@localhost; -ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users +ERROR HY000: Can't revoke all privileges for one or more of the requested users grant select(a) on test.t1 to drop_user1@localhost; grant select on test.t1 to drop_user2@localhost; grant select on test.* to drop_user3@localhost; @@ -247,7 +247,7 @@ drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; -ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users +ERROR HY000: Can't revoke all privileges for one or more of the requested users drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; ERROR HY000: Operation DROP USER failed for 'drop_user1'@'localhost','drop_user2'@'localhost','drop_user3'@'localhost','drop_user4'@'localhost' @@ -594,3 +594,24 @@ flush privileges; set @user123="non-existent"; select * from mysql.db where user=@user123; Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv +set names koi8r; +create database ÂÄ; +grant select on ÂÄ.* to root@localhost; +select hex(Db) from mysql.db where Db='ÂÄ'; +hex(Db) +D0B1D0B4 +show grants for root@localhost; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT SELECT ON `ÂÄ`.* TO 'root'@'localhost' +flush privileges; +show grants for root@localhost; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT SELECT ON `ÂÄ`.* TO 'root'@'localhost' +drop database ÂÄ; +revoke all privileges on ÂÄ.* from root@localhost; +show grants for root@localhost; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +set names latin1; diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index ca375ef5057..246aaa3a93e 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -107,6 +107,17 @@ delete from mysql.columns_priv where user like 'mysqltest\_%'; flush privileges; drop database mysqltest; use test; +create user mysqltest_1@host1; +create user mysqltest_2@host2; +create user mysqltest_3@host3; +create user mysqltest_4@host4; +create user mysqltest_5@host5; +create user mysqltest_6@host6; +create user mysqltest_7@host7; +flush privileges; +drop user mysqltest_3@host3; +drop user mysqltest_1@host1, mysqltest_2@host2, mysqltest_4@host4, +mysqltest_5@host5, mysqltest_6@host6, mysqltest_7@host7; set sql_mode='maxdb'; drop table if exists t1, t2; create table t1(c1 int); @@ -191,7 +202,7 @@ flush privileges; show grants for 'mysqltest_1'; ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' revoke all privileges, grant option from 'mysqltest_1'; -ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users +ERROR HY000: Can't revoke all privileges for one or more of the requested users drop user 'mysqltest_1'; select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user; host db user diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 038d0c75f74..91579a7ea42 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2002,3 +2002,44 @@ a count(a) 1 1 NULL 1 drop table t1; +create table t1 (f1 int, f2 char(1), primary key(f1,f2)) engine=innodb; +insert into t1 values ( 1,"e"),(2,"a"),( 3,"c"),(4,"d"); +alter table t1 drop primary key, add primary key (f2, f1); +explain select distinct f1 a, f1 b from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 5 NULL 4 Using index; Using temporary +explain select distinct f1, f2 from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL PRIMARY 5 NULL 3 Using index for group-by; Using temporary +drop table t1; +create table t1 (c1 int not null,c2 int not null, primary key(c1,c2)); +insert into t1 (c1,c2) values +(10,1),(10,2),(10,3),(20,4),(20,5),(20,6),(30,7),(30,8),(30,9); +select distinct c1, c2 from t1 order by c2; +c1 c2 +10 1 +10 2 +10 3 +20 4 +20 5 +20 6 +30 7 +30 8 +30 9 +select c1,min(c2) as c2 from t1 group by c1 order by c2; +c1 c2 +10 1 +20 4 +30 7 +select c1,c2 from t1 group by c1,c2 order by c2; +c1 c2 +10 1 +10 2 +10 3 +20 4 +20 5 +20 6 +30 7 +30 8 +30 9 +drop table t1; diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result index 072d4582cbc..104025e83eb 100644 --- a/mysql-test/r/handler.result +++ b/mysql-test/r/handler.result @@ -1,4 +1,4 @@ -drop table if exists t1; +drop table if exists t1,t3,t4,t5; create table t1 (a int, b char(10), key a(a), key b(a,b)); insert into t1 values (17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"), @@ -445,3 +445,40 @@ drop table t2; drop table t3; drop table t4; drop table t5; +create table t1 (c1 int); +insert into t1 values (1); +handler t1 open; +handler t1 read first; +c1 +1 +send the below to another connection, do not wait for the result + optimize table t1; +proceed with the normal connection +handler t1 read next; +c1 +1 +handler t1 close; +read the result from the other connection +Table Op Msg_type Msg_text +test.t1 optimize status OK +proceed with the normal connection +drop table t1; +create table t1 (c1 int); +insert into t1 values (14397); +flush tables with read lock; +drop table t1; +ERROR HY000: Can't execute the query because you have a conflicting read lock +send the below to another connection, do not wait for the result + drop table t1; +proceed with the normal connection +select * from t1; +c1 +14397 +unlock tables; +read the result from the other connection +proceed with the normal connection +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +drop table if exists t1; +Warnings: +Note 1051 Unknown table 't1' diff --git a/mysql-test/r/have_openssl_1.require b/mysql-test/r/have_openssl_1.require deleted file mode 100644 index b33a1d2854f..00000000000 --- a/mysql-test/r/have_openssl_1.require +++ /dev/null @@ -1,2 +0,0 @@ -Variable_name Value -Ssl_cipher DHE-RSA-AES256-SHA diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 9c3d6d40139..05f2118a8c7 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -647,28 +647,42 @@ drop function sub1; select table_name from information_schema.views where table_schema='test'; table_name +v2 +v3 Warnings: -Warning 1356 View 'test.v2' references invalid table(s) or column(s) or function(s) -Warning 1356 View 'test.v3' references invalid table(s) or column(s) or function(s) +Warning 1356 View 'test.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +Warning 1356 View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them select table_name from information_schema.views where table_schema='test'; table_name +v2 +v3 Warnings: -Warning 1356 View 'test.v2' references invalid table(s) or column(s) or function(s) -Warning 1356 View 'test.v3' references invalid table(s) or column(s) or function(s) +Warning 1356 View 'test.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +Warning 1356 View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them select column_name from information_schema.columns where table_schema='test'; column_name f1 Warnings: -Warning 1356 View 'test.v2' references invalid table(s) or column(s) or function(s) -Warning 1356 View 'test.v3' references invalid table(s) or column(s) or function(s) +Warning 1356 View 'test.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +Warning 1356 View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them select index_name from information_schema.statistics where table_schema='test'; index_name f1_key select constraint_name from information_schema.table_constraints where table_schema='test'; constraint_name +show create view v2; +View Create View +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `test`.`t1`.`f1` AS `c` from `t1` +Warnings: +Warning 1356 View 'test.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +show create table v3; +View Create View +v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select sql_no_cache `test`.`sub1`(1) AS `c` +Warnings: +Warning 1356 View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them drop view v2; drop view v3; drop table t4; @@ -722,6 +736,7 @@ information_schema ROUTINES SQL_MODE information_schema TRIGGERS ACTION_CONDITION information_schema TRIGGERS ACTION_STATEMENT information_schema TRIGGERS SQL_MODE +information_schema TRIGGERS DEFINER information_schema VIEWS VIEW_DEFINITION select table_name, column_name, data_type from information_schema.columns where data_type = 'datetime'; @@ -800,45 +815,45 @@ set @fired:= "Yes"; end if; end| show triggers; -Trigger Event Table Statement Timing Created sql_mode +Trigger Event Table Statement Timing Created sql_mode Definer trg1 INSERT t1 begin if new.j > 10 then set new.j := 10; end if; -end BEFORE NULL +end BEFORE NULL root@localhost trg2 UPDATE t1 begin if old.i % 2 = 0 then set new.j := -1; end if; -end BEFORE NULL +end BEFORE NULL root@localhost trg3 UPDATE t1 begin if new.j = -1 then set @fired:= "Yes"; end if; -end AFTER NULL +end AFTER NULL root@localhost select * from information_schema.triggers; -TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE +TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE DEFINER NULL test trg1 INSERT NULL test t1 0 NULL begin if new.j > 10 then set new.j := 10; end if; -end ROW BEFORE NULL NULL OLD NEW NULL +end ROW BEFORE NULL NULL OLD NEW NULL root@localhost NULL test trg2 UPDATE NULL test t1 0 NULL begin if old.i % 2 = 0 then set new.j := -1; end if; -end ROW BEFORE NULL NULL OLD NEW NULL +end ROW BEFORE NULL NULL OLD NEW NULL root@localhost NULL test trg3 UPDATE NULL test t1 0 NULL begin if new.j = -1 then set @fired:= "Yes"; end if; -end ROW AFTER NULL NULL OLD NEW NULL +end ROW AFTER NULL NULL OLD NEW NULL root@localhost drop trigger trg1; drop trigger trg2; drop trigger trg3; @@ -1025,3 +1040,53 @@ select 1 from (select 1 from test.t1) a; 1 use test; drop table t1; +create table t1(a blob, b text charset utf8, c text charset ucs2); +select data_type, character_octet_length, character_maximum_length +from information_schema.columns where table_name='t1'; +data_type character_octet_length character_maximum_length +blob 65535 65535 +text 65535 65535 +text 65535 32767 +drop table t1; +create table t1 (f1 int(11)); +create view v1 as select * from t1; +drop table t1; +select table_type from information_schema.tables +where table_name="v1"; +table_type +VIEW +drop view v1; +create temporary table t1(f1 int, index(f1)); +show columns from t1; +Field Type Null Key Default Extra +f1 int(11) YES MUL NULL +describe t1; +Field Type Null Key Default Extra +f1 int(11) YES MUL NULL +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 f1 1 f1 A NULL NULL NULL YES BTREE +drop table t1; +create table t1(f1 binary(32), f2 varbinary(64)); +select character_maximum_length, character_octet_length +from information_schema.columns where table_name='t1'; +character_maximum_length character_octet_length +32 32 +64 64 +drop table t1; +CREATE TABLE t1 (f1 BIGINT, f2 VARCHAR(20), f3 BIGINT); +INSERT INTO t1 SET f1 = 1, f2 = 'Schoenenbourg', f3 = 1; +CREATE FUNCTION func2() RETURNS BIGINT RETURN 1; +CREATE FUNCTION func1() RETURNS BIGINT +BEGIN +RETURN ( SELECT COUNT(*) FROM INFORMATION_SCHEMA.VIEWS); +END// +CREATE VIEW v1 AS SELECT 1 FROM t1 +WHERE f3 = (SELECT func2 ()); +SELECT func1(); +func1() +1 +DROP TABLE t1; +DROP VIEW v1; +DROP FUNCTION func1; +DROP FUNCTION func2; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index dc4893c3bfa..dcff72ba7c0 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -2437,7 +2437,9 @@ a b 20 NULL drop table t1; create table t1 (v varchar(65530), key(v)); -ERROR HY000: Can't create table './test/t1' (errno: 139) +Warnings: +Warning 1071 Specified key was too long; max key length is 767 bytes +drop table t1; create table t1 (v varchar(65536)); Warnings: Note 1246 Converting column 'v' from VARCHAR to TEXT @@ -2577,22 +2579,49 @@ create table t8 (col1 blob, index(col1(767))) character set = latin1 engine = innodb; create table t9 (col1 varchar(512), col2 varchar(512), index(col1, col2)) character set = latin1 engine = innodb; +show create table t9; +Table Create Table +t9 CREATE TABLE `t9` ( + `col1` varchar(512) default NULL, + `col2` varchar(512) default NULL, + KEY `col1` (`col1`,`col2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 drop table t1, t2, t3, t4, t5, t6, t7, t8, t9; -create table t1 (col1 varchar(768), index (col1)) +create table t1 (col1 varchar(768), index(col1)) character set = latin1 engine = innodb; -ERROR HY000: Can't create table './test/t1.frm' (errno: 139) -create table t2 (col1 varchar(768) primary key) +Warnings: +Warning 1071 Specified key was too long; max key length is 767 bytes +create table t2 (col1 varbinary(768), index(col1)) character set = latin1 engine = innodb; -ERROR HY000: Can't create table './test/t2.frm' (errno: 139) -create table t3 (col1 varbinary(768) primary key) +Warnings: +Warning 1071 Specified key was too long; max key length is 767 bytes +create table t3 (col1 text, index(col1(768))) character set = latin1 engine = innodb; -ERROR HY000: Can't create table './test/t3.frm' (errno: 139) -create table t4 (col1 text, index(col1(768))) +Warnings: +Warning 1071 Specified key was too long; max key length is 767 bytes +create table t4 (col1 blob, index(col1(768))) character set = latin1 engine = innodb; -ERROR HY000: Can't create table './test/t4.frm' (errno: 139) -create table t5 (col1 blob, index(col1(768))) +Warnings: +Warning 1071 Specified key was too long; max key length is 767 bytes +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `col1` varchar(768) default NULL, + KEY `col1` (`col1`(767)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +drop table t1, t2, t3, t4; +create table t1 (col1 varchar(768) primary key) +character set = latin1 engine = innodb; +ERROR 42000: Specified key was too long; max key length is 767 bytes +create table t2 (col1 varbinary(768) primary key) +character set = latin1 engine = innodb; +ERROR 42000: Specified key was too long; max key length is 767 bytes +create table t3 (col1 text, primary key(col1(768))) character set = latin1 engine = innodb; -ERROR HY000: Can't create table './test/t5.frm' (errno: 139) +ERROR 42000: Specified key was too long; max key length is 767 bytes +create table t4 (col1 blob, primary key(col1(768))) +character set = latin1 engine = innodb; +ERROR 42000: Specified key was too long; max key length is 767 bytes CREATE TABLE t1 ( id INT PRIMARY KEY @@ -2772,3 +2801,78 @@ insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); drop table t1; drop table t2; commit; +set foreign_key_checks=0; +create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +ERROR HY000: Can't create table './test/t1.frm' (errno: 150) +set foreign_key_checks=1; +drop table t2; +set foreign_key_checks=0; +create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8; +ERROR HY000: Can't create table './test/t2.frm' (errno: 150) +set foreign_key_checks=1; +drop table t1; +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb; +create table t1(a varchar(10) primary key) engine = innodb; +alter table t1 modify column a int; +Got one of the listed errors +set foreign_key_checks=1; +drop table t2,t1; +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; +create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +alter table t1 convert to character set utf8; +set foreign_key_checks=1; +drop table t2,t1; +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; +create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; +rename table t3 to t1; +ERROR HY000: Error on rename of './test/t3' to './test/t1' (errno: 150) +set foreign_key_checks=1; +drop table t2,t3; +create table t1 (a varchar(255) character set utf8, +b varchar(255) character set utf8, +c varchar(255) character set utf8, +d varchar(255) character set utf8, +key (a,b,c,d)) engine=innodb; +drop table t1; +create table t1 (a varchar(255) character set utf8, +b varchar(255) character set utf8, +c varchar(255) character set utf8, +d varchar(255) character set utf8, +e varchar(255) character set utf8, +key (a,b,c,d,e)) engine=innodb; +ERROR 42000: Specified key was too long; max key length is 3072 bytes +create table t1(a int primary key) row_format=redundant engine=innodb; +create table t2(a int primary key,constraint foreign key(a)references t1(a)) row_format=compact engine=innodb; +create table t3(a int primary key) row_format=compact engine=innodb; +create table t4(a int primary key,constraint foreign key(a)references t3(a)) row_format=redundant engine=innodb; +insert into t1 values(1); +insert into t3 values(1); +insert into t2 values(2); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +insert into t4 values(2); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +insert into t2 values(1); +insert into t4 values(1); +update t1 set a=2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +update t2 set a=2; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +update t3 set a=2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +update t4 set a=2; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +truncate t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +truncate t3; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +truncate t2; +truncate t4; +truncate t1; +truncate t3; +drop table t4,t3,t2,t1; +End of 5.0 tests diff --git a/mysql-test/r/innodb_gis.result b/mysql-test/r/innodb_gis.result new file mode 100644 index 00000000000..826a17cb60d --- /dev/null +++ b/mysql-test/r/innodb_gis.result @@ -0,0 +1,458 @@ +SET storage_engine=innodb; +DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE gis_point (fid INTEGER, g POINT); +CREATE TABLE gis_line (fid INTEGER, g LINESTRING); +CREATE TABLE gis_polygon (fid INTEGER, g POLYGON); +CREATE TABLE gis_multi_point (fid INTEGER, g MULTIPOINT); +CREATE TABLE gis_multi_line (fid INTEGER, g MULTILINESTRING); +CREATE TABLE gis_multi_polygon (fid INTEGER, g MULTIPOLYGON); +CREATE TABLE gis_geometrycollection (fid INTEGER, g GEOMETRYCOLLECTION); +CREATE TABLE gis_geometry (fid INTEGER, g GEOMETRY); +SHOW CREATE TABLE gis_point; +Table Create Table +gis_point CREATE TABLE `gis_point` ( + `fid` int(11) default NULL, + `g` point default NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW FIELDS FROM gis_point; +Field Type Null Key Default Extra +fid int(11) YES NULL +g point YES NULL +SHOW FIELDS FROM gis_line; +Field Type Null Key Default Extra +fid int(11) YES NULL +g linestring YES NULL +SHOW FIELDS FROM gis_polygon; +Field Type Null Key Default Extra +fid int(11) YES NULL +g polygon YES NULL +SHOW FIELDS FROM gis_multi_point; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multipoint YES NULL +SHOW FIELDS FROM gis_multi_line; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multilinestring YES NULL +SHOW FIELDS FROM gis_multi_polygon; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multipolygon YES NULL +SHOW FIELDS FROM gis_geometrycollection; +Field Type Null Key Default Extra +fid int(11) YES NULL +g geometrycollection YES NULL +SHOW FIELDS FROM gis_geometry; +Field Type Null Key Default Extra +fid int(11) YES NULL +g geometry YES NULL +INSERT INTO gis_point VALUES +(101, PointFromText('POINT(10 10)')), +(102, PointFromText('POINT(20 10)')), +(103, PointFromText('POINT(20 20)')), +(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)')))); +INSERT INTO gis_line VALUES +(105, LineFromText('LINESTRING(0 0,0 10,10 0)')), +(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')), +(107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10)))); +INSERT INTO gis_polygon VALUES +(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')), +(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')), +(110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))))); +INSERT INTO gis_multi_point VALUES +(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')), +(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')), +(113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10)))); +INSERT INTO gis_multi_line VALUES +(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')), +(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')), +(116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7))))); +INSERT INTO gis_multi_polygon VALUES +(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))))); +INSERT INTO gis_geometrycollection VALUES +(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')), +(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))); +INSERT into gis_geometry SELECT * FROM gis_point; +INSERT into gis_geometry SELECT * FROM gis_line; +INSERT into gis_geometry SELECT * FROM gis_polygon; +INSERT into gis_geometry SELECT * FROM gis_multi_point; +INSERT into gis_geometry SELECT * FROM gis_multi_line; +INSERT into gis_geometry SELECT * FROM gis_multi_polygon; +INSERT into gis_geometry SELECT * FROM gis_geometrycollection; +SELECT fid, AsText(g) FROM gis_point ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +SELECT fid, AsText(g) FROM gis_line ORDER by fid; +fid AsText(g) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +SELECT fid, AsText(g) FROM gis_polygon ORDER by fid; +fid AsText(g) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +SELECT fid, AsText(g) FROM gis_multi_point ORDER by fid; +fid AsText(g) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +SELECT fid, AsText(g) FROM gis_multi_line ORDER by fid; +fid AsText(g) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +SELECT fid, AsText(g) FROM gis_multi_polygon ORDER by fid; +fid AsText(g) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +SELECT fid, AsText(g) FROM gis_geometrycollection ORDER by fid; +fid AsText(g) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, AsText(g) FROM gis_geometry ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, Dimension(g) FROM gis_geometry ORDER by fid; +fid Dimension(g) +101 0 +102 0 +103 0 +104 0 +105 1 +106 1 +107 1 +108 2 +109 2 +110 2 +111 0 +112 0 +113 0 +114 1 +115 1 +116 1 +117 2 +118 2 +119 2 +120 1 +121 1 +SELECT fid, GeometryType(g) FROM gis_geometry ORDER by fid; +fid GeometryType(g) +101 POINT +102 POINT +103 POINT +104 POINT +105 LINESTRING +106 LINESTRING +107 LINESTRING +108 POLYGON +109 POLYGON +110 POLYGON +111 MULTIPOINT +112 MULTIPOINT +113 MULTIPOINT +114 MULTILINESTRING +115 MULTILINESTRING +116 MULTILINESTRING +117 MULTIPOLYGON +118 MULTIPOLYGON +119 MULTIPOLYGON +120 GEOMETRYCOLLECTION +121 GEOMETRYCOLLECTION +SELECT fid, IsEmpty(g) FROM gis_geometry ORDER by fid; +fid IsEmpty(g) +101 0 +102 0 +103 0 +104 0 +105 0 +106 0 +107 0 +108 0 +109 0 +110 0 +111 0 +112 0 +113 0 +114 0 +115 0 +116 0 +117 0 +118 0 +119 0 +120 0 +121 0 +SELECT fid, AsText(Envelope(g)) FROM gis_geometry ORDER by fid; +fid AsText(Envelope(g)) +101 POLYGON((10 10,10 10,10 10,10 10,10 10)) +102 POLYGON((20 10,20 10,20 10,20 10,20 10)) +103 POLYGON((20 20,20 20,20 20,20 20,20 20)) +104 POLYGON((10 20,10 20,10 20,10 20,10 20)) +105 POLYGON((0 0,10 0,10 10,0 10,0 0)) +106 POLYGON((10 10,20 10,20 20,10 20,10 10)) +107 POLYGON((10 10,40 10,40 10,10 10,10 10)) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0)) +110 POLYGON((0 0,30 0,30 30,0 30,0 0)) +111 POLYGON((0 0,20 0,20 20,0 20,0 0)) +112 POLYGON((1 1,21 1,21 21,1 21,1 1)) +113 POLYGON((3 6,4 6,4 10,3 10,3 6)) +114 POLYGON((10 0,16 0,16 48,10 48,10 0)) +115 POLYGON((10 0,10 0,10 48,10 48,10 0)) +116 POLYGON((1 2,21 2,21 8,1 8,1 2)) +117 POLYGON((28 0,84 0,84 42,28 42,28 0)) +118 POLYGON((28 0,84 0,84 42,28 42,28 0)) +119 POLYGON((0 0,3 0,3 3,0 3,0 0)) +120 POLYGON((0 0,10 0,10 10,0 10,0 0)) +121 POLYGON((3 6,44 6,44 9,3 9,3 6)) +explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21 +Warnings: +Note 1003 select dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,astext(envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry` +SELECT fid, X(g) FROM gis_point ORDER by fid; +fid X(g) +101 10 +102 20 +103 20 +104 10 +SELECT fid, Y(g) FROM gis_point ORDER by fid; +fid Y(g) +101 10 +102 10 +103 20 +104 20 +explain extended select X(g),Y(g) FROM gis_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_point ALL NULL NULL NULL NULL 4 +Warnings: +Note 1003 select x(`test`.`gis_point`.`g`) AS `X(g)`,y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point` +SELECT fid, AsText(StartPoint(g)) FROM gis_line ORDER by fid; +fid AsText(StartPoint(g)) +105 POINT(0 0) +106 POINT(10 10) +107 POINT(10 10) +SELECT fid, AsText(EndPoint(g)) FROM gis_line ORDER by fid; +fid AsText(EndPoint(g)) +105 POINT(10 0) +106 POINT(10 10) +107 POINT(40 10) +SELECT fid, GLength(g) FROM gis_line ORDER by fid; +fid GLength(g) +105 24.142135623731 +106 40 +107 30 +SELECT fid, NumPoints(g) FROM gis_line ORDER by fid; +fid NumPoints(g) +105 3 +106 5 +107 2 +SELECT fid, AsText(PointN(g, 2)) FROM gis_line ORDER by fid; +fid AsText(PointN(g, 2)) +105 POINT(0 10) +106 POINT(20 10) +107 POINT(40 10) +SELECT fid, IsClosed(g) FROM gis_line ORDER by fid; +fid IsClosed(g) +105 0 +106 1 +107 0 +explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_line ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,astext(endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,glength(`test`.`gis_line`.`g`) AS `GLength(g)`,numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,astext(pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line` +SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; +fid AsText(Centroid(g)) +108 POINT(15 15) +109 POINT(25.416666666667 25.416666666667) +110 POINT(20 10) +SELECT fid, Area(g) FROM gis_polygon ORDER by fid; +fid Area(g) +108 100 +109 2400 +110 450 +SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon ORDER by fid; +fid AsText(ExteriorRing(g)) +108 LINESTRING(10 10,20 10,20 20,10 20,10 10) +109 LINESTRING(0 0,50 0,50 50,0 50,0 0) +110 LINESTRING(0 0,30 0,30 30,0 0) +SELECT fid, NumInteriorRings(g) FROM gis_polygon ORDER by fid; +fid NumInteriorRings(g) +108 0 +109 1 +110 0 +SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon ORDER by fid; +fid AsText(InteriorRingN(g, 1)) +108 NULL +109 LINESTRING(10 10,20 10,20 20,10 20,10 10) +110 NULL +explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM gis_polygon; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select astext(centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,area(`test`.`gis_polygon`.`g`) AS `Area(g)`,astext(exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,astext(interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon` +SELECT fid, IsClosed(g) FROM gis_multi_line ORDER by fid; +fid IsClosed(g) +114 0 +115 0 +116 0 +SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; +fid AsText(Centroid(g)) +117 POINT(55.588527753042 17.426536064114) +118 POINT(55.588527753042 17.426536064114) +119 POINT(2 2) +SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; +fid Area(g) +117 1684.5 +118 1684.5 +119 4.5 +SELECT fid, NumGeometries(g) from gis_multi_point ORDER by fid; +fid NumGeometries(g) +111 4 +112 4 +113 2 +SELECT fid, NumGeometries(g) from gis_multi_line ORDER by fid; +fid NumGeometries(g) +114 2 +115 1 +116 2 +SELECT fid, NumGeometries(g) from gis_multi_polygon ORDER by fid; +fid NumGeometries(g) +117 2 +118 2 +119 1 +SELECT fid, NumGeometries(g) from gis_geometrycollection ORDER by fid; +fid NumGeometries(g) +120 2 +121 2 +explain extended SELECT fid, NumGeometries(g) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point` +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point ORDER by fid; +fid AsText(GeometryN(g, 2)) +111 POINT(10 10) +112 POINT(11 11) +113 POINT(4 10) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line ORDER by fid; +fid AsText(GeometryN(g, 2)) +114 LINESTRING(16 0,16 23,16 48) +115 NULL +116 LINESTRING(2 5,5 8,21 7) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon ORDER by fid; +fid AsText(GeometryN(g, 2)) +117 POLYGON((59 18,67 18,67 13,59 13,59 18)) +118 POLYGON((59 18,67 18,67 13,59 13,59 18)) +119 NULL +SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 2)) +120 LINESTRING(0 0,10 10) +121 LINESTRING(3 6,7 9) +SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 1)) +120 POINT(0 0) +121 POINT(44 6) +explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,astext(geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point` +SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +first second w c o e d t i r +120 120 1 1 0 1 0 0 1 0 +120 121 0 0 0 0 0 0 1 0 +121 120 0 0 1 0 0 0 1 0 +121 121 1 1 0 1 0 0 1 0 +explain extended SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE g1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +1 SIMPLE g2 ALL NULL NULL NULL NULL 2 +Warnings: +Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,overlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,disjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,intersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid` +DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE t1 ( +gp point, +ln linestring, +pg polygon, +mp multipoint, +mln multilinestring, +mpg multipolygon, +gc geometrycollection, +gm geometry +); +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +ALTER TABLE t1 ADD fid INT; +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +fid int(11) YES NULL +DROP TABLE t1; +create table t1 (a geometry not null); +insert into t1 values (GeomFromText('Point(1 2)')); +insert into t1 values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert IGNORE into t1 values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; +create table t1 (fl geometry); +insert into t1 values (1); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values (1.11); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values ("qwerty"); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values (pointfromtext('point(1,1)')); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 17f65d96abc..434dddb3049 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -668,3 +668,21 @@ ERROR 42S22: Unknown column 't2.a' in 'field list' insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b; ERROR 42S22: Unknown column 't2.b' in 'field list' drop table t1,t2,t3; +create table t1(f1 varchar(5) key); +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +select * from t1; +f1 +2000 +2001 +2002 +drop table t1; +create table t1(x int, y int); +create table t2(x int, z int); +insert into t1(x,y) select x,z from t2 on duplicate key update x=values(x); +insert into t1(x,y) select x,z from t2 on duplicate key update x=values(z); +ERROR 42S22: Unknown column 'z' in 'field list' +insert into t1(x,y) select x,z from t2 on duplicate key update x=values(t2.x); +ERROR 42S22: Unknown column 't2.x' in 'field list' +drop table t1,t2; diff --git a/mysql-test/r/is_debug_build.require b/mysql-test/r/is_debug_build.require new file mode 100644 index 00000000000..4d77bcdc1ed --- /dev/null +++ b/mysql-test/r/is_debug_build.require @@ -0,0 +1,2 @@ +instr(version(), "debug") > 0 +1 diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index c887dc9d6a7..724d1b1e39f 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -391,3 +391,304 @@ i i i 2 NULL 4 2 2 2 drop table t1,t2,t3; +create table t1 (c int, b int); +create table t2 (a int, b int); +create table t3 (b int, c int); +create table t4 (y int, c int); +create table t5 (y int, z int); +create table t6 (a int, c int); +insert into t1 values (10,1); +insert into t1 values (3 ,1); +insert into t1 values (3 ,2); +insert into t2 values (2, 1); +insert into t3 values (1, 3); +insert into t3 values (1,10); +insert into t4 values (11,3); +insert into t4 values (2, 3); +insert into t5 values (11,4); +insert into t6 values (2, 3); +create algorithm=merge view v1a as +select * from t1 natural join t2; +create algorithm=merge view v1b(a,b,c) as +select * from t1 natural join t2; +create algorithm=merge view v1c as +select b as a, c as b, a as c from t1 natural join t2; +create algorithm=merge view v1d(b, a, c) as +select a as c, c as b, b as a from t1 natural join t2; +create algorithm=merge view v2a as +select t1.c, t1.b, t2.a from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; +create algorithm=merge view v2b as +select t1.c as b, t1.b as a, t2.a as c +from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; +create algorithm=merge view v3a as +select * from t1 natural join t2 natural join t3; +create algorithm=merge view v3b as +select * from t1 natural join (t2 natural join t3); +create algorithm=merge view v4 as +select * from v2a natural join v3a; +select * from (t1 natural join t2) natural join (t3 natural join t4); +b c a y +1 3 2 11 +1 3 2 2 +select * from (t1 natural join t2) natural left join (t3 natural join t4); +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +select * from (t3 natural join t4) natural right join (t1 natural join t2); +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +select * from (t1 natural left join t2) natural left join (t3 natural left join t4); +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +2 3 NULL NULL +select * from (t4 natural right join t3) natural right join (t2 natural right join t1); +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +2 3 NULL NULL +select * from t1 natural join t2 natural join t3 natural join t4; +c b a y +3 1 2 11 +3 1 2 2 +select * from ((t1 natural join t2) natural join t3) natural join t4; +c b a y +3 1 2 11 +3 1 2 2 +select * from t1 natural join (t2 natural join (t3 natural join t4)); +c b a y +3 1 2 11 +3 1 2 2 +select * from t5 natural right join (t4 natural right join ((t2 natural right join t1) natural right join t3)); +y c b a z +11 3 1 2 4 +2 3 1 2 NULL +NULL 10 1 2 NULL +select * from (t1 natural join t2), (t3 natural join t4); +b c a c b y +1 10 2 3 1 11 +1 10 2 3 1 2 +1 3 2 3 1 11 +1 3 2 3 1 2 +select * from (t1 join t2 using (b)) join (t3 join t4 using (c)) using (c); +c b a b y +3 1 2 1 11 +3 1 2 1 2 +select * from (t1 join t2 using (b)) natural join (t3 join t4 using (c)); +b c a y +1 3 2 11 +1 3 2 2 +select a,b,c from (t1 natural join t2) natural join (t3 natural join t4) +where b + 1 = y or b + 10 = y group by b,c,a having min(b) < max(y) order by a; +a b c +2 1 3 +select * from (t1 natural join t2) natural left join (t3 natural join t4) +where b + 1 = y or b + 10 = y group by b,c,a,y having min(b) < max(y) order by a, y; +b c a y +1 3 2 2 +1 3 2 11 +select * from (t3 natural join t4) natural right join (t1 natural join t2) +where b + 1 = y or b + 10 = y group by b,c,a,y having min(b) < max(y) order by a, y; +b c a y +1 3 2 2 +1 3 2 11 +select * from t1 natural join t2 where t1.c > t2.a; +b c a +1 10 2 +1 3 2 +select * from t1 natural join t2 where t1.b > t2.b; +b c a +select * from t1 natural left join (t4 natural join t5) where t5.z is not NULL; +c b y z +3 1 11 4 +3 2 11 4 +select * from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; +c b a b y c +3 1 2 1 2 3 +3 2 2 1 2 3 +select * from (t2 join t4 on b + 1 = y) join t1 on t1.c = t4.c; +a b y c c b +2 1 2 3 3 1 +2 1 2 3 3 2 +select * from t1 natural join (t2 join t4 on b + 1 = y); +c b a y +3 1 2 2 +select * from (t1 cross join t2) join (t3 cross join t4) on (a < y and t2.b < t3.c); +c b a b b c y c +10 1 2 1 1 3 11 3 +10 1 2 1 1 10 11 3 +3 1 2 1 1 3 11 3 +3 1 2 1 1 10 11 3 +3 2 2 1 1 3 11 3 +3 2 2 1 1 10 11 3 +select * from (t1, t2) join (t3, t4) on (a < y and t2.b < t3.c); +c b a b b c y c +10 1 2 1 1 3 11 3 +10 1 2 1 1 10 11 3 +3 1 2 1 1 3 11 3 +3 1 2 1 1 10 11 3 +3 2 2 1 1 3 11 3 +3 2 2 1 1 10 11 3 +select * from (t1 natural join t2) join (t3 natural join t4) on a = y; +b c a c b y +1 10 2 3 1 2 +1 3 2 3 1 2 +select * from ((t3 join (t1 join t2 on c > a) on t3.b < t2.a) join t4 on y > t1.c) join t5 on z = t1.b + 3; +b c c b a b y c y z +1 3 10 1 2 1 11 3 11 4 +1 10 10 1 2 1 11 3 11 4 +1 3 3 1 2 1 11 3 11 4 +1 10 3 1 2 1 11 3 11 4 +select * from t1 natural join t2 where t1.b > 0; +b c a +1 10 2 +1 3 2 +select * from t1 natural join (t4 natural join t5) where t4.y > 7; +c b y z +3 1 11 4 +3 2 11 4 +select * from (t4 natural join t5) natural join t1 where t4.y > 7; +c y z b +3 11 4 1 +3 11 4 2 +select * from t1 natural left join (t4 natural join t5) where t4.y > 7; +c b y z +3 1 11 4 +3 2 11 4 +select * from (t4 natural join t5) natural right join t1 where t4.y > 7; +c b y z +3 1 11 4 +3 2 11 4 +select * from (t1 natural join t2) join (t3 natural join t4) on t1.b = t3.b; +b c a c b y +1 10 2 3 1 11 +1 10 2 3 1 2 +1 3 2 3 1 11 +1 3 2 3 1 2 +select t1.*, t2.* from t1 natural join t2; +c b a b +10 1 2 1 +3 1 2 1 +select t1.*, t2.*, t3.*, t4.* from (t1 natural join t2) natural join (t3 natural join t4); +c b a b b c y c +3 1 2 1 1 3 11 3 +3 1 2 1 1 3 2 3 +select * from (select * from t1 natural join t2) as t12 +natural join +(select * from t3 natural join t4) as t34; +b c a y +1 3 2 11 +1 3 2 2 +select * from (select * from t1 natural join t2) as t12 +natural left join +(select * from t3 natural join t4) as t34; +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +select * from (select * from t3 natural join t4) as t34 +natural right join +(select * from t1 natural join t2) as t12; +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +select * from v1a; +b c a +1 10 2 +1 3 2 +select * from v1b; +a b c +1 10 2 +1 3 2 +select * from v1c; +a b c +1 10 2 +1 3 2 +select * from v1d; +b a c +2 10 1 +2 3 1 +select * from v2a; +c b a +3 1 2 +3 2 2 +select * from v2b; +b a c +3 1 2 +3 2 2 +select * from v3a; +b c a +1 10 2 +1 3 2 +select * from v3b; +c b a +10 1 2 +3 1 2 +select * from v4; +c b a +3 1 2 +select * from v1a natural join v2a; +b c a +1 3 2 +select v2a.* from v1a natural join v2a; +c b a +3 1 2 +select * from v1b join v2a on v1b.b = v2a.c; +a b c c b a +1 3 2 3 1 2 +1 3 2 3 2 2 +select * from v1c join v2a on v1c.b = v2a.c; +a b c c b a +1 3 2 3 1 2 +1 3 2 3 2 2 +select * from v1d join v2a on v1d.a = v2a.c; +b a c c b a +2 3 1 3 1 2 +2 3 1 3 2 2 +select * from v1a join (t3 natural join t4) on a = y; +b c a c b y +1 10 2 3 1 2 +1 3 2 3 1 2 +select * from t1 natural join (t3 cross join t4); +ERROR 23000: Column 'c' in from clause is ambiguous +select * from (t3 cross join t4) natural join t1; +ERROR 23000: Column 'c' in from clause is ambiguous +select * from t1 join (t2, t3) using (b); +ERROR 23000: Column 'b' in from clause is ambiguous +select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; +ERROR 23000: Column 'c' in from clause is ambiguous +select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; +ERROR 23000: Column 'c' in from clause is ambiguous +select * from (t1 join t2 on t1.b=t2.b) natural join (t3 natural join t4); +ERROR 23000: Column 'b' in from clause is ambiguous +select * from (t3 natural join t4) natural join (t1 join t2 on t1.b=t2.b); +ERROR 23000: Column 'b' in from clause is ambiguous +select * from (t3 join (t4 natural join t5) on (b < z)) +natural join +(t1 natural join t2); +ERROR 23000: Column 'c' in from clause is ambiguous +select t1.b from v1a; +ERROR 42S22: Unknown column 't1.b' in 'field list' +select * from v1a join v1b on t1.b = t2.b; +ERROR 42S22: Unknown column 't1.b' in 'on clause' +drop table t1; +drop table t2; +drop table t3; +drop table t4; +drop table t5; +drop table t6; +drop view v1a; +drop view v1b; +drop view v1c; +drop view v1d; +drop view v2a; +drop view v2b; +drop view v3a; +drop view v3b; +drop view v4; diff --git a/mysql-test/r/join_nested.result b/mysql-test/r/join_nested.result index 9d514be76e8..6b7293d46bc 100644 --- a/mysql-test/r/join_nested.result +++ b/mysql-test/r/join_nested.result @@ -1403,3 +1403,67 @@ SELECT v2.x FROM v2 JOIN t2 ON e=b JOIN t3 ON e=c JOIN t4 USING(d); ERROR 42S22: Unknown column 'v2.x' in 'field list' DROP VIEW v1, v2; DROP TABLE t1, t2, t3, t4, t5, t6; +create table t1 (id1 int(11) not null); +insert into t1 values (1),(2); +create table t2 (id2 int(11) not null); +insert into t2 values (1),(2),(3),(4); +create table t3 (id3 char(16) not null); +insert into t3 values ('100'); +create table t4 (id2 int(11) not null, id3 char(16)); +create table t5 (id1 int(11) not null, key (id1)); +insert into t5 values (1),(2),(1); +create view v1 as +select t4.id3 from t4 join t2 on t4.id2 = t2.id2; +select t1.id1 from t1 inner join (t3 left join v1 on t3.id3 = v1.id3); +id1 +1 +2 +drop view v1; +drop table t1, t2, t3, t4, t5; +create table t0 (a int); +insert into t0 values (0),(1),(2),(3); +create table t1(a int); +insert into t1 select A.a + 10*(B.a) from t0 A, t0 B; +create table t2 (a int, b int); +insert into t2 values (1,1), (2,2), (3,3); +create table t3(a int, b int, filler char(200), key(a)); +insert into t3 select a,a,'filler' from t1; +insert into t3 select a,a,'filler' from t1; +create table t4 like t3; +insert into t4 select * from t3; +insert into t4 select * from t3; +create table t5 like t4; +insert into t5 select * from t4; +insert into t5 select * from t4; +create table t6 like t5; +insert into t6 select * from t5; +insert into t6 select * from t5; +create table t7 like t6; +insert into t7 select * from t6; +insert into t7 select * from t6; +explain select * from t4 join +t2 left join (t3 join t5 on t5.a=t3.b) on t3.a=t2.b where t4.a<=>t3.b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL X +1 SIMPLE t3 ref a a 5 test.t2.b X +1 SIMPLE t5 ref a a 5 test.t3.b X +1 SIMPLE t4 ref a a 5 test.t3.b X Using where +explain select * from (t4 join t6 on t6.a=t4.b) right join t3 on t4.a=t3.b +join t2 left join (t5 join t7 on t7.a=t5.b) on t5.a=t2.b where t3.a<=>t2.b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL X +1 SIMPLE t3 ref a a 5 test.t2.b X Using where +1 SIMPLE t4 ref a a 5 test.t3.b X +1 SIMPLE t6 ref a a 5 test.t4.b X +1 SIMPLE t5 ref a a 5 test.t2.b X +1 SIMPLE t7 ref a a 5 test.t5.b X +explain select * from t2 left join +(t3 left join (t4 join t6 on t6.a=t4.b) on t4.a=t3.b +join t5 on t5.a=t3.b) on t3.a=t2.b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL X +1 SIMPLE t3 ref a a 5 test.t2.b X +1 SIMPLE t4 ref a a 5 test.t3.b X +1 SIMPLE t6 ref a a 5 test.t4.b X +1 SIMPLE t5 ref a a 5 test.t3.b X +drop table t0, t1, t2, t3, t4, t5, t6, t7; diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index 754568093ff..2413834be4f 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -5,8 +5,6 @@ select ((@id := kill_id) - kill_id) from t1; ((@id := kill_id) - kill_id) 0 kill @id; -select 1; -Got one of the listed errors select ((@id := kill_id) - kill_id) from t1; ((@id := kill_id) - kill_id) 0 diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index f9d47e3533c..4e47ce6f82c 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -77,6 +77,14 @@ id 0 SET @@SQL_MODE=@OLD_SQL_MODE; drop table t1; +create table t1 (a varchar(20), b varchar(20)); +load data infile '../../std_data/loaddata_dq.dat' into table t1 fields terminated by ',' enclosed by '"' escaped by '"' (a,b); +select * from t1; +a b +field1 field2 +a"b cd"ef +a"b c"d"e +drop table t1; create table t1 (a int default 100, b int, c varchar(60)); load data infile '../../std_data/rpl_loaddata.dat' into table t1 (a, @b) set b=@b+10, c=concat("b=",@b); select * from t1; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index e028e58acf5..7e3ccc83d73 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -719,3 +719,52 @@ SELECT b FROM t2; b 3 DROP TABLE t1, t2; +create table t1(a int); +create table t2(a int); +insert into t1 values (1); +insert into t2 values (2); +create table t3 (a int) engine=merge union=(t1, t2) insert_method=first; +select * from t3; +a +1 +2 +insert t2 select * from t2; +select * from t2; +a +2 +2 +insert t3 select * from t1; +select * from t3; +a +1 +1 +2 +2 +insert t1 select * from t3; +select * from t1; +a +1 +1 +1 +1 +2 +2 +select * from t2; +a +2 +2 +select * from t3; +a +1 +1 +1 +1 +2 +2 +2 +2 +check table t1, t2; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t2 check status OK +drop table t1, t2, t3; diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result index e4528450b31..c84bd65e748 100644 --- a/mysql-test/r/mix_innodb_myisam_binlog.result +++ b/mysql-test/r/mix_innodb_myisam_binlog.result @@ -205,3 +205,54 @@ select (@after-@before) >= 2; (@after-@before) >= 2 1 drop table t1,t2; +commit; +begin; +create temporary table ti (a int) engine=innodb; +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +insert into ti values(1); +set autocommit=0; +create temporary table t1 (a int) engine=myisam; +commit; +insert t1 values (1); +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +create table t0 (n int); +insert t0 select * from t1; +set autocommit=1; +insert into t0 select GET_LOCK("lock1",null); +set autocommit=0; +create table t2 (n int) engine=innodb; +insert into t2 values (3); +select get_lock("lock1",60); +get_lock("lock1",60) +1 +show binlog events from 98; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 98 Query 1 # use `test`; BEGIN +master-bin.000001 166 Query 1 # use `test`; insert into t1 values(16) +master-bin.000001 254 Query 1 # use `test`; insert into t1 values(18) +master-bin.000001 342 Xid 1 # COMMIT /* xid=105 */ +master-bin.000001 369 Query 1 # use `test`; delete from t1 +master-bin.000001 446 Xid 1 # COMMIT /* xid=114 */ +master-bin.000001 473 Query 1 # use `test`; delete from t2 +master-bin.000001 550 Xid 1 # COMMIT /* xid=115 */ +master-bin.000001 577 Query 1 # use `test`; alter table t2 type=MyISAM +master-bin.000001 666 Query 1 # use `test`; insert into t1 values (1) +master-bin.000001 754 Xid 1 # COMMIT /* xid=117 */ +master-bin.000001 781 Query 1 # use `test`; insert into t2 values (20) +master-bin.000001 870 Query 1 # use `test`; drop table t1,t2 +master-bin.000001 949 Query 1 # use `test`; create temporary table ti (a int) engine=innodb +master-bin.000001 1059 Query 1 # use `test`; insert into ti values(1) +master-bin.000001 1146 Xid 1 # COMMIT /* xid=132 */ +master-bin.000001 1173 Query 1 # use `test`; create temporary table t1 (a int) engine=myisam +master-bin.000001 1283 Query 1 # use `test`; insert t1 values (1) +master-bin.000001 1366 Query 1 # use `test`; create table t0 (n int) +master-bin.000001 1452 Query 1 # use `test`; insert t0 select * from t1 +master-bin.000001 1541 Query 1 # use `test`; insert into t0 select GET_LOCK("lock1",null) +master-bin.000001 1648 Query 1 # use `test`; create table t2 (n int) engine=innodb +master-bin.000001 1748 Query 1 # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti` +do release_lock("lock1"); +drop table t0,t2; diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index f484a937b27..e000cfd9c11 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -505,6 +505,16 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 Using temporary 1 SIMPLE t2 index NULL PRIMARY 4 NULL 2 Using index; Distinct drop table t1,t2; +create table t1 ( +c1 varchar(32), +key (c1) +) engine=myisam; +alter table t1 disable keys; +insert into t1 values ('a'), ('b'); +select c1 from t1 order by c1 limit 1; +c1 +a +drop table t1; CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) ENGINE=MyISAM; Got one of the listed errors create table t1 (a int, b varchar(200), c text not null) checksum=1; @@ -669,6 +679,56 @@ show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 1 a 1 a A 10 NULL NULL YES BTREE drop table t1; +set myisam_stats_method=nulls_ignored; +show variables like 'myisam_stats_method'; +Variable_name Value +myisam_stats_method nulls_ignored +create table t1 ( +a char(3), b char(4), c char(5), d char(6), +key(a,b,c,d) +); +insert into t1 values ('bcd','def1', NULL, 'zz'); +insert into t1 values ('bcd','def2', NULL, 'zz'); +insert into t1 values ('bce','def1', 'yuu', NULL); +insert into t1 values ('bce','def2', NULL, 'quux'); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +show index from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A 2 NULL NULL YES BTREE +t1 1 a 2 b A 4 NULL NULL YES BTREE +t1 1 a 3 c A 4 NULL NULL YES BTREE +t1 1 a 4 d A 4 NULL NULL YES BTREE +delete from t1; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +show index from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A 0 NULL NULL YES BTREE +t1 1 a 2 b A 0 NULL NULL YES BTREE +t1 1 a 3 c A 0 NULL NULL YES BTREE +t1 1 a 4 d A 0 NULL NULL YES BTREE +set myisam_stats_method=DEFAULT; +drop table t1; +create table t1( +cip INT NOT NULL, +time TIME NOT NULL, +score INT NOT NULL DEFAULT 0, +bob TINYBLOB +); +insert into t1 (cip, time) VALUES (1, '00:01'), (2, '00:02'), (3,'00:03'); +insert into t1 (cip, bob, time) VALUES (4, 'a', '00:04'), (5, 'b', '00:05'), +(6, 'c', '00:06'); +select * from t1 where bob is null and cip=1; +cip time score bob +1 00:01:00 0 NULL +create index bug on t1 (bob(22), cip, time); +select * from t1 where bob is null and cip=1; +cip time score bob +1 00:01:00 0 NULL +drop table t1; set storage_engine=MyISAM; drop table if exists t1,t2,t3; --- Testing varchar --- diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 99efde39614..62d2b46e617 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1458,6 +1458,7 @@ UNLOCK TABLES; /*!40000 ALTER TABLE `t2` ENABLE KEYS */; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; +/*!50001 DROP TABLE IF EXISTS `v2`*/; /*!50001 CREATE TABLE `v2` ( `a` varchar(30) ) */; @@ -1613,6 +1614,16 @@ mysqldump: Couldn't find table: "t\1" mysqldump: Couldn't find table: "t/1" +mysqldump: Couldn't find table: "T_1" + +mysqldump: Couldn't find table: "T%1" + +mysqldump: Couldn't find table: "T'1" + +mysqldump: Couldn't find table: "T_1" + +mysqldump: Couldn't find table: "T_" + test_sequence ------ Testing with illegal database names ------ mysqldump: Got error: 1049: Unknown database 'mysqldump_test_d' when selecting the database @@ -1676,6 +1687,16 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir </database> </mysqldump> drop table t1, t2; +create table t1 (a text character set utf8, b text character set latin1); +insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); +select * from t1; +a b +Osnabrück Köln +test.t1: Records: 1 Deleted: 0 Skipped: 0 Warnings: 0 +select * from t1; +a b +Osnabrück Köln +drop table t1; create table t1(a int); create view v1 as select * from t1; @@ -1701,6 +1722,7 @@ UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; +/*!50001 DROP TABLE IF EXISTS `v1`*/; /*!50001 CREATE TABLE `v1` ( `a` int(11) ) */; @@ -1756,6 +1778,7 @@ UNLOCK TABLES; /*!40000 ALTER TABLE `t2` ENABLE KEYS */; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; +/*!50001 DROP TABLE IF EXISTS `v2`*/; /*!50001 CREATE TABLE `v2` ( `a` varchar(30) ) */; @@ -1845,6 +1868,7 @@ UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; +/*!50001 DROP TABLE IF EXISTS `v1`*/; /*!50001 CREATE TABLE `v1` ( `a` int(11), `b` int(11), @@ -1852,11 +1876,13 @@ DROP TABLE IF EXISTS `v1`; ) */; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; +/*!50001 DROP TABLE IF EXISTS `v2`*/; /*!50001 CREATE TABLE `v2` ( `a` int(11) ) */; DROP TABLE IF EXISTS `v3`; /*!50001 DROP VIEW IF EXISTS `v3`*/; +/*!50001 DROP TABLE IF EXISTS `v3`*/; /*!50001 CREATE TABLE `v3` ( `a` int(11), `b` int(11), @@ -1910,23 +1936,23 @@ end if; end| set sql_mode=default| show triggers like "t1"; -Trigger Event Table Statement Timing Created sql_mode +Trigger Event Table Statement Timing Created sql_mode Definer trg1 INSERT t1 begin if new.a > 10 then set new.a := 10; set new.a := 11; end if; -end BEFORE 0000-00-00 00:00:00 +end BEFORE 0000-00-00 00:00:00 root@localhost trg2 UPDATE t1 begin if old.a % 2 = 0 then set new.b := 12; end if; -end BEFORE 0000-00-00 00:00:00 +end BEFORE 0000-00-00 00:00:00 root@localhost trg3 UPDATE t1 begin if new.a = -1 then set @fired:= "Yes"; end if; -end AFTER 0000-00-00 00:00:00 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER +end AFTER 0000-00-00 00:00:00 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost INSERT INTO t1 (a) VALUES (1),(2),(3),(22); update t1 set a = 4 where a=3; @@ -2069,29 +2095,29 @@ Tables_in_test t1 t2 show triggers; -Trigger Event Table Statement Timing Created sql_mode +Trigger Event Table Statement Timing Created sql_mode Definer trg1 INSERT t1 begin if new.a > 10 then set new.a := 10; set new.a := 11; end if; -end BEFORE # +end BEFORE # root@localhost trg2 UPDATE t1 begin if old.a % 2 = 0 then set new.b := 12; end if; -end BEFORE # +end BEFORE # root@localhost trg3 UPDATE t1 begin if new.a = -1 then set @fired:= "Yes"; end if; -end AFTER # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER +end AFTER # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost trg4 INSERT t2 begin if new.a > 10 then set @fired:= "No"; end if; -end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER +end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost DROP TABLE t1, t2; --port=1234 --port=1234 @@ -2114,9 +2140,9 @@ SELECT * FROM `test2`; a2 1 SHOW TRIGGERS; -Trigger Event Table Statement Timing Created sql_mode +Trigger Event Table Statement Timing Created sql_mode Definer testref INSERT test1 BEGIN -INSERT INTO test2 SET a2 = NEW.a1; END BEFORE NULL +INSERT INTO test2 SET a2 = NEW.a1; END BEFORE NULL root@localhost SELECT * FROM `test1`; a1 1 @@ -2131,6 +2157,7 @@ DROP FUNCTION IF EXISTS bug9056_func1; DROP FUNCTION IF EXISTS bug9056_func2; DROP PROCEDURE IF EXISTS bug9056_proc1; DROP PROCEDURE IF EXISTS bug9056_proc2; +DROP PROCEDURE IF EXISTS `a'b`; CREATE TABLE t1 (id int); INSERT INTO t1 VALUES(1), (2), (3), (4), (5); CREATE FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11) RETURN a+b // @@ -2220,6 +2247,7 @@ DROP FUNCTION bug9056_func1; DROP FUNCTION bug9056_func2; DROP PROCEDURE bug9056_proc1; DROP PROCEDURE bug9056_proc2; +DROP PROCEDURE `a'b`; drop table t1; drop table if exists t1; create table t1 (`d` timestamp, unique (`d`)); @@ -2417,6 +2445,7 @@ UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `v0`; /*!50001 DROP VIEW IF EXISTS `v0`*/; +/*!50001 DROP TABLE IF EXISTS `v0`*/; /*!50001 CREATE TABLE `v0` ( `a` int(11), `b` varchar(32), @@ -2424,6 +2453,7 @@ DROP TABLE IF EXISTS `v0`; ) */; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; +/*!50001 DROP TABLE IF EXISTS `v1`*/; /*!50001 CREATE TABLE `v1` ( `a` int(11), `b` varchar(32), @@ -2431,6 +2461,7 @@ DROP TABLE IF EXISTS `v1`; ) */; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; +/*!50001 DROP TABLE IF EXISTS `v2`*/; /*!50001 CREATE TABLE `v2` ( `a` int(11), `b` varchar(32), @@ -2463,3 +2494,128 @@ drop view v2; drop view v0; drop view v1; drop table t1; +SET @old_sql_mode = @@SQL_MODE; +SET SQL_MODE = IGNORE_SPACE; +CREATE TABLE t1 (a INT); +CREATE TRIGGER tr1 BEFORE INSERT ON t1 +FOR EACH ROW +BEGIN +SET new.a = 0; +END| +SET SQL_MODE = @old_sql_mode; + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET latin1 */; + +USE `test`; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; + +/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/; +DELIMITER ;; +/*!50003 SET SESSION SQL_MODE="IGNORE_SPACE" */;; +/*!50003 CREATE TRIGGER `tr1` BEFORE INSERT ON `t1` FOR EACH ROW BEGIN +SET new.a = 0; +END */;; + +DELIMITER ; +/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TRIGGER tr1; +DROP TABLE t1; +create table t1 (a binary(1), b blob); +insert into t1 values ('',''); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` binary(1) default NULL, + `b` blob +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES (0x00,''); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` binary(1) default NULL, + `b` blob +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES (0x00,''); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +drop table t1; diff --git a/mysql-test/r/mysqlshow.result b/mysql-test/r/mysqlshow.result index 355c20fdad3..942cde83f21 100644 --- a/mysql-test/r/mysqlshow.result +++ b/mysql-test/r/mysqlshow.result @@ -1,4 +1,4 @@ -DROP TABLE IF EXISTS t1,t2; +DROP TABLE IF EXISTS t1,t2,test1,test2; CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); CREATE TABLE t2 (a int, b int); diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 0ad6db8c57e..5ff931dafb5 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -344,6 +344,18 @@ mysqltest: At line 1: Wrong column number to replace_column in 'replace_column 1 mysqltest: At line 1: Invalid integer argument "10!" mysqltest: At line 1: End of line junk detected: "!" mysqltest: At line 1: Invalid integer argument "a" +mysqltest: At line 1: Syntax error in connect - expected '(' found 'mysqltest: At line 1: Missing connection host +mysqltest: At line 1: Missing connection host +mysqltest: At line 1: Missing connection user +mysqltest: At line 1: Missing connection user +mysqltest: At line 1: Missing connection password +mysqltest: At line 1: Missing connection db +mysqltest: At line 1: Could not open connection 'con2': Unknown database 'illegal_db' +mysqltest: At line 1: Illegal argument for port: 'illegal_port' +mysqltest: At line 1: Illegal option to connect: SMTP +mysqltest: In included file "./var/tmp/con.sql": At line 7: Connection limit exhausted - increase MAX_CONS in mysqltest.c +mysqltest: In included file "./var/tmp/con.sql": At line 3: connection 'test_con1' not found in connection pool +mysqltest: In included file "./var/tmp/con.sql": At line 2: Connection test_con1 already exists Output from mysqltest-x.inc Output from mysqltest-x.inc Output from mysqltest-x.inc @@ -379,3 +391,25 @@ root@localhost -------------------------------------------------------------------------------- this will be executed this will be executed +mysqltest: At line 3: query 'create table t1 (a int primary key); +insert into t1 values (1); +select 'select-me'; +insertz 'error query'' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insertz 'error query'' at line 1 +drop table t1; +drop table t1; +create table t1 (a int primary key); +insert into t1 values (1); +select 'select-me'; +insertz error query|||| +select-me +select-me +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 'insertz error query' at line 1 +drop table t1; +create table t1 (a int primary key); +insert into t1 values (1); +select 'select-me'; +insertz error query|||| +select-me +select-me +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 'insertz error query' at line 1 +drop table t1; diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result index 69aa233b5e4..acb67250c26 100644 --- a/mysql-test/r/ndb_alter_table.result +++ b/mysql-test/r/ndb_alter_table.result @@ -179,8 +179,7 @@ a b c 2 two two alter table t1 drop index c; select * from t1 where b = 'two'; -a b c -2 two two +ERROR HY000: Can't lock file (errno: 241) select * from t1 where b = 'two'; a b c 2 two two diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result index a374f845933..9dd75f1390c 100644 --- a/mysql-test/r/ndb_basic.result +++ b/mysql-test/r/ndb_basic.result @@ -667,9 +667,29 @@ counter datavalue 57 newval 58 newval drop table t1; +CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb; +select * from t1; +b +drop table t1; create table atablewithareallylongandirritatingname (a int); insert into atablewithareallylongandirritatingname values (2); select * from atablewithareallylongandirritatingname; a 2 drop table atablewithareallylongandirritatingname; +create table t1 (f1 varchar(50), f2 text,f3 int, primary key(f1)) engine=NDB; +insert into t1 (f1,f2,f3)VALUES("111111","aaaaaa",1); +insert into t1 (f1,f2,f3)VALUES("222222","bbbbbb",2); +select * from t1 order by f1; +f1 f2 f3 +111111 aaaaaa 1 +222222 bbbbbb 2 +select * from t1 order by f2; +f1 f2 f3 +111111 aaaaaa 1 +222222 bbbbbb 2 +select * from t1 order by f3; +f1 f2 f3 +111111 aaaaaa 1 +222222 bbbbbb 2 +drop table t1; diff --git a/mysql-test/r/ndb_charset.result b/mysql-test/r/ndb_charset.result index 500b0497890..3763e20e59a 100644 --- a/mysql-test/r/ndb_charset.result +++ b/mysql-test/r/ndb_charset.result @@ -306,11 +306,21 @@ count(*) drop table t1; create table t1 ( a char(10) primary key -) engine=ndb; -insert into t1 values ('jonas % '); -replace into t1 values ('jonas % '); -replace into t1 values ('jonas % '); +) engine=ndbcluster default charset=latin1; +insert into t1 values ('aaabb'); +select * from t1; +a +aaabb +replace into t1 set a = 'AAABB'; +select * from t1; +a +AAABB +replace into t1 set a = 'aAaBb'; +select * from t1; +a +aAaBb +replace into t1 set a = 'aaabb'; select * from t1; a -jonas % +aaabb drop table t1; diff --git a/mysql-test/r/ndb_gis.result b/mysql-test/r/ndb_gis.result new file mode 100644 index 00000000000..43075306bd2 --- /dev/null +++ b/mysql-test/r/ndb_gis.result @@ -0,0 +1,916 @@ +SET storage_engine=ndbcluster; +DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE gis_point (fid INTEGER, g POINT); +CREATE TABLE gis_line (fid INTEGER, g LINESTRING); +CREATE TABLE gis_polygon (fid INTEGER, g POLYGON); +CREATE TABLE gis_multi_point (fid INTEGER, g MULTIPOINT); +CREATE TABLE gis_multi_line (fid INTEGER, g MULTILINESTRING); +CREATE TABLE gis_multi_polygon (fid INTEGER, g MULTIPOLYGON); +CREATE TABLE gis_geometrycollection (fid INTEGER, g GEOMETRYCOLLECTION); +CREATE TABLE gis_geometry (fid INTEGER, g GEOMETRY); +SHOW CREATE TABLE gis_point; +Table Create Table +gis_point CREATE TABLE `gis_point` ( + `fid` int(11) default NULL, + `g` point default NULL +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +SHOW FIELDS FROM gis_point; +Field Type Null Key Default Extra +fid int(11) YES NULL +g point YES NULL +SHOW FIELDS FROM gis_line; +Field Type Null Key Default Extra +fid int(11) YES NULL +g linestring YES NULL +SHOW FIELDS FROM gis_polygon; +Field Type Null Key Default Extra +fid int(11) YES NULL +g polygon YES NULL +SHOW FIELDS FROM gis_multi_point; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multipoint YES NULL +SHOW FIELDS FROM gis_multi_line; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multilinestring YES NULL +SHOW FIELDS FROM gis_multi_polygon; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multipolygon YES NULL +SHOW FIELDS FROM gis_geometrycollection; +Field Type Null Key Default Extra +fid int(11) YES NULL +g geometrycollection YES NULL +SHOW FIELDS FROM gis_geometry; +Field Type Null Key Default Extra +fid int(11) YES NULL +g geometry YES NULL +INSERT INTO gis_point VALUES +(101, PointFromText('POINT(10 10)')), +(102, PointFromText('POINT(20 10)')), +(103, PointFromText('POINT(20 20)')), +(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)')))); +INSERT INTO gis_line VALUES +(105, LineFromText('LINESTRING(0 0,0 10,10 0)')), +(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')), +(107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10)))); +INSERT INTO gis_polygon VALUES +(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')), +(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')), +(110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))))); +INSERT INTO gis_multi_point VALUES +(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')), +(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')), +(113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10)))); +INSERT INTO gis_multi_line VALUES +(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')), +(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')), +(116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7))))); +INSERT INTO gis_multi_polygon VALUES +(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))))); +INSERT INTO gis_geometrycollection VALUES +(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')), +(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))); +INSERT into gis_geometry SELECT * FROM gis_point; +INSERT into gis_geometry SELECT * FROM gis_line; +INSERT into gis_geometry SELECT * FROM gis_polygon; +INSERT into gis_geometry SELECT * FROM gis_multi_point; +INSERT into gis_geometry SELECT * FROM gis_multi_line; +INSERT into gis_geometry SELECT * FROM gis_multi_polygon; +INSERT into gis_geometry SELECT * FROM gis_geometrycollection; +SELECT fid, AsText(g) FROM gis_point ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +SELECT fid, AsText(g) FROM gis_line ORDER by fid; +fid AsText(g) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +SELECT fid, AsText(g) FROM gis_polygon ORDER by fid; +fid AsText(g) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +SELECT fid, AsText(g) FROM gis_multi_point ORDER by fid; +fid AsText(g) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +SELECT fid, AsText(g) FROM gis_multi_line ORDER by fid; +fid AsText(g) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +SELECT fid, AsText(g) FROM gis_multi_polygon ORDER by fid; +fid AsText(g) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +SELECT fid, AsText(g) FROM gis_geometrycollection ORDER by fid; +fid AsText(g) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, AsText(g) FROM gis_geometry ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, Dimension(g) FROM gis_geometry ORDER by fid; +fid Dimension(g) +101 0 +102 0 +103 0 +104 0 +105 1 +106 1 +107 1 +108 2 +109 2 +110 2 +111 0 +112 0 +113 0 +114 1 +115 1 +116 1 +117 2 +118 2 +119 2 +120 1 +121 1 +SELECT fid, GeometryType(g) FROM gis_geometry ORDER by fid; +fid GeometryType(g) +101 POINT +102 POINT +103 POINT +104 POINT +105 LINESTRING +106 LINESTRING +107 LINESTRING +108 POLYGON +109 POLYGON +110 POLYGON +111 MULTIPOINT +112 MULTIPOINT +113 MULTIPOINT +114 MULTILINESTRING +115 MULTILINESTRING +116 MULTILINESTRING +117 MULTIPOLYGON +118 MULTIPOLYGON +119 MULTIPOLYGON +120 GEOMETRYCOLLECTION +121 GEOMETRYCOLLECTION +SELECT fid, IsEmpty(g) FROM gis_geometry ORDER by fid; +fid IsEmpty(g) +101 0 +102 0 +103 0 +104 0 +105 0 +106 0 +107 0 +108 0 +109 0 +110 0 +111 0 +112 0 +113 0 +114 0 +115 0 +116 0 +117 0 +118 0 +119 0 +120 0 +121 0 +SELECT fid, AsText(Envelope(g)) FROM gis_geometry ORDER by fid; +fid AsText(Envelope(g)) +101 POLYGON((10 10,10 10,10 10,10 10,10 10)) +102 POLYGON((20 10,20 10,20 10,20 10,20 10)) +103 POLYGON((20 20,20 20,20 20,20 20,20 20)) +104 POLYGON((10 20,10 20,10 20,10 20,10 20)) +105 POLYGON((0 0,10 0,10 10,0 10,0 0)) +106 POLYGON((10 10,20 10,20 20,10 20,10 10)) +107 POLYGON((10 10,40 10,40 10,10 10,10 10)) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0)) +110 POLYGON((0 0,30 0,30 30,0 30,0 0)) +111 POLYGON((0 0,20 0,20 20,0 20,0 0)) +112 POLYGON((1 1,21 1,21 21,1 21,1 1)) +113 POLYGON((3 6,4 6,4 10,3 10,3 6)) +114 POLYGON((10 0,16 0,16 48,10 48,10 0)) +115 POLYGON((10 0,10 0,10 48,10 48,10 0)) +116 POLYGON((1 2,21 2,21 8,1 8,1 2)) +117 POLYGON((28 0,84 0,84 42,28 42,28 0)) +118 POLYGON((28 0,84 0,84 42,28 42,28 0)) +119 POLYGON((0 0,3 0,3 3,0 3,0 0)) +120 POLYGON((0 0,10 0,10 10,0 10,0 0)) +121 POLYGON((3 6,44 6,44 9,3 9,3 6)) +explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21 +Warnings: +Note 1003 select dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,astext(envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry` +SELECT fid, X(g) FROM gis_point ORDER by fid; +fid X(g) +101 10 +102 20 +103 20 +104 10 +SELECT fid, Y(g) FROM gis_point ORDER by fid; +fid Y(g) +101 10 +102 10 +103 20 +104 20 +explain extended select X(g),Y(g) FROM gis_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_point ALL NULL NULL NULL NULL 4 +Warnings: +Note 1003 select x(`test`.`gis_point`.`g`) AS `X(g)`,y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point` +SELECT fid, AsText(StartPoint(g)) FROM gis_line ORDER by fid; +fid AsText(StartPoint(g)) +105 POINT(0 0) +106 POINT(10 10) +107 POINT(10 10) +SELECT fid, AsText(EndPoint(g)) FROM gis_line ORDER by fid; +fid AsText(EndPoint(g)) +105 POINT(10 0) +106 POINT(10 10) +107 POINT(40 10) +SELECT fid, GLength(g) FROM gis_line ORDER by fid; +fid GLength(g) +105 24.142135623731 +106 40 +107 30 +SELECT fid, NumPoints(g) FROM gis_line ORDER by fid; +fid NumPoints(g) +105 3 +106 5 +107 2 +SELECT fid, AsText(PointN(g, 2)) FROM gis_line ORDER by fid; +fid AsText(PointN(g, 2)) +105 POINT(0 10) +106 POINT(20 10) +107 POINT(40 10) +SELECT fid, IsClosed(g) FROM gis_line ORDER by fid; +fid IsClosed(g) +105 0 +106 1 +107 0 +explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_line ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,astext(endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,glength(`test`.`gis_line`.`g`) AS `GLength(g)`,numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,astext(pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line` +SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; +fid AsText(Centroid(g)) +108 POINT(15 15) +109 POINT(25.416666666667 25.416666666667) +110 POINT(20 10) +SELECT fid, Area(g) FROM gis_polygon ORDER by fid; +fid Area(g) +108 100 +109 2400 +110 450 +SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon ORDER by fid; +fid AsText(ExteriorRing(g)) +108 LINESTRING(10 10,20 10,20 20,10 20,10 10) +109 LINESTRING(0 0,50 0,50 50,0 50,0 0) +110 LINESTRING(0 0,30 0,30 30,0 0) +SELECT fid, NumInteriorRings(g) FROM gis_polygon ORDER by fid; +fid NumInteriorRings(g) +108 0 +109 1 +110 0 +SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon ORDER by fid; +fid AsText(InteriorRingN(g, 1)) +108 NULL +109 LINESTRING(10 10,20 10,20 20,10 20,10 10) +110 NULL +explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM gis_polygon; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select astext(centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,area(`test`.`gis_polygon`.`g`) AS `Area(g)`,astext(exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,astext(interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon` +SELECT fid, IsClosed(g) FROM gis_multi_line ORDER by fid; +fid IsClosed(g) +114 0 +115 0 +116 0 +SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; +fid AsText(Centroid(g)) +117 POINT(55.588527753042 17.426536064114) +118 POINT(55.588527753042 17.426536064114) +119 POINT(2 2) +SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; +fid Area(g) +117 1684.5 +118 1684.5 +119 4.5 +SELECT fid, NumGeometries(g) from gis_multi_point ORDER by fid; +fid NumGeometries(g) +111 4 +112 4 +113 2 +SELECT fid, NumGeometries(g) from gis_multi_line ORDER by fid; +fid NumGeometries(g) +114 2 +115 1 +116 2 +SELECT fid, NumGeometries(g) from gis_multi_polygon ORDER by fid; +fid NumGeometries(g) +117 2 +118 2 +119 1 +SELECT fid, NumGeometries(g) from gis_geometrycollection ORDER by fid; +fid NumGeometries(g) +120 2 +121 2 +explain extended SELECT fid, NumGeometries(g) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point` +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point ORDER by fid; +fid AsText(GeometryN(g, 2)) +111 POINT(10 10) +112 POINT(11 11) +113 POINT(4 10) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line ORDER by fid; +fid AsText(GeometryN(g, 2)) +114 LINESTRING(16 0,16 23,16 48) +115 NULL +116 LINESTRING(2 5,5 8,21 7) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon ORDER by fid; +fid AsText(GeometryN(g, 2)) +117 POLYGON((59 18,67 18,67 13,59 13,59 18)) +118 POLYGON((59 18,67 18,67 13,59 13,59 18)) +119 NULL +SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 2)) +120 LINESTRING(0 0,10 10) +121 LINESTRING(3 6,7 9) +SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 1)) +120 POINT(0 0) +121 POINT(44 6) +explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,astext(geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point` +SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +first second w c o e d t i r +120 120 1 1 0 1 0 0 1 0 +120 121 0 0 0 0 0 0 1 0 +121 120 0 0 1 0 0 0 1 0 +121 121 1 1 0 1 0 0 1 0 +explain extended SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE g1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +1 SIMPLE g2 ALL NULL NULL NULL NULL 2 +Warnings: +Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,overlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,disjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,intersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid` +DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE t1 ( +gp point, +ln linestring, +pg polygon, +mp multipoint, +mln multilinestring, +mpg multipolygon, +gc geometrycollection, +gm geometry +); +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +ALTER TABLE t1 ADD fid INT; +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +fid int(11) YES NULL +DROP TABLE t1; +create table t1 (a geometry not null); +insert into t1 values (GeomFromText('Point(1 2)')); +insert into t1 values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert IGNORE into t1 values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; +create table t1 (fl geometry); +insert into t1 values (1); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values (1.11); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values ("qwerty"); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values (pointfromtext('point(1,1)')); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; +set engine_condition_pushdown = on; +DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE gis_point (fid INTEGER, g POINT); +CREATE TABLE gis_line (fid INTEGER, g LINESTRING); +CREATE TABLE gis_polygon (fid INTEGER, g POLYGON); +CREATE TABLE gis_multi_point (fid INTEGER, g MULTIPOINT); +CREATE TABLE gis_multi_line (fid INTEGER, g MULTILINESTRING); +CREATE TABLE gis_multi_polygon (fid INTEGER, g MULTIPOLYGON); +CREATE TABLE gis_geometrycollection (fid INTEGER, g GEOMETRYCOLLECTION); +CREATE TABLE gis_geometry (fid INTEGER, g GEOMETRY); +SHOW CREATE TABLE gis_point; +Table Create Table +gis_point CREATE TABLE `gis_point` ( + `fid` int(11) default NULL, + `g` point default NULL +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +SHOW FIELDS FROM gis_point; +Field Type Null Key Default Extra +fid int(11) YES NULL +g point YES NULL +SHOW FIELDS FROM gis_line; +Field Type Null Key Default Extra +fid int(11) YES NULL +g linestring YES NULL +SHOW FIELDS FROM gis_polygon; +Field Type Null Key Default Extra +fid int(11) YES NULL +g polygon YES NULL +SHOW FIELDS FROM gis_multi_point; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multipoint YES NULL +SHOW FIELDS FROM gis_multi_line; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multilinestring YES NULL +SHOW FIELDS FROM gis_multi_polygon; +Field Type Null Key Default Extra +fid int(11) YES NULL +g multipolygon YES NULL +SHOW FIELDS FROM gis_geometrycollection; +Field Type Null Key Default Extra +fid int(11) YES NULL +g geometrycollection YES NULL +SHOW FIELDS FROM gis_geometry; +Field Type Null Key Default Extra +fid int(11) YES NULL +g geometry YES NULL +INSERT INTO gis_point VALUES +(101, PointFromText('POINT(10 10)')), +(102, PointFromText('POINT(20 10)')), +(103, PointFromText('POINT(20 20)')), +(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)')))); +INSERT INTO gis_line VALUES +(105, LineFromText('LINESTRING(0 0,0 10,10 0)')), +(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')), +(107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10)))); +INSERT INTO gis_polygon VALUES +(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')), +(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')), +(110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))))); +INSERT INTO gis_multi_point VALUES +(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')), +(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')), +(113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10)))); +INSERT INTO gis_multi_line VALUES +(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')), +(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')), +(116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7))))); +INSERT INTO gis_multi_polygon VALUES +(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))))); +INSERT INTO gis_geometrycollection VALUES +(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')), +(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))); +INSERT into gis_geometry SELECT * FROM gis_point; +INSERT into gis_geometry SELECT * FROM gis_line; +INSERT into gis_geometry SELECT * FROM gis_polygon; +INSERT into gis_geometry SELECT * FROM gis_multi_point; +INSERT into gis_geometry SELECT * FROM gis_multi_line; +INSERT into gis_geometry SELECT * FROM gis_multi_polygon; +INSERT into gis_geometry SELECT * FROM gis_geometrycollection; +SELECT fid, AsText(g) FROM gis_point ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +SELECT fid, AsText(g) FROM gis_line ORDER by fid; +fid AsText(g) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +SELECT fid, AsText(g) FROM gis_polygon ORDER by fid; +fid AsText(g) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +SELECT fid, AsText(g) FROM gis_multi_point ORDER by fid; +fid AsText(g) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +SELECT fid, AsText(g) FROM gis_multi_line ORDER by fid; +fid AsText(g) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +SELECT fid, AsText(g) FROM gis_multi_polygon ORDER by fid; +fid AsText(g) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +SELECT fid, AsText(g) FROM gis_geometrycollection ORDER by fid; +fid AsText(g) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, AsText(g) FROM gis_geometry ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, Dimension(g) FROM gis_geometry ORDER by fid; +fid Dimension(g) +101 0 +102 0 +103 0 +104 0 +105 1 +106 1 +107 1 +108 2 +109 2 +110 2 +111 0 +112 0 +113 0 +114 1 +115 1 +116 1 +117 2 +118 2 +119 2 +120 1 +121 1 +SELECT fid, GeometryType(g) FROM gis_geometry ORDER by fid; +fid GeometryType(g) +101 POINT +102 POINT +103 POINT +104 POINT +105 LINESTRING +106 LINESTRING +107 LINESTRING +108 POLYGON +109 POLYGON +110 POLYGON +111 MULTIPOINT +112 MULTIPOINT +113 MULTIPOINT +114 MULTILINESTRING +115 MULTILINESTRING +116 MULTILINESTRING +117 MULTIPOLYGON +118 MULTIPOLYGON +119 MULTIPOLYGON +120 GEOMETRYCOLLECTION +121 GEOMETRYCOLLECTION +SELECT fid, IsEmpty(g) FROM gis_geometry ORDER by fid; +fid IsEmpty(g) +101 0 +102 0 +103 0 +104 0 +105 0 +106 0 +107 0 +108 0 +109 0 +110 0 +111 0 +112 0 +113 0 +114 0 +115 0 +116 0 +117 0 +118 0 +119 0 +120 0 +121 0 +SELECT fid, AsText(Envelope(g)) FROM gis_geometry ORDER by fid; +fid AsText(Envelope(g)) +101 POLYGON((10 10,10 10,10 10,10 10,10 10)) +102 POLYGON((20 10,20 10,20 10,20 10,20 10)) +103 POLYGON((20 20,20 20,20 20,20 20,20 20)) +104 POLYGON((10 20,10 20,10 20,10 20,10 20)) +105 POLYGON((0 0,10 0,10 10,0 10,0 0)) +106 POLYGON((10 10,20 10,20 20,10 20,10 10)) +107 POLYGON((10 10,40 10,40 10,10 10,10 10)) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0)) +110 POLYGON((0 0,30 0,30 30,0 30,0 0)) +111 POLYGON((0 0,20 0,20 20,0 20,0 0)) +112 POLYGON((1 1,21 1,21 21,1 21,1 1)) +113 POLYGON((3 6,4 6,4 10,3 10,3 6)) +114 POLYGON((10 0,16 0,16 48,10 48,10 0)) +115 POLYGON((10 0,10 0,10 48,10 48,10 0)) +116 POLYGON((1 2,21 2,21 8,1 8,1 2)) +117 POLYGON((28 0,84 0,84 42,28 42,28 0)) +118 POLYGON((28 0,84 0,84 42,28 42,28 0)) +119 POLYGON((0 0,3 0,3 3,0 3,0 0)) +120 POLYGON((0 0,10 0,10 10,0 10,0 0)) +121 POLYGON((3 6,44 6,44 9,3 9,3 6)) +explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21 +Warnings: +Note 1003 select dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,astext(envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry` +SELECT fid, X(g) FROM gis_point ORDER by fid; +fid X(g) +101 10 +102 20 +103 20 +104 10 +SELECT fid, Y(g) FROM gis_point ORDER by fid; +fid Y(g) +101 10 +102 10 +103 20 +104 20 +explain extended select X(g),Y(g) FROM gis_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_point ALL NULL NULL NULL NULL 4 +Warnings: +Note 1003 select x(`test`.`gis_point`.`g`) AS `X(g)`,y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point` +SELECT fid, AsText(StartPoint(g)) FROM gis_line ORDER by fid; +fid AsText(StartPoint(g)) +105 POINT(0 0) +106 POINT(10 10) +107 POINT(10 10) +SELECT fid, AsText(EndPoint(g)) FROM gis_line ORDER by fid; +fid AsText(EndPoint(g)) +105 POINT(10 0) +106 POINT(10 10) +107 POINT(40 10) +SELECT fid, GLength(g) FROM gis_line ORDER by fid; +fid GLength(g) +105 24.142135623731 +106 40 +107 30 +SELECT fid, NumPoints(g) FROM gis_line ORDER by fid; +fid NumPoints(g) +105 3 +106 5 +107 2 +SELECT fid, AsText(PointN(g, 2)) FROM gis_line ORDER by fid; +fid AsText(PointN(g, 2)) +105 POINT(0 10) +106 POINT(20 10) +107 POINT(40 10) +SELECT fid, IsClosed(g) FROM gis_line ORDER by fid; +fid IsClosed(g) +105 0 +106 1 +107 0 +explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_line ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,astext(endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,glength(`test`.`gis_line`.`g`) AS `GLength(g)`,numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,astext(pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line` +SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; +fid AsText(Centroid(g)) +108 POINT(15 15) +109 POINT(25.416666666667 25.416666666667) +110 POINT(20 10) +SELECT fid, Area(g) FROM gis_polygon ORDER by fid; +fid Area(g) +108 100 +109 2400 +110 450 +SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon ORDER by fid; +fid AsText(ExteriorRing(g)) +108 LINESTRING(10 10,20 10,20 20,10 20,10 10) +109 LINESTRING(0 0,50 0,50 50,0 50,0 0) +110 LINESTRING(0 0,30 0,30 30,0 0) +SELECT fid, NumInteriorRings(g) FROM gis_polygon ORDER by fid; +fid NumInteriorRings(g) +108 0 +109 1 +110 0 +SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon ORDER by fid; +fid AsText(InteriorRingN(g, 1)) +108 NULL +109 LINESTRING(10 10,20 10,20 20,10 20,10 10) +110 NULL +explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM gis_polygon; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select astext(centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,area(`test`.`gis_polygon`.`g`) AS `Area(g)`,astext(exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,astext(interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon` +SELECT fid, IsClosed(g) FROM gis_multi_line ORDER by fid; +fid IsClosed(g) +114 0 +115 0 +116 0 +SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; +fid AsText(Centroid(g)) +117 POINT(55.588527753042 17.426536064114) +118 POINT(55.588527753042 17.426536064114) +119 POINT(2 2) +SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; +fid Area(g) +117 1684.5 +118 1684.5 +119 4.5 +SELECT fid, NumGeometries(g) from gis_multi_point ORDER by fid; +fid NumGeometries(g) +111 4 +112 4 +113 2 +SELECT fid, NumGeometries(g) from gis_multi_line ORDER by fid; +fid NumGeometries(g) +114 2 +115 1 +116 2 +SELECT fid, NumGeometries(g) from gis_multi_polygon ORDER by fid; +fid NumGeometries(g) +117 2 +118 2 +119 1 +SELECT fid, NumGeometries(g) from gis_geometrycollection ORDER by fid; +fid NumGeometries(g) +120 2 +121 2 +explain extended SELECT fid, NumGeometries(g) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point` +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point ORDER by fid; +fid AsText(GeometryN(g, 2)) +111 POINT(10 10) +112 POINT(11 11) +113 POINT(4 10) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line ORDER by fid; +fid AsText(GeometryN(g, 2)) +114 LINESTRING(16 0,16 23,16 48) +115 NULL +116 LINESTRING(2 5,5 8,21 7) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon ORDER by fid; +fid AsText(GeometryN(g, 2)) +117 POLYGON((59 18,67 18,67 13,59 13,59 18)) +118 POLYGON((59 18,67 18,67 13,59 13,59 18)) +119 NULL +SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 2)) +120 LINESTRING(0 0,10 10) +121 LINESTRING(3 6,7 9) +SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 1)) +120 POINT(0 0) +121 POINT(44 6) +explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,astext(geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point` +SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +first second w c o e d t i r +120 120 1 1 0 1 0 0 1 0 +120 121 0 0 0 0 0 0 1 0 +121 120 0 0 1 0 0 0 1 0 +121 121 1 1 0 1 0 0 1 0 +explain extended SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE g1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +1 SIMPLE g2 ALL NULL NULL NULL NULL 2 +Warnings: +Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,overlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,disjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,intersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid` +DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE t1 ( +gp point, +ln linestring, +pg polygon, +mp multipoint, +mln multilinestring, +mpg multipolygon, +gc geometrycollection, +gm geometry +); +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +ALTER TABLE t1 ADD fid INT; +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +fid int(11) YES NULL +DROP TABLE t1; +create table t1 (a geometry not null); +insert into t1 values (GeomFromText('Point(1 2)')); +insert into t1 values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert IGNORE into t1 values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; +create table t1 (fl geometry); +insert into t1 values (1); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values (1.11); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values ("qwerty"); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 values (pointfromtext('point(1,1)')); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; diff --git a/mysql-test/r/ndb_multi.result b/mysql-test/r/ndb_multi.result index 2080be241e8..bd3af223a65 100644 --- a/mysql-test/r/ndb_multi.result +++ b/mysql-test/r/ndb_multi.result @@ -30,6 +30,7 @@ create table t1 (a int) engine=ndbcluster; insert into t1 value (2); select * from t1; ERROR HY000: Got error 241 'Invalid schema object version' from ndbcluster +flush table t1; select * from t1; a 2 diff --git a/mysql-test/r/ndb_read_multi_range.result b/mysql-test/r/ndb_read_multi_range.result index f42ac394b6c..bb9398054ff 100644 --- a/mysql-test/r/ndb_read_multi_range.result +++ b/mysql-test/r/ndb_read_multi_range.result @@ -1,4 +1,4 @@ -DROP TABLE IF EXISTS t1, r1; +DROP TABLE IF EXISTS t1, t2, r1; create table t1 ( a int primary key, b int not null, diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result index 035c84431f8..77f2d5495a9 100644 --- a/mysql-test/r/openssl_1.result +++ b/mysql-test/r/openssl_1.result @@ -6,21 +6,33 @@ grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com"; grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com"; flush privileges; +SHOW STATUS LIKE 'Ssl_cipher'; +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA select * from t1; f1 5 delete from t1; ERROR 42000: DELETE command denied to user 'ssl_user1'@'localhost' for table 't1' +SHOW STATUS LIKE 'Ssl_cipher'; +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA select * from t1; f1 5 delete from t1; ERROR 42000: DELETE command denied to user 'ssl_user2'@'localhost' for table 't1' +SHOW STATUS LIKE 'Ssl_cipher'; +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA select * from t1; f1 5 delete from t1; ERROR 42000: DELETE command denied to user 'ssl_user3'@'localhost' for table 't1' +SHOW STATUS LIKE 'Ssl_cipher'; +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA select * from t1; f1 5 diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index f1c3672083d..bc3d2a6108c 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -337,7 +337,7 @@ set @precision=10000000000; select rand(), cast(rand(10)*@precision as unsigned integer) from t1; rand() cast(rand(10)*@precision as unsigned integer) -- 6570515219 +- 6570515220 - 1282061302 - 6698761160 - 9647622201 @@ -348,23 +348,23 @@ prepare stmt from set @var=1; execute stmt using @var; rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 - +- 6570515220 - - 1282061302 - - 6698761160 - - 9647622201 - set @var=2; execute stmt using @var; rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 6555866465 -- 1282061302 1223466192 -- 6698761160 6449731873 +- 6570515220 6555866465 +- 1282061302 1223466193 +- 6698761160 6449731874 - 9647622201 8578261098 set @var=3; execute stmt using @var; rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 9057697559 +- 6570515220 9057697560 - 1282061302 3730790581 -- 6698761160 1480860534 +- 6698761160 1480860535 - 9647622201 6211931236 drop table t1; deallocate prepare stmt; @@ -806,3 +806,29 @@ execute stmt; @@tx_isolation REPEATABLE-READ deallocate prepare stmt; +prepare stmt from "create temporary table t1 (letter enum('','a','b','c') +not null)"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +set names latin1; +prepare stmt from "create table t1 (a enum('test') default 'test') + character set utf8"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +set names default; +deallocate prepare stmt; +create table t1 (id int); +prepare ins_call from "insert into t1 (id) values (1)"; +execute ins_call; +select row_count(); +row_count() +1 +drop table t1; diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index d41d1b74ca7..aba3da02c4c 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -332,7 +332,6 @@ CSV YES/NO CSV storage engine ndbcluster YES/NO Clustered, fault-tolerant, memory-based tables FEDERATED YES/NO Federated MySQL storage engine MRG_MYISAM YES/NO Collection of identical MyISAM tables -binlog YES/NO This is a meta storage engine to represent the binlog in a transaction ISAM YES/NO Obsolete storage engine drop table if exists t5; prepare stmt1 from ' drop table if exists t5 ' ; diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 97d14b2be3a..405669e95f8 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -1022,6 +1022,31 @@ Variable_name Value Qcache_hits 1 drop table t1; create table t1 (a int); +flush status; +(select a from t1) union (select a from t1); +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +(select a from t1) union (select a from t1); +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +drop table t1; +create table t1 (a int); insert into t1 values (1),(2); CREATE PROCEDURE `p1`() begin diff --git a/mysql-test/r/read_only.result b/mysql-test/r/read_only.result new file mode 100644 index 00000000000..55a14bcaec8 --- /dev/null +++ b/mysql-test/r/read_only.result @@ -0,0 +1,43 @@ +DROP TABLE IF EXISTS t1,t2,t3; +grant CREATE, SELECT, DROP on *.* to test@localhost; +set global read_only=0; +create table t1 (a int); +insert into t1 values(1); +create table t2 select * from t1; +set global read_only=1; +create table t3 (a int); +drop table t3; +select @@global.read_only; +@@global.read_only +1 +create table t3 (a int); +ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement +insert into t1 values(1); +ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement +update t1 set a=1 where 1=0; +ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement +update t1,t2 set t1.a=t2.a+1 where t1.a=t2.a; +ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement +delete t1,t2 from t1,t2 where t1.a=t2.a; +ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement +create temporary table t3 (a int); +create temporary table t4 (a int) select * from t3; +insert into t3 values(1); +insert into t4 select * from t3; +update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; +ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement +update t1,t3 set t3.a=t1.a+1 where t1.a=t3.a; +update t4,t3 set t4.a=t3.a+1 where t4.a=t3.a; +delete t1 from t1,t3 where t1.a=t3.a; +ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement +delete t3 from t1,t3 where t1.a=t3.a; +delete t4 from t3,t4 where t4.a=t3.a; +create temporary table t1 (a int); +insert into t1 values(1); +update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; +delete t1 from t1,t3 where t1.a=t3.a; +drop table t1; +insert into t1 values(1); +ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement +drop table t1,t2; +drop user test@localhost; diff --git a/mysql-test/r/rpl000001.result b/mysql-test/r/rpl000001.result index 450e728090e..de9f6f16b2a 100644 --- a/mysql-test/r/rpl000001.result +++ b/mysql-test/r/rpl000001.result @@ -50,7 +50,7 @@ select (@id := id) - id from t2; 0 kill @id; drop table t2; -ERROR 08S01: Server shutdown in progress +Got one of the listed errors set global sql_slave_skip_counter=1; start slave; select count(*) from t1; diff --git a/mysql-test/r/rpl_ddl.result b/mysql-test/r/rpl_ddl.result index 2a97da63c64..4d8f2f11d4a 100644 --- a/mysql-test/r/rpl_ddl.result +++ b/mysql-test/r/rpl_ddl.result @@ -1465,13 +1465,13 @@ flush logs; -------- switch to master ------- SHOW TRIGGERS; -Trigger Event Table Statement Timing Created sql_mode -trg1 INSERT t1 SET @a:=1 BEFORE NULL +Trigger Event Table Statement Timing Created sql_mode Definer +trg1 INSERT t1 SET @a:=1 BEFORE NULL root@localhost -------- switch to slave ------- SHOW TRIGGERS; -Trigger Event Table Statement Timing Created sql_mode -trg1 INSERT t1 SET @a:=1 BEFORE NULL +Trigger Event Table Statement Timing Created sql_mode Definer +trg1 INSERT t1 SET @a:=1 BEFORE NULL root@localhost ######## DROP TRIGGER trg1 ######## @@ -1520,11 +1520,11 @@ flush logs; -------- switch to master ------- SHOW TRIGGERS; -Trigger Event Table Statement Timing Created sql_mode +Trigger Event Table Statement Timing Created sql_mode Definer -------- switch to slave ------- SHOW TRIGGERS; -Trigger Event Table Statement Timing Created sql_mode +Trigger Event Table Statement Timing Created sql_mode Definer ######## CREATE USER user1@localhost ######## diff --git a/mysql-test/r/rpl_deadlock.result b/mysql-test/r/rpl_deadlock.result index b112a51a145..c25cb1e6a53 100644 --- a/mysql-test/r/rpl_deadlock.result +++ b/mysql-test/r/rpl_deadlock.result @@ -83,5 +83,5 @@ a 22 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 18911 # # master-bin.000001 Yes Yes 0 0 18911 # None 0 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 18911 # # master-bin.000001 # Yes 0 0 18911 # None 0 No # drop table t1,t2,t3,t4; diff --git a/mysql-test/r/rpl_relayrotate.result b/mysql-test/r/rpl_relayrotate.result index c79187e12d0..20f19973d83 100644 --- a/mysql-test/r/rpl_relayrotate.result +++ b/mysql-test/r/rpl_relayrotate.result @@ -10,13 +10,7 @@ reset slave; start slave; stop slave; start slave; -select master_pos_wait('master-bin.001',3000)>=0; -master_pos_wait('master-bin.001',3000)>=0 -1 select max(a) from t1; max(a) 8000 -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 735186 # # master-bin.000001 Yes Yes 0 0 735186 # None 0 No # drop table t1; diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result index 5f1c3afd14d..c9a9e162fa6 100644 --- a/mysql-test/r/rpl_sp.result +++ b/mysql-test/r/rpl_sp.result @@ -4,16 +4,11 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -create database if not exists mysqltest1; +drop database if exists mysqltest1; +create database mysqltest1; use mysqltest1; create table t1 (a varchar(100)); use mysqltest1; -drop procedure if exists foo; -drop procedure if exists foo2; -drop procedure if exists foo3; -drop procedure if exists foo4; -drop procedure if exists bar; -drop function if exists fn1; create procedure foo() begin declare b int; @@ -21,21 +16,9 @@ set b = 8; insert into t1 values (b); insert into t1 values (unix_timestamp()); end| -ERROR HY000: This routine has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable) -show binlog events from 98| -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query 1 # create database if not exists mysqltest1 -master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a varchar(100)) -create procedure foo() deterministic -begin -declare b int; -set b = 8; -insert into t1 values (b); -insert into t1 values (unix_timestamp()); -end| select * from mysql.proc where name='foo' and db='mysqltest1'; db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment -mysqltest1 foo PROCEDURE foo SQL CONTAINS_SQL YES DEFINER begin +mysqltest1 foo PROCEDURE foo SQL CONTAINS_SQL NO DEFINER begin declare b int; set b = 8; insert into t1 values (b); @@ -43,7 +26,7 @@ insert into t1 values (unix_timestamp()); end root@localhost # # select * from mysql.proc where name='foo' and db='mysqltest1'; db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment -mysqltest1 foo PROCEDURE foo SQL CONTAINS_SQL YES DEFINER begin +mysqltest1 foo PROCEDURE foo SQL CONTAINS_SQL NO DEFINER begin declare b int; set b = 8; insert into t1 values (b); @@ -51,17 +34,6 @@ insert into t1 values (unix_timestamp()); end @ # # set timestamp=1000000000; call foo(); -show binlog events from 308; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo() deterministic -begin -declare b int; -set b = 8; -insert into t1 values (b); -insert into t1 values (unix_timestamp()); -end -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values ( NAME_CONST('b',8)) -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (unix_timestamp()) select * from t1; a 8 @@ -72,22 +44,10 @@ a 1000000000 delete from t1; create procedure foo2() -not deterministic -reads sql data select * from mysqltest1.t1; call foo2(); a -show binlog events from 518; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values ( NAME_CONST('b',8)) -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (unix_timestamp()) -master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1 -master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo2() -not deterministic -reads sql data -select * from mysqltest1.t1 alter procedure foo2 contains sql; -ERROR HY000: This routine has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable) drop table t1; create table t1 (a int); create table t2 like t1; @@ -97,11 +57,9 @@ insert into t1 values (15); grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1; -create procedure foo4() -deterministic -insert into t1 values (10); -ERROR HY000: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable) -set global log_bin_trust_routine_creators=1; +SELECT 1; +1 +1 create procedure foo4() deterministic begin @@ -110,46 +68,15 @@ insert into t1 values (5); end| call foo4(); Got one of the listed errors -show warnings; -Level Code Message -Error 1142 INSERT command denied to user 'zedjzlcsjhd'@'localhost' for table 't1' -Warning 1417 A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes call foo3(); show warnings; Level Code Message call foo4(); Got one of the listed errors -show warnings; -Level Code Message -Error 1142 INSERT command denied to user 'zedjzlcsjhd'@'127.0.0.1' for table 't1' -Warning 1417 A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes alter procedure foo4 sql security invoker; call foo4(); show warnings; Level Code Message -show binlog events from 990; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1 -master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int) -master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 like t1 -master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo3() -deterministic -insert into t1 values (15) -master-bin.000001 # Query 1 # use `mysqltest1`; grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1 -master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1 -master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1 -master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo4() -deterministic -begin -insert into t2 values(3); -insert into t1 values (5); -end -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3) -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (15) -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3) -master-bin.000001 # Query 1 # use `mysqltest1`; alter procedure foo4 sql security invoker -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3) -master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (5) select * from t1; a 15 @@ -168,11 +95,29 @@ a 3 3 3 +delete from t2; +alter table t2 add unique (a); +drop procedure foo4; +create procedure foo4() +deterministic +begin +insert into t2 values(20),(20); +end| +call foo4(); +ERROR 23000: Duplicate entry '20' for key 1 +show warnings; +Level Code Message +Error 1062 Duplicate entry '20' for key 1 +select * from t2; +a +20 +select * from t2; +a +20 select * from mysql.proc where name="foo4" and db='mysqltest1'; db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment -mysqltest1 foo4 PROCEDURE foo4 SQL CONTAINS_SQL YES INVOKER begin -insert into t2 values(3); -insert into t1 values (5); +mysqltest1 foo4 PROCEDURE foo4 SQL CONTAINS_SQL YES DEFINER begin +insert into t2 values(20),(20); end @ # # drop procedure foo4; select * from mysql.proc where name="foo4" and db='mysqltest1'; @@ -184,6 +129,13 @@ drop procedure foo2; drop procedure foo3; create function fn1(x int) returns int +begin +insert into t1 values (x); +return x+2; +end| +ERROR HY000: This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable) +create function fn1(x int) +returns int deterministic begin insert into t1 values (x); @@ -211,18 +163,55 @@ a drop function fn1; create function fn1() returns int -deterministic +no sql begin return unix_timestamp(); end| +alter function fn1 contains sql; +ERROR HY000: This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable) delete from t1; set timestamp=1000000000; insert into t1 values(fn1()); +create function fn2() +returns int +no sql +begin +return unix_timestamp(); +end| +ERROR HY000: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable) +set global log_bin_trust_routine_creators=1; +Warnings: +Warning 1287 'log_bin_trust_routine_creators' is deprecated; use 'log_bin_trust_function_creators' instead +set global log_bin_trust_function_creators=0; +set global log_bin_trust_function_creators=1; +set global log_bin_trust_function_creators=1; +create function fn2() +returns int +no sql +begin +return unix_timestamp(); +end| +create function fn3() +returns int +not deterministic +reads sql data +begin +return 0; +end| +select fn3(); +fn3() +0 select * from mysql.proc where db='mysqltest1'; db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment -mysqltest1 fn1 FUNCTION fn1 SQL CONTAINS_SQL YES DEFINER int(11) begin +mysqltest1 fn1 FUNCTION fn1 SQL NO_SQL NO DEFINER int(11) begin return unix_timestamp(); end root@localhost # # +mysqltest1 fn2 FUNCTION fn2 SQL NO_SQL NO DEFINER int(11) begin +return unix_timestamp(); +end zedjzlcsjhd@localhost # # +mysqltest1 fn3 FUNCTION fn3 SQL READS_SQL_DATA NO DEFINER int(11) begin +return 0; +end root@localhost # # select * from t1; a 1000000000 @@ -232,12 +221,34 @@ a 1000000000 select * from mysql.proc where db='mysqltest1'; db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment -mysqltest1 fn1 FUNCTION fn1 SQL CONTAINS_SQL YES DEFINER int(11) begin +mysqltest1 fn1 FUNCTION fn1 SQL NO_SQL NO DEFINER int(11) begin +return unix_timestamp(); +end @ # # +mysqltest1 fn2 FUNCTION fn2 SQL NO_SQL NO DEFINER int(11) begin return unix_timestamp(); end @ # # +mysqltest1 fn3 FUNCTION fn3 SQL READS_SQL_DATA NO DEFINER int(11) begin +return 0; +end @ # # +delete from t2; +alter table t2 add unique (a); +drop function fn1; +create function fn1() +returns int +begin +insert into t2 values(20),(20); +return 10; +end| +select fn1(); +ERROR 23000: Duplicate entry '20' for key 1 +select * from t2; +a +20 +select * from t2; +a +20 create trigger trg before insert on t1 for each row set new.a= 10; ERROR 42000: Access denied; you need the SUPER privilege for this operation -flush logs; delete from t1; create trigger trg before insert on t1 for each row set new.a= 10; insert into t1 values (1); @@ -253,14 +264,106 @@ insert into t1 values (1); select * from t1; a 1 -show binlog events in 'master-bin.000002' from 98; +show binlog events in 'master-bin.000001' from 98; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000002 # Query 1 # use `mysqltest1`; delete from t1 -master-bin.000002 # Query 1 # use `mysqltest1`; create trigger trg before insert on t1 for each row set new.a= 10 -master-bin.000002 # Query 1 # use `mysqltest1`; insert into t1 values (1) -master-bin.000002 # Query 1 # use `mysqltest1`; delete from t1 -master-bin.000002 # Query 1 # use `mysqltest1`; drop trigger trg -master-bin.000002 # Query 1 # use `mysqltest1`; insert into t1 values (1) +master-bin.000001 # Query 1 # drop database if exists mysqltest1 +master-bin.000001 # Query 1 # create database mysqltest1 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a varchar(100)) +master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo() +begin +declare b int; +set b = 8; +insert into t1 values (b); +insert into t1 values (unix_timestamp()); +end +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values ( NAME_CONST('b',8)) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (unix_timestamp()) +master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1 +master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo2() +select * from mysqltest1.t1 +master-bin.000001 # Query 1 # use `mysqltest1`; alter procedure foo2 contains sql +master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int) +master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 like t1 +master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo3() +deterministic +insert into t1 values (15) +master-bin.000001 # Query 1 # use `mysqltest1`; grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1 +master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1 +master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1 +master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo4() +deterministic +begin +insert into t2 values(3); +insert into t1 values (5); +end +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (15) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3) +master-bin.000001 # Query 1 # use `mysqltest1`; alter procedure foo4 sql security invoker +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (5) +master-bin.000001 # Query 1 # use `mysqltest1`; delete from t2 +master-bin.000001 # Query 1 # use `mysqltest1`; alter table t2 add unique (a) +master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo4 +master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo4() +deterministic +begin +insert into t2 values(20),(20); +end +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(20),(20) +master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo4 +master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo +master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo2 +master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo3 +master-bin.000001 # Query 1 # use `mysqltest1`; create function fn1(x int) +returns int +deterministic +begin +insert into t1 values (x); +return x+2; +end +master-bin.000001 # Query 1 # use `mysqltest1`; delete t1,t2 from t1,t2 +master-bin.000001 # Query 1 # use `mysqltest1`; DO `fn1`(20) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(fn1(21)) +master-bin.000001 # Query 1 # use `mysqltest1`; drop function fn1 +master-bin.000001 # Query 1 # use `mysqltest1`; create function fn1() +returns int +no sql +begin +return unix_timestamp(); +end +master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1 +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(fn1()) +master-bin.000001 # Query 1 # use `mysqltest1`; create function fn2() +returns int +no sql +begin +return unix_timestamp(); +end +master-bin.000001 # Query 1 # use `mysqltest1`; create function fn3() +returns int +not deterministic +reads sql data +begin +return 0; +end +master-bin.000001 # Query 1 # use `mysqltest1`; delete from t2 +master-bin.000001 # Query 1 # use `mysqltest1`; alter table t2 add unique (a) +master-bin.000001 # Query 1 # use `mysqltest1`; drop function fn1 +master-bin.000001 # Query 1 # use `mysqltest1`; create function fn1() +returns int +begin +insert into t2 values(20),(20); +return 10; +end +master-bin.000001 # Query 1 # use `mysqltest1`; DO `fn1`() +master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger trg before insert on t1 for each row set new.a= 10 +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (1) +master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1 +master-bin.000001 # Query 1 # use `mysqltest1`; drop trigger trg +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (1) select * from t1; a 1 @@ -275,3 +378,28 @@ drop procedure foo; drop function fn1; drop database mysqltest1; drop user "zedjzlcsjhd"@127.0.0.1; +use test; +use test; +drop function if exists f1; +create function f1() returns int reads sql data +begin +declare var integer; +declare c cursor for select a from v1; +open c; +fetch c into var; +close c; +return var; +end| +create view v1 as select 1 as a; +create table t1 (a int); +insert into t1 (a) values (f1()); +select * from t1; +a +1 +drop view v1; +drop function f1; +select * from t1; +a +1 +drop table t1; +reset master; diff --git a/mysql-test/r/rpl_trigger.result b/mysql-test/r/rpl_trigger.result index db824c9c423..7613f2547f0 100644 --- a/mysql-test/r/rpl_trigger.result +++ b/mysql-test/r/rpl_trigger.result @@ -89,8 +89,24 @@ insert into t1 set a = now(); select a=b && a=c from t1; a=b && a=c 1 +SELECT routine_name, definer +FROM information_schema.routines; +routine_name definer +bug12480 root@localhost +SELECT trigger_name, definer +FROM information_schema.triggers; +trigger_name definer +t1_first root@localhost --- On slave -- +SELECT routine_name, definer +FROM information_schema.routines; +routine_name definer +bug12480 @ +SELECT trigger_name, definer +FROM information_schema.triggers; +trigger_name definer +t1_first root@localhost select a=b && a=c from t1; a=b && a=c 1 @@ -106,3 +122,15 @@ a=b && a=c 1 drop function bug12480; drop table t1; +create table t1 (i int); +create table t2 (i int); +create trigger tr1 before insert on t1 for each row +begin +insert into t2 values (1); +end| +create database other; +use other; +insert into test.t1 values (1); +use test; +drop table t1,t2; +drop database other; diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index 64efeab0145..b584e04ed57 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -31,7 +31,7 @@ n 4 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 319 # Master master-bin.000001 319 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 319 # Master master-bin.000001 319 No # start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; select * from t1; n @@ -41,7 +41,7 @@ n 4 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 319 # Master master-no-such-bin.000001 291 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 319 # Master master-no-such-bin.000001 291 No # start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746; select * from t2; n @@ -49,7 +49,7 @@ n 2 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 608 # Relay slave-relay-bin.000004 746 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 608 # Relay slave-relay-bin.000004 746 No # start slave; stop slave; start slave until master_log_file='master-bin.000001', master_log_pos=776; diff --git a/mysql-test/r/schema.result b/mysql-test/r/schema.result index 48e6ebcfad2..538abd8d039 100644 --- a/mysql-test/r/schema.result +++ b/mysql-test/r/schema.result @@ -1,3 +1,4 @@ +drop database if exists mysqltest1; create schema foo; show create schema foo; Database Create Database diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index cd7c70b603c..e2c4609d902 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2700,6 +2700,22 @@ a b c d 1 2 2 1 1 2 3 1 DROP TABLE IF EXISTS t1, t2; +create table t1 (f1 int primary key, f2 int); +create table t2 (f3 int, f4 int, primary key(f3,f4)); +insert into t1 values (1,1); +insert into t2 values (1,1),(1,2); +select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1; +count(f2) >0 +1 +drop table t1,t2; +create table t1 (f1 int,f2 int); +insert into t1 values(1,1); +create table t2 (f3 int, f4 int, primary key(f3,f4)); +insert into t2 values(1,1); +select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2)); +f1 f2 +1 1 +drop table t1,t2; CREATE TABLE t1 ( city char(30) ); INSERT INTO t1 VALUES ('London'); INSERT INTO t1 VALUES ('Paris'); @@ -3193,3 +3209,139 @@ a b c select * from t1 join t2 straight_join t3 on (t1.a=t3.c); a b c drop table t1, t2 ,t3; +create table t1(f1 int, f2 date); +insert into t1 values(1,'2005-01-01'),(2,'2005-09-01'),(3,'2005-09-30'), +(4,'2005-10-01'),(5,'2005-12-30'); +select * from t1 where f2 >= 0; +f1 f2 +1 2005-01-01 +2 2005-09-01 +3 2005-09-30 +4 2005-10-01 +5 2005-12-30 +select * from t1 where f2 >= '0000-00-00'; +f1 f2 +1 2005-01-01 +2 2005-09-01 +3 2005-09-30 +4 2005-10-01 +5 2005-12-30 +select * from t1 where f2 >= '2005-09-31'; +f1 f2 +4 2005-10-01 +5 2005-12-30 +select * from t1 where f2 >= '2005-09-3a'; +f1 f2 +4 2005-10-01 +5 2005-12-30 +Warnings: +Warning 1292 Incorrect date value: '2005-09-3a' for column 'f2' at row 1 +select * from t1 where f2 <= '2005-09-31'; +f1 f2 +1 2005-01-01 +2 2005-09-01 +3 2005-09-30 +select * from t1 where f2 <= '2005-09-3a'; +f1 f2 +1 2005-01-01 +2 2005-09-01 +3 2005-09-30 +Warnings: +Warning 1292 Incorrect date value: '2005-09-3a' for column 'f2' at row 1 +drop table t1; +create table t1 (f1 int, f2 int); +insert into t1 values (1, 30), (2, 20), (3, 10); +create algorithm=merge view v1 as select f1, f2 from t1; +create algorithm=merge view v2 (f2, f1) as select f1, f2 from t1; +create algorithm=merge view v3 as select t1.f1 as f2, t1.f2 as f1 from t1; +select t1.f1 as x1, f1 from t1 order by t1.f1; +x1 f1 +1 1 +2 2 +3 3 +select v1.f1 as x1, f1 from v1 order by v1.f1; +x1 f1 +1 1 +2 2 +3 3 +select v2.f1 as x1, f1 from v2 order by v2.f1; +x1 f1 +10 10 +20 20 +30 30 +select v3.f1 as x1, f1 from v3 order by v3.f1; +x1 f1 +10 10 +20 20 +30 30 +select f1, f2, v1.f1 as x1 from v1 order by v1.f1; +f1 f2 x1 +1 30 1 +2 20 2 +3 10 3 +select f1, f2, v2.f1 as x1 from v2 order by v2.f1; +f1 f2 x1 +10 3 10 +20 2 20 +30 1 30 +select f1, f2, v3.f1 as x1 from v3 order by v3.f1; +f1 f2 x1 +10 3 10 +20 2 20 +30 1 30 +drop table t1; +drop view v1, v2, v3; +CREATE TABLE t1(key_a int4 NOT NULL, optimus varchar(32), PRIMARY KEY(key_a)); +CREATE TABLE t2(key_a int4 NOT NULL, prime varchar(32), PRIMARY KEY(key_a)); +CREATE table t3(key_a int4 NOT NULL, key_b int4 NOT NULL, foo varchar(32), +PRIMARY KEY(key_a,key_b)); +INSERT INTO t1 VALUES (0,''); +INSERT INTO t1 VALUES (1,'i'); +INSERT INTO t1 VALUES (2,'j'); +INSERT INTO t1 VALUES (3,'k'); +INSERT INTO t2 VALUES (1,'r'); +INSERT INTO t2 VALUES (2,'s'); +INSERT INTO t2 VALUES (3,'t'); +INSERT INTO t3 VALUES (1,5,'x'); +INSERT INTO t3 VALUES (1,6,'y'); +INSERT INTO t3 VALUES (2,5,'xx'); +INSERT INTO t3 VALUES (2,6,'yy'); +INSERT INTO t3 VALUES (2,7,'zz'); +INSERT INTO t3 VALUES (3,5,'xxx'); +SELECT t2.key_a,foo +FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a +INNER JOIN t3 ON t1.key_a = t3.key_a +WHERE t2.key_a=2 and key_b=5; +key_a foo +2 xx +EXPLAIN SELECT t2.key_a,foo +FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a +INNER JOIN t3 ON t1.key_a = t3.key_a +WHERE t2.key_a=2 and key_b=5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index +1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 Using index +1 SIMPLE t3 const PRIMARY PRIMARY 8 const,const 1 +SELECT t2.key_a,foo +FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a +INNER JOIN t3 ON t1.key_a = t3.key_a +WHERE t2.key_a=2 and key_b=5; +key_a foo +2 xx +EXPLAIN SELECT t2.key_a,foo +FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a +INNER JOIN t3 ON t1.key_a = t3.key_a +WHERE t2.key_a=2 and key_b=5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index +1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 Using index +1 SIMPLE t3 const PRIMARY PRIMARY 8 const,const 1 +DROP TABLE t1,t2,t3; +create table t1(f1 char, f2 char not null); +insert into t1 values(null,'a'); +create table t2 (f2 char not null); +insert into t2 values('b'); +select * from t1 left join t2 on f1=t2.f2 where t1.f2='a'; +f1 f2 f2 +NULL a NULL +drop table t1,t2; diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index fdb0db602ff..61a820b4469 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -1,6 +1,7 @@ drop table if exists t1,t2; drop table if exists t1aa,t2aa; drop database if exists mysqltest; +drop database if exists mysqltest1; delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; flush privileges; diff --git a/mysql-test/r/skip_grants.result b/mysql-test/r/skip_grants.result index 4d723f8e12a..5dc770a7363 100644 --- a/mysql-test/r/skip_grants.result +++ b/mysql-test/r/skip_grants.result @@ -4,7 +4,7 @@ drop procedure if exists f1; use test; create table t1 (field1 INT); CREATE VIEW v1 AS SELECT field1 FROM t1; -ERROR HY000: View definer is not fully qualified +ERROR HY000: Definer is not fully qualified drop table t1; create procedure f1() select 1; drop procedure f1; diff --git a/mysql-test/r/skip_name_resolve.result b/mysql-test/r/skip_name_resolve.result index a969c5c9ae0..8ef52e75238 100644 --- a/mysql-test/r/skip_name_resolve.result +++ b/mysql-test/r/skip_name_resolve.result @@ -10,5 +10,5 @@ user() # show processlist; Id User Host db Command Time State Info -# root # test Sleep # NULL -# root # test Query # NULL show processlist +<id> root <host> test <command> <time> <state> <info> +<id> root <host> test <command> <time> <state> <info> diff --git a/mysql-test/r/sp-big.result b/mysql-test/r/sp-big.result index 1f0b6b34651..9765508859c 100644 --- a/mysql-test/r/sp-big.result +++ b/mysql-test/r/sp-big.result @@ -25,6 +25,7 @@ count(*) select count(*) from t2; count(*) 0 +drop procedure if exists p1; create procedure p1() begin declare done integer default 0; diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result new file mode 100644 index 00000000000..e6c4ffe1731 --- /dev/null +++ b/mysql-test/r/sp-code.result @@ -0,0 +1,62 @@ +create procedure empty() +begin +end; +show procedure code empty; +Pos Instruction +drop procedure empty; +create function almost_empty() +returns int +return 0; +show function code almost_empty; +Pos Instruction +0 freturn 3 0 +drop function almost_empty; +create procedure code_sample(x int, out err int, out nulls int) +begin +declare count int default 0; +set nulls = 0; +begin +declare c cursor for select name from t1; +declare exit handler for not found close c; +open c; +loop +begin +declare n varchar(20); +declare continue handler for sqlexception set err=1; +fetch c into n; +if isnull(n) then +set nulls = nulls + 1; +else +set count = count + 1; +update t2 set idx = count where name=n; +end if; +end; +end loop; +end; +select t.name, t.idx from t2 t order by idx asc; +end// +show procedure code code_sample; +Pos Instruction +0 set count@3 0 +1 set nulls@2 0 +2 cpush c@0 +3 hpush_jump 6 4 EXIT +4 cclose c@0 +5 hreturn 0 19 +6 copen c@0 +7 set n@4 NULL +8 hpush_jump 11 5 CONTINUE +9 set err@1 1 +10 hreturn 5 +11 cfetch c@0 n@4 +12 jump_if_not 15 isnull(n@4) +13 set nulls@2 (nulls@2 + 1) +14 jump 17 +15 set count@3 (count@3 + 1) +16 stmt 4 "update t2 set idx = count where name=n" +17 hpop 1 +18 jump 7 +19 hpop 1 +20 cpop 1 +21 stmt 0 "select t.name, t.idx from t2 t order ..." +drop procedure code_sample; diff --git a/mysql-test/r/sp-destruct.result b/mysql-test/r/sp-destruct.result new file mode 100644 index 00000000000..1b720be9403 --- /dev/null +++ b/mysql-test/r/sp-destruct.result @@ -0,0 +1,77 @@ +use test; +drop procedure if exists bug14233; +drop function if exists bug14233; +drop table if exists t1; +drop view if exists v1; +create procedure bug14233() +set @x = 42; +create function bug14233_f() returns int +return 42; +create table t1 (id int); +create trigger t1_ai after insert on t1 for each row call bug14233(); +alter table mysql.proc drop type; +call bug14233(); +ERROR HY000: Failed to load routine test.bug14233. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5) +create view v1 as select bug14233_f(); +ERROR HY000: Failed to load routine test.bug14233_f. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5) +insert into t1 values (0); +ERROR HY000: Failed to load routine test.bug14233. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5) +flush table mysql.proc; +call bug14233(); +ERROR HY000: Incorrect information in file: './mysql/proc.frm' +create view v1 as select bug14233_f(); +ERROR HY000: Incorrect information in file: './mysql/proc.frm' +insert into t1 values (0); +ERROR HY000: Incorrect information in file: './mysql/proc.frm' +flush table mysql.proc; +call bug14233(); +ERROR 42S02: Table 'mysql.proc' doesn't exist +create view v1 as select bug14233_f(); +ERROR 42S02: Table 'mysql.proc' doesn't exist +insert into t1 values (0); +ERROR 42S02: Table 'mysql.proc' doesn't exist +flush table mysql.proc; +flush privileges; +delete from mysql.proc where name like 'bug14233%'; +insert into mysql.proc +( +db, name, type, specific_name, language, sql_data_access, is_deterministic, +security_type, param_list, returns, body, definer, created, modified, +sql_mode, comment +) +values +( +'test', 'bug14233_1', 'FUNCTION', 'bug14233_1', 'SQL', 'READS_SQL_DATA', 'NO', +'DEFINER', '', 'int(10)', +'select count(*) from mysql.user', +'root@localhost', NOW() , '0000-00-00 00:00:00', '', '' +), +( +'test', 'bug14233_2', 'FUNCTION', 'bug14233_2', 'SQL', 'READS_SQL_DATA', 'NO', +'DEFINER', '', 'int(10)', +'begin declare x int; select count(*) into x from mysql.user; end', +'root@localhost', NOW() , '0000-00-00 00:00:00', '', '' +), +( +'test', 'bug14233_3', 'PROCEDURE', 'bug14233_3', 'SQL', 'READS_SQL_DATA','NO', +'DEFINER', '', '', +'alksj wpsj sa ^#!@ ', +'root@localhost', NOW() , '0000-00-00 00:00:00', '', '' +); +select bug14233_1(); +ERROR HY000: Failed to load routine test.bug14233_1. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6) +create view v1 as select bug14233_1(); +ERROR HY000: Failed to load routine test.bug14233_1. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6) +select bug14233_2(); +ERROR HY000: Failed to load routine test.bug14233_2. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6) +create view v1 as select bug14233_2(); +ERROR HY000: Failed to load routine test.bug14233_2. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6) +call bug14233_3(); +ERROR HY000: Failed to load routine test.bug14233_3. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6) +drop trigger t1_ai; +create trigger t1_ai after insert on t1 for each row call bug14233_3(); +insert into t1 values (0); +ERROR HY000: Failed to load routine test.bug14233_3. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6) +delete from mysql.proc where name like 'bug14233%'; +drop trigger t1_ai; +drop table t1; diff --git a/mysql-test/r/sp-dynamic.result b/mysql-test/r/sp-dynamic.result index 8fe469431cc..c00b09f90e1 100644 --- a/mysql-test/r/sp-dynamic.result +++ b/mysql-test/r/sp-dynamic.result @@ -1,3 +1,5 @@ +drop procedure if exists p1| +drop procedure if exists p2| create procedure p1() begin prepare stmt from "select 1"; @@ -33,6 +35,8 @@ begin execute stmt; end| prepare stmt from "call p1()"| +set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth| +set @@max_sp_recursion_depth=100| execute stmt| ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner execute stmt| @@ -40,11 +44,18 @@ ERROR HY000: The prepared statement contains a stored routine call that refers t execute stmt| ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner call p1()| -ERROR HY000: Recursive stored routines are not allowed. +ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner +call p1()| +ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner +call p1()| +ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner +set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS| +call p1()| +ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine p1 call p1()| -ERROR HY000: Recursive stored routines are not allowed. +ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine p1 call p1()| -ERROR HY000: Recursive stored routines are not allowed. +ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine p1 drop procedure p1| create procedure p1() begin diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 50ff7ea264a..d7bed7e88a7 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -124,7 +124,7 @@ begin declare x int; set x = val+3; end| -ERROR 42000: No RETURN found in FUNCTION f +ERROR 42000: No RETURN found in FUNCTION test.f create function f(val int) returns int begin declare x int; @@ -708,7 +708,7 @@ return (i in (100, 200, bug11394(i-1), 400)); end if; end| select bug11394(2)| -ERROR HY000: Recursive stored routines are not allowed. +ERROR HY000: Recursive stored functions and triggers are not allowed. drop function bug11394| create function bug11394_1(i int) returns int begin @@ -719,7 +719,7 @@ return (select bug11394_1(i-1)); end if; end| select bug11394_1(2)| -ERROR HY000: Recursive stored routines are not allowed. +ERROR HY000: Recursive stored functions and triggers are not allowed. drop function bug11394_1| create function bug11394_2(i int) returns int return i| select bug11394_2(bug11394_2(10))| @@ -733,7 +733,10 @@ call bug11394(i - 1,(select 1)); end if; end| call bug11394(2, 1)| -ERROR HY000: Recursive stored routines are not allowed. +ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine bug11394 +set @@max_sp_recursion_depth=10| +call bug11394(2, 1)| +set @@max_sp_recursion_depth=default| drop procedure bug11394| CREATE PROCEDURE BUG_12490() HELP CONTENTS; ERROR 0A000: HELP is not allowed in stored procedures @@ -765,7 +768,7 @@ BEGIN OPTIMIZE TABLE t1; RETURN 1; END| -ERROR 0A000: OPTIMIZE TABLE is not allowed in stored procedures +ERROR 0A000: Not allowed to return a result set from a function DROP FUNCTION IF EXISTS bug12995| CREATE FUNCTION bug12995() RETURNS INT BEGIN @@ -845,6 +848,8 @@ set password = 'foo1'; select password; end| ERROR 42000: Variable 'password' must be quoted with `...`, or renamed +set names='foo2'| +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 create procedure bug13510_2() begin declare names varchar(10); @@ -872,6 +877,129 @@ names foo4 drop procedure bug13510_3| drop procedure bug13510_4| +drop function if exists bug_13627_f| +CREATE TABLE t1 (a int)| +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN DROP TRIGGER test1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN DROP TRIGGER test1; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN load table t1 from master; END | +ERROR 0A000: LOAD TABLE is not allowed in stored procedures +CREATE FUNCTION bug_13627_f() returns int BEGIN load table t1 from master; return 1; END | +ERROR 0A000: LOAD TABLE is not allowed in stored procedures +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create table t2 (a int); END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN create table t2 (a int); return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create index t1_i on t1 (a); END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN create index t1_i on t1 (a); return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN alter table t1 add column b int; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN alter table t1 add column b int; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN rename table t1 to t2; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN rename table t1 to t2; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN truncate table t1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN truncate table t1; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop table t1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN drop table t1; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop index t1_i on t1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN drop index t1_i on t1; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN unlock tables; END | +ERROR 0A000: UNLOCK is not allowed in stored procedures +CREATE FUNCTION bug_13627_f() returns int BEGIN unlock tables; return 1; END | +ERROR 0A000: UNLOCK is not allowed in stored procedures +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN LOCK TABLE t1 READ; END | +ERROR 0A000: LOCK is not allowed in stored procedures +CREATE FUNCTION bug_13627_f() returns int BEGIN LOCK TABLE t1 READ; return 1; END | +ERROR 0A000: LOCK is not allowed in stored procedures +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create database mysqltest; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN create database mysqltest; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop database mysqltest; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN drop database mysqltest; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create user 'mysqltest_1'; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN create user 'mysqltest_1'; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop user 'mysqltest_1'; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN drop user 'mysqltest_1'; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN rename user 'mysqltest_2' to 'mysqltest_1'; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN rename user 'mysqltest_2' to 'mysqltest_1'; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create view v1 as select 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN create view v1 as select 1; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN alter view v1 as select 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN alter view v1 as select 1; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop view v1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug_13627_f() returns int BEGIN drop view v1; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create trigger tr2 before insert on t1 for each row do select 1; END | +ERROR 2F003: Can't create a TRIGGER from within another stored routine +CREATE FUNCTION bug_13627_f() returns int BEGIN create trigger tr2 before insert on t1 for each row do select 1; return 1; END | +ERROR 2F003: Can't create a TRIGGER from within another stored routine +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop function bug_13627_f; END | +ERROR HY000: Can't drop or alter a FUNCTION from within another stored routine +CREATE FUNCTION bug_13627_f() returns int BEGIN drop function bug_13627_f; return 1; END | +ERROR HY000: Can't drop or alter a FUNCTION from within another stored routine +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create function f2 () returns int return 1; END | +ERROR 2F003: Can't create a FUNCTION from within another stored routine +CREATE FUNCTION bug_13627_f() returns int BEGIN create function f2 () returns int return 1; return 1; END | +ERROR 2F003: Can't create a FUNCTION from within another stored routine +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW +BEGIN +CREATE TEMPORARY TABLE t2 (a int); +DROP TEMPORARY TABLE t2; +END | +CREATE FUNCTION bug_13627_f() returns int +BEGIN +CREATE TEMPORARY TABLE t2 (a int); +DROP TEMPORARY TABLE t2; +return 1; +END | +drop table t1| +drop function bug_13627_f| +drop function if exists bug12329; +Warnings: +Note 1305 FUNCTION bug12329 does not exist +create table t1 as select 1 a; +create table t2 as select 1 a; +create function bug12329() returns int return (select a from t1); +prepare stmt1 from 'select bug12329()'; +execute stmt1; +bug12329() +1 +drop function bug12329; +create function bug12329() returns int return (select a+100 from t2); +select bug12329(); +bug12329() +101 +execute stmt1; +ERROR HY000: Table 't2' was not locked with LOCK TABLES +deallocate prepare stmt1; +drop function bug12329; +drop table t1, t2; create database mysqltest1; use mysqltest1; drop database mysqltest1; @@ -916,3 +1044,87 @@ ERROR 42S22: Unknown column 'bug13037_foo' in 'field list' DROP PROCEDURE bug13037_p1; DROP PROCEDURE bug13037_p2; DROP PROCEDURE bug13037_p3; +create database mysqltest1; +create database mysqltest2; +use mysqltest1; +drop database mysqltest1; +create procedure mysqltest2.p1() select version(); +create procedure p2() select version(); +ERROR 3D000: No database selected +use mysqltest2; +show procedure status; +Db Name Type Definer Modified Created Security_type Comment +mysqltest2 p1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +drop database mysqltest2; +use test; +DROP FUNCTION IF EXISTS bug13012| +CREATE FUNCTION bug13012() RETURNS INT +BEGIN +REPAIR TABLE t1; +RETURN 1; +END| +ERROR 0A000: Not allowed to return a result set from a function +CREATE FUNCTION bug13012() RETURNS INT +BEGIN +BACKUP TABLE t1 TO '/tmp'; +RETURN 1; +END| +ERROR 0A000: Not allowed to return a result set from a function +CREATE FUNCTION bug13012() RETURNS INT +BEGIN +RESTORE TABLE t1 FROM '/tmp'; +RETURN 1; +END| +ERROR 0A000: Not allowed to return a result set from a function +create table t1 (a int)| +CREATE PROCEDURE bug13012_1() REPAIR TABLE t1| +CREATE FUNCTION bug13012_2() RETURNS INT +BEGIN +CALL bug13012_1(); +RETURN 1; +END| +SELECT bug13012_2()| +ERROR 0A000: Not allowed to return a result set from a function +drop table t1| +drop procedure bug13012_1| +drop function bug13012_2| +drop function if exists bug11555_1; +drop function if exists bug11555_2; +drop view if exists v1, v2, v3, v4; +create function bug11555_1() returns int return (select max(i) from t1); +create function bug11555_2() returns int return bug11555_1(); +create view v1 as select bug11555_1(); +ERROR 42S02: Table 'test.t1' doesn't exist +create view v2 as select bug11555_2(); +ERROR 42S02: Table 'test.t1' doesn't exist +create table t1 (i int); +create view v1 as select bug11555_1(); +create view v2 as select bug11555_2(); +create view v3 as select * from v1; +drop table t1; +select * from v1; +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v2; +ERROR HY000: View 'test.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v3; +ERROR HY000: View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +create view v4 as select * from v1; +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +drop view v1, v2, v3; +drop function bug11555_1; +drop function bug11555_2; +create table t1 (i int); +create table t2 (i int); +create trigger t1_ai after insert on t1 for each row insert into t2 values (new.i); +create view v1 as select * from t1; +drop table t2; +insert into v1 values (1); +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +drop trigger t1_ai; +create function bug11555_1() returns int return (select max(i) from t2); +create trigger t1_ai after insert on t1 for each row set @a:=bug11555_1(); +insert into v1 values (2); +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +drop function bug11555_1; +drop table t1; +drop view v1; diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result new file mode 100644 index 00000000000..6b4d7b1a6d3 --- /dev/null +++ b/mysql-test/r/sp-vars.result @@ -0,0 +1,1077 @@ +DROP PROCEDURE IF EXISTS sp_vars_check_dflt; +DROP PROCEDURE IF EXISTS sp_vars_check_assignment; +DROP FUNCTION IF EXISTS sp_vars_check_ret1; +DROP FUNCTION IF EXISTS sp_vars_check_ret2; +DROP FUNCTION IF EXISTS sp_vars_check_ret3; +DROP FUNCTION IF EXISTS sp_vars_check_ret4; +SET @@sql_mode = 'ansi'; +CREATE PROCEDURE sp_vars_check_dflt() +BEGIN +DECLARE v1 TINYINT DEFAULT 1e200; +DECLARE v1u TINYINT UNSIGNED DEFAULT 1e200; +DECLARE v2 TINYINT DEFAULT -1e200; +DECLARE v2u TINYINT UNSIGNED DEFAULT -1e200; +DECLARE v3 TINYINT DEFAULT 300; +DECLARE v3u TINYINT UNSIGNED DEFAULT 300; +DECLARE v4 TINYINT DEFAULT -300; +DECLARE v4u TINYINT UNSIGNED DEFAULT -300; +DECLARE v5 TINYINT DEFAULT 10 * 10 * 10; +DECLARE v5u TINYINT UNSIGNED DEFAULT 10 * 10 * 10; +DECLARE v6 TINYINT DEFAULT -10 * 10 * 10; +DECLARE v6u TINYINT UNSIGNED DEFAULT -10 * 10 * 10; +DECLARE v7 TINYINT DEFAULT '10'; +DECLARE v8 TINYINT DEFAULT '10 '; +DECLARE v9 TINYINT DEFAULT ' 10 '; +DECLARE v10 TINYINT DEFAULT 'String 10 '; +DECLARE v11 TINYINT DEFAULT 'String10'; +DECLARE v12 TINYINT DEFAULT '10 String'; +DECLARE v13 TINYINT DEFAULT '10String'; +DECLARE v14 TINYINT DEFAULT concat('10', ' '); +DECLARE v15 TINYINT DEFAULT concat(' ', '10'); +DECLARE v16 TINYINT DEFAULT concat('Hello, ', 'world'); +DECLARE v17 DECIMAL(64, 2) DEFAULT 12; +DECLARE v18 DECIMAL(64, 2) DEFAULT 12.123; +DECLARE v19 DECIMAL(64, 2) DEFAULT 11 + 1; +DECLARE v20 DECIMAL(64, 2) DEFAULT 12 + 0.123; +SELECT v1, v1u, v2, v2u, v3, v3u, v4, v4u; +SELECT v5, v5u, v6, v6u; +SELECT v7, v8, v9, v10, v11, v12, v13, v14, v15, v16; +SELECT v17, v18, v19, v20; +END| +CREATE PROCEDURE sp_vars_check_assignment() +BEGIN +DECLARE i1, i2, i3, i4 TINYINT; +DECLARE u1, u2, u3, u4 TINYINT UNSIGNED; +DECLARE d1, d2, d3 DECIMAL(64, 2); +SET i1 = 1e200; +SET i2 = -1e200; +SET i3 = 300; +SET i4 = -300; +SELECT i1, i2, i3, i4; +SET i1 = 10 * 10 * 10; +SET i2 = -10 * 10 * 10; +SET i3 = sign(10 * 10) * 10 * 20; +SET i4 = sign(-10 * 10) * -10 * 20; +SELECT i1, i2, i3, i4; +SET u1 = 1e200; +SET u2 = -1e200; +SET u3 = 300; +SET u4 = -300; +SELECT u1, u2, u3, u4; +SET u1 = 10 * 10 * 10; +SET u2 = -10 * 10 * 10; +SET u3 = sign(10 * 10) * 10 * 20; +SET u4 = sign(-10 * 10) * -10 * 20; +SELECT u1, u2, u3, u4; +SET d1 = 1234; +SET d2 = 1234.12; +SET d3 = 1234.1234; +SELECT d1, d2, d3; +SET d1 = 12 * 100 + 34; +SET d2 = 12 * 100 + 34 + 0.12; +SET d3 = 12 * 100 + 34 + 0.1234; +SELECT d1, d2, d3; +END| +CREATE FUNCTION sp_vars_check_ret1() RETURNS TINYINT +BEGIN +RETURN 1e200; +END| +CREATE FUNCTION sp_vars_check_ret2() RETURNS TINYINT +BEGIN +RETURN 10 * 10 * 10; +END| +CREATE FUNCTION sp_vars_check_ret3() RETURNS TINYINT +BEGIN +RETURN 'Hello, world'; +END| +CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2) +BEGIN +RETURN 12 * 10 + 34 + 0.1234; +END| + +--------------------------------------------------------------- +Calling the routines, created in ANSI mode. +--------------------------------------------------------------- + +CALL sp_vars_check_dflt(); +v1 v1u v2 v2u v3 v3u v4 v4u +127 255 -128 0 127 255 -128 0 +v5 v5u v6 v6u +127 255 -128 0 +v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 +10 10 10 0 0 10 10 10 10 0 +v17 v18 v19 v20 +12.00 12.12 12.00 12.12 +Warnings: +Warning 1264 Out of range value adjusted for column 'v1' at row 1 +Warning 1264 Out of range value adjusted for column 'v1u' at row 1 +Warning 1264 Out of range value adjusted for column 'v2' at row 1 +Warning 1264 Out of range value adjusted for column 'v2u' at row 1 +Warning 1264 Out of range value adjusted for column 'v3' at row 1 +Warning 1264 Out of range value adjusted for column 'v3u' at row 1 +Warning 1264 Out of range value adjusted for column 'v4' at row 1 +Warning 1264 Out of range value adjusted for column 'v4u' at row 1 +Warning 1264 Out of range value adjusted for column 'v5' at row 1 +Warning 1264 Out of range value adjusted for column 'v5u' at row 1 +Warning 1264 Out of range value adjusted for column 'v6' at row 1 +Warning 1264 Out of range value adjusted for column 'v6u' at row 1 +Warning 1366 Incorrect integer value: 'String 10 ' for column 'v10' at row 1 +Warning 1366 Incorrect integer value: 'String10' for column 'v11' at row 1 +Warning 1265 Data truncated for column 'v12' at row 1 +Warning 1265 Data truncated for column 'v13' at row 1 +Warning 1366 Incorrect integer value: 'Hello, world' for column 'v16' at row 1 +Note 1265 Data truncated for column 'v18' at row 1 +Note 1265 Data truncated for column 'v20' at row 1 +CALL sp_vars_check_assignment(); +i1 i2 i3 i4 +127 -128 127 -128 +i1 i2 i3 i4 +127 -128 127 127 +u1 u2 u3 u4 +255 0 255 0 +u1 u2 u3 u4 +255 0 200 200 +d1 d2 d3 +1234.00 1234.12 1234.12 +d1 d2 d3 +1234.00 1234.12 1234.12 +Warnings: +Warning 1264 Out of range value adjusted for column 'i1' at row 1 +Warning 1264 Out of range value adjusted for column 'i2' at row 1 +Warning 1264 Out of range value adjusted for column 'i3' at row 1 +Warning 1264 Out of range value adjusted for column 'i4' at row 1 +Warning 1264 Out of range value adjusted for column 'i1' at row 1 +Warning 1264 Out of range value adjusted for column 'i2' at row 1 +Warning 1264 Out of range value adjusted for column 'i3' at row 1 +Warning 1264 Out of range value adjusted for column 'i4' at row 1 +Warning 1264 Out of range value adjusted for column 'u1' at row 1 +Warning 1264 Out of range value adjusted for column 'u2' at row 1 +Warning 1264 Out of range value adjusted for column 'u3' at row 1 +Warning 1264 Out of range value adjusted for column 'u4' at row 1 +Warning 1264 Out of range value adjusted for column 'u1' at row 1 +Warning 1264 Out of range value adjusted for column 'u2' at row 1 +Note 1265 Data truncated for column 'd3' at row 1 +Note 1265 Data truncated for column 'd3' at row 1 +SELECT sp_vars_check_ret1(); +sp_vars_check_ret1() +127 +Warnings: +Warning 1264 Out of range value adjusted for column 'sp_vars_check_ret1()' at row 1 +SELECT sp_vars_check_ret2(); +sp_vars_check_ret2() +127 +Warnings: +Warning 1264 Out of range value adjusted for column 'sp_vars_check_ret2()' at row 1 +SELECT sp_vars_check_ret3(); +sp_vars_check_ret3() +0 +Warnings: +Warning 1366 Incorrect integer value: 'Hello, world' for column 'sp_vars_check_ret3()' at row 1 +SELECT sp_vars_check_ret4(); +sp_vars_check_ret4() +154.12 +Warnings: +Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1 +SET @@sql_mode = 'traditional'; + +--------------------------------------------------------------- +Calling in TRADITIONAL mode the routines, created in ANSI mode. +--------------------------------------------------------------- + +CALL sp_vars_check_dflt(); +v1 v1u v2 v2u v3 v3u v4 v4u +127 255 -128 0 127 255 -128 0 +v5 v5u v6 v6u +127 255 -128 0 +v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 +10 10 10 0 0 10 10 10 10 0 +v17 v18 v19 v20 +12.00 12.12 12.00 12.12 +Warnings: +Warning 1264 Out of range value adjusted for column 'v1' at row 1 +Warning 1264 Out of range value adjusted for column 'v1u' at row 1 +Warning 1264 Out of range value adjusted for column 'v2' at row 1 +Warning 1264 Out of range value adjusted for column 'v2u' at row 1 +Warning 1264 Out of range value adjusted for column 'v3' at row 1 +Warning 1264 Out of range value adjusted for column 'v3u' at row 1 +Warning 1264 Out of range value adjusted for column 'v4' at row 1 +Warning 1264 Out of range value adjusted for column 'v4u' at row 1 +Warning 1264 Out of range value adjusted for column 'v5' at row 1 +Warning 1264 Out of range value adjusted for column 'v5u' at row 1 +Warning 1264 Out of range value adjusted for column 'v6' at row 1 +Warning 1264 Out of range value adjusted for column 'v6u' at row 1 +Warning 1366 Incorrect integer value: 'String 10 ' for column 'v10' at row 1 +Warning 1366 Incorrect integer value: 'String10' for column 'v11' at row 1 +Warning 1265 Data truncated for column 'v12' at row 1 +Warning 1265 Data truncated for column 'v13' at row 1 +Warning 1366 Incorrect integer value: 'Hello, world' for column 'v16' at row 1 +Note 1265 Data truncated for column 'v18' at row 1 +Note 1265 Data truncated for column 'v20' at row 1 +CALL sp_vars_check_assignment(); +i1 i2 i3 i4 +127 -128 127 -128 +i1 i2 i3 i4 +127 -128 127 127 +u1 u2 u3 u4 +255 0 255 0 +u1 u2 u3 u4 +255 0 200 200 +d1 d2 d3 +1234.00 1234.12 1234.12 +d1 d2 d3 +1234.00 1234.12 1234.12 +Warnings: +Warning 1264 Out of range value adjusted for column 'i1' at row 1 +Warning 1264 Out of range value adjusted for column 'i2' at row 1 +Warning 1264 Out of range value adjusted for column 'i3' at row 1 +Warning 1264 Out of range value adjusted for column 'i4' at row 1 +Warning 1264 Out of range value adjusted for column 'i1' at row 1 +Warning 1264 Out of range value adjusted for column 'i2' at row 1 +Warning 1264 Out of range value adjusted for column 'i3' at row 1 +Warning 1264 Out of range value adjusted for column 'i4' at row 1 +Warning 1264 Out of range value adjusted for column 'u1' at row 1 +Warning 1264 Out of range value adjusted for column 'u2' at row 1 +Warning 1264 Out of range value adjusted for column 'u3' at row 1 +Warning 1264 Out of range value adjusted for column 'u4' at row 1 +Warning 1264 Out of range value adjusted for column 'u1' at row 1 +Warning 1264 Out of range value adjusted for column 'u2' at row 1 +Note 1265 Data truncated for column 'd3' at row 1 +Note 1265 Data truncated for column 'd3' at row 1 +SELECT sp_vars_check_ret1(); +sp_vars_check_ret1() +127 +Warnings: +Warning 1264 Out of range value adjusted for column 'sp_vars_check_ret1()' at row 1 +SELECT sp_vars_check_ret2(); +sp_vars_check_ret2() +127 +Warnings: +Warning 1264 Out of range value adjusted for column 'sp_vars_check_ret2()' at row 1 +SELECT sp_vars_check_ret3(); +sp_vars_check_ret3() +0 +Warnings: +Warning 1366 Incorrect integer value: 'Hello, world' for column 'sp_vars_check_ret3()' at row 1 +SELECT sp_vars_check_ret4(); +sp_vars_check_ret4() +154.12 +Warnings: +Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1 +DROP PROCEDURE sp_vars_check_dflt; +DROP PROCEDURE sp_vars_check_assignment; +DROP FUNCTION sp_vars_check_ret1; +DROP FUNCTION sp_vars_check_ret2; +DROP FUNCTION sp_vars_check_ret3; +DROP FUNCTION sp_vars_check_ret4; +CREATE PROCEDURE sp_vars_check_dflt() +BEGIN +DECLARE v1 TINYINT DEFAULT 1e200; +DECLARE v1u TINYINT UNSIGNED DEFAULT 1e200; +DECLARE v2 TINYINT DEFAULT -1e200; +DECLARE v2u TINYINT UNSIGNED DEFAULT -1e200; +DECLARE v3 TINYINT DEFAULT 300; +DECLARE v3u TINYINT UNSIGNED DEFAULT 300; +DECLARE v4 TINYINT DEFAULT -300; +DECLARE v4u TINYINT UNSIGNED DEFAULT -300; +DECLARE v5 TINYINT DEFAULT 10 * 10 * 10; +DECLARE v5u TINYINT UNSIGNED DEFAULT 10 * 10 * 10; +DECLARE v6 TINYINT DEFAULT -10 * 10 * 10; +DECLARE v6u TINYINT UNSIGNED DEFAULT -10 * 10 * 10; +DECLARE v7 TINYINT DEFAULT '10'; +DECLARE v8 TINYINT DEFAULT '10 '; +DECLARE v9 TINYINT DEFAULT ' 10 '; +DECLARE v10 TINYINT DEFAULT 'String 10 '; +DECLARE v11 TINYINT DEFAULT 'String10'; +DECLARE v12 TINYINT DEFAULT '10 String'; +DECLARE v13 TINYINT DEFAULT '10String'; +DECLARE v14 TINYINT DEFAULT concat('10', ' '); +DECLARE v15 TINYINT DEFAULT concat(' ', '10'); +DECLARE v16 TINYINT DEFAULT concat('Hello, ', 'world'); +DECLARE v17 DECIMAL(64, 2) DEFAULT 12; +DECLARE v18 DECIMAL(64, 2) DEFAULT 12.123; +DECLARE v19 DECIMAL(64, 2) DEFAULT 11 + 1; +DECLARE v20 DECIMAL(64, 2) DEFAULT 12 + 0.123; +SELECT v1, v1u, v2, v2u, v3, v3u, v4, v4u; +SELECT v5, v5u, v6, v6u; +SELECT v7, v8, v9, v10, v11, v12, v13, v14, v15, v16; +SELECT v17, v18, v19, v20; +END| +CREATE PROCEDURE sp_vars_check_assignment() +BEGIN +DECLARE i1, i2, i3, i4 TINYINT; +DECLARE u1, u2, u3, u4 TINYINT UNSIGNED; +DECLARE d1, d2, d3 DECIMAL(64, 2); +SET i1 = 1e200; +SET i2 = -1e200; +SET i3 = 300; +SET i4 = -300; +SELECT i1, i2, i3, i4; +SET i1 = 10 * 10 * 10; +SET i2 = -10 * 10 * 10; +SET i3 = sign(10 * 10) * 10 * 20; +SET i4 = sign(-10 * 10) * -10 * 20; +SELECT i1, i2, i3, i4; +SET u1 = 1e200; +SET u2 = -1e200; +SET u3 = 300; +SET u4 = -300; +SELECT u1, u2, u3, u4; +SET u1 = 10 * 10 * 10; +SET u2 = -10 * 10 * 10; +SET u3 = sign(10 * 10) * 10 * 20; +SET u4 = sign(-10 * 10) * -10 * 20; +SELECT u1, u2, u3, u4; +SET d1 = 1234; +SET d2 = 1234.12; +SET d3 = 1234.1234; +SELECT d1, d2, d3; +SET d1 = 12 * 100 + 34; +SET d2 = 12 * 100 + 34 + 0.12; +SET d3 = 12 * 100 + 34 + 0.1234; +SELECT d1, d2, d3; +END| +CREATE FUNCTION sp_vars_check_ret1() RETURNS TINYINT +BEGIN +RETURN 1e200; +END| +CREATE FUNCTION sp_vars_check_ret2() RETURNS TINYINT +BEGIN +RETURN 10 * 10 * 10; +END| +CREATE FUNCTION sp_vars_check_ret3() RETURNS TINYINT +BEGIN +RETURN 'Hello, world'; +END| +CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2) +BEGIN +RETURN 12 * 10 + 34 + 0.1234; +END| + +--------------------------------------------------------------- +Calling the routines, created in TRADITIONAL mode. +--------------------------------------------------------------- + +CALL sp_vars_check_dflt(); +ERROR 22003: Out of range value adjusted for column 'v1' at row 1 +CALL sp_vars_check_assignment(); +ERROR 22003: Out of range value adjusted for column 'i1' at row 1 +SELECT sp_vars_check_ret1(); +ERROR 22003: Out of range value adjusted for column 'sp_vars_check_ret1()' at row 1 +SELECT sp_vars_check_ret2(); +ERROR 22003: Out of range value adjusted for column 'sp_vars_check_ret2()' at row 1 +SELECT sp_vars_check_ret3(); +ERROR HY000: Incorrect integer value: 'Hello, world' for column 'sp_vars_check_ret3()' at row 1 +SELECT sp_vars_check_ret4(); +sp_vars_check_ret4() +154.12 +Warnings: +Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1 +SET @@sql_mode = 'ansi'; +DROP PROCEDURE sp_vars_check_dflt; +DROP PROCEDURE sp_vars_check_assignment; +DROP FUNCTION sp_vars_check_ret1; +DROP FUNCTION sp_vars_check_ret2; +DROP FUNCTION sp_vars_check_ret3; +DROP FUNCTION sp_vars_check_ret4; + +--------------------------------------------------------------- +BIT data type tests +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +CREATE PROCEDURE p1() +BEGIN +DECLARE v1 BIT; +DECLARE v2 BIT(1); +DECLARE v3 BIT(3) DEFAULT b'101'; +DECLARE v4 BIT(64) DEFAULT 0x5555555555555555; +DECLARE v5 BIT(3); +DECLARE v6 BIT(64); +DECLARE v7 BIT(8) DEFAULT 128; +DECLARE v8 BIT(8) DEFAULT '128'; +DECLARE v9 BIT(8) DEFAULT ' 128'; +DECLARE v10 BIT(8) DEFAULT 'x 128'; +SET v1 = v4; +SET v2 = 0; +SET v5 = v4; # check overflow +SET v6 = v3; # check padding +SELECT HEX(v1); +SELECT HEX(v2); +SELECT HEX(v3); +SELECT HEX(v4); +SELECT HEX(v5); +SELECT HEX(v6); +SELECT HEX(v7); +SELECT HEX(v8); +SELECT HEX(v9); +SELECT HEX(v10); +END| +CALL p1(); +HEX(v1) +01 +HEX(v2) +00 +HEX(v3) +05 +HEX(v4) +5555555555555555 +HEX(v5) +07 +HEX(v6) +0000000000000005 +HEX(v7) +80 +HEX(v8) +FF +HEX(v9) +FF +HEX(v10) +FF +Warnings: +Warning 1264 Out of range value adjusted for column 'v8' at row 1 +Warning 1264 Out of range value adjusted for column 'v9' at row 1 +Warning 1264 Out of range value adjusted for column 'v10' at row 1 +Warning 1264 Out of range value adjusted for column 'v1' at row 1 +Warning 1264 Out of range value adjusted for column 'v5' at row 1 +DROP PROCEDURE p1; + +--------------------------------------------------------------- +CASE expression tests. +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +Warnings: +Note 1305 PROCEDURE p1 does not exist +DROP PROCEDURE IF EXISTS p2; +Warnings: +Note 1305 PROCEDURE p2 does not exist +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 't1' +CREATE TABLE t1(log_msg VARCHAR(1024)); +CREATE PROCEDURE p1(arg VARCHAR(255)) +BEGIN +INSERT INTO t1 VALUES('p1: step1'); +CASE arg * 10 +WHEN 10 * 10 THEN +INSERT INTO t1 VALUES('p1: case1: on 10'); +WHEN 10 * 10 + 10 * 10 THEN +BEGIN +CASE arg / 10 +WHEN 1 THEN +INSERT INTO t1 VALUES('p1: case1: case2: on 1'); +WHEN 2 THEN +BEGIN +DECLARE i TINYINT DEFAULT 10; +WHILE i > 0 DO +INSERT INTO t1 VALUES(CONCAT('p1: case1: case2: loop: i: ', i)); +CASE MOD(i, 2) +WHEN 0 THEN +INSERT INTO t1 VALUES('p1: case1: case2: loop: i is even'); +WHEN 1 THEN +INSERT INTO t1 VALUES('p1: case1: case2: loop: i is odd'); +ELSE +INSERT INTO t1 VALUES('p1: case1: case2: loop: ERROR'); +END CASE; +SET i = i - 1; +END WHILE; +END; +ELSE +INSERT INTO t1 VALUES('p1: case1: case2: ERROR'); +END CASE; +CASE arg +WHEN 10 THEN +INSERT INTO t1 VALUES('p1: case1: case3: on 10'); +WHEN 20 THEN +INSERT INTO t1 VALUES('p1: case1: case3: on 20'); +ELSE +INSERT INTO t1 VALUES('p1: case1: case3: ERROR'); +END CASE; +END; +ELSE +INSERT INTO t1 VALUES('p1: case1: ERROR'); +END CASE; +CASE arg * 10 +WHEN 10 * 10 THEN +INSERT INTO t1 VALUES('p1: case4: on 10'); +WHEN 10 * 10 + 10 * 10 THEN +BEGIN +CASE arg / 10 +WHEN 1 THEN +INSERT INTO t1 VALUES('p1: case4: case5: on 1'); +WHEN 2 THEN +BEGIN +DECLARE i TINYINT DEFAULT 10; +WHILE i > 0 DO +INSERT INTO t1 VALUES(CONCAT('p1: case4: case5: loop: i: ', i)); +CASE MOD(i, 2) +WHEN 0 THEN +INSERT INTO t1 VALUES('p1: case4: case5: loop: i is even'); +WHEN 1 THEN +INSERT INTO t1 VALUES('p1: case4: case5: loop: i is odd'); +ELSE +INSERT INTO t1 VALUES('p1: case4: case5: loop: ERROR'); +END CASE; +SET i = i - 1; +END WHILE; +END; +ELSE +INSERT INTO t1 VALUES('p1: case4: case5: ERROR'); +END CASE; +CASE arg +WHEN 10 THEN +INSERT INTO t1 VALUES('p1: case4: case6: on 10'); +WHEN 20 THEN +INSERT INTO t1 VALUES('p1: case4: case6: on 20'); +ELSE +INSERT INTO t1 VALUES('p1: case4: case6: ERROR'); +END CASE; +END; +ELSE +INSERT INTO t1 VALUES('p1: case4: ERROR'); +END CASE; +END| +CREATE PROCEDURE p2() +BEGIN +DECLARE i TINYINT DEFAULT 3; +WHILE i > 0 DO +IF MOD(i, 2) = 0 THEN +SET @_test_session_var = 10; +ELSE +SET @_test_session_var = 'test'; +END IF; +CASE @_test_session_var +WHEN 10 THEN +INSERT INTO t1 VALUES('p2: case: numerical type'); +WHEN 'test' THEN +INSERT INTO t1 VALUES('p2: case: string type'); +ELSE +INSERT INTO t1 VALUES('p2: case: ERROR'); +END CASE; +SET i = i - 1; +END WHILE; +END| +CALL p1(10); +CALL p1(20); +CALL p2(); +SELECT * FROM t1; +log_msg +p1: step1 +p1: case1: on 10 +p1: case4: on 10 +p1: step1 +p1: case1: case2: loop: i: 10 +p1: case1: case2: loop: i is even +p1: case1: case2: loop: i: 9 +p1: case1: case2: loop: i is odd +p1: case1: case2: loop: i: 8 +p1: case1: case2: loop: i is even +p1: case1: case2: loop: i: 7 +p1: case1: case2: loop: i is odd +p1: case1: case2: loop: i: 6 +p1: case1: case2: loop: i is even +p1: case1: case2: loop: i: 5 +p1: case1: case2: loop: i is odd +p1: case1: case2: loop: i: 4 +p1: case1: case2: loop: i is even +p1: case1: case2: loop: i: 3 +p1: case1: case2: loop: i is odd +p1: case1: case2: loop: i: 2 +p1: case1: case2: loop: i is even +p1: case1: case2: loop: i: 1 +p1: case1: case2: loop: i is odd +p1: case1: case3: on 20 +p1: case4: case5: loop: i: 10 +p1: case4: case5: loop: i is even +p1: case4: case5: loop: i: 9 +p1: case4: case5: loop: i is odd +p1: case4: case5: loop: i: 8 +p1: case4: case5: loop: i is even +p1: case4: case5: loop: i: 7 +p1: case4: case5: loop: i is odd +p1: case4: case5: loop: i: 6 +p1: case4: case5: loop: i is even +p1: case4: case5: loop: i: 5 +p1: case4: case5: loop: i is odd +p1: case4: case5: loop: i: 4 +p1: case4: case5: loop: i is even +p1: case4: case5: loop: i: 3 +p1: case4: case5: loop: i is odd +p1: case4: case5: loop: i: 2 +p1: case4: case5: loop: i is even +p1: case4: case5: loop: i: 1 +p1: case4: case5: loop: i is odd +p1: case4: case6: on 20 +p2: case: string type +p2: case: numerical type +p2: case: string type +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP TABLE t1; + +--------------------------------------------------------------- +BUG#14161 +--------------------------------------------------------------- + +DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; +CREATE TABLE t1(col BIGINT UNSIGNED); +INSERT INTO t1 VALUE(18446744073709551614); +CREATE PROCEDURE p1(IN arg BIGINT UNSIGNED) +BEGIN +SELECT arg; +SELECT * FROM t1; +SELECT * FROM t1 WHERE col = arg; +END| +CALL p1(18446744073709551614); +arg +18446744073709551614 +col +18446744073709551614 +col +18446744073709551614 +DROP TABLE t1; +DROP PROCEDURE p1; + +--------------------------------------------------------------- +BUG#13705 +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +CREATE PROCEDURE p1(x VARCHAR(10), y CHAR(3)) READS SQL DATA +BEGIN +SELECT x, y; +END| +CALL p1('alpha', 'abc'); +x y +alpha abc +CALL p1('alpha', 'abcdef'); +x y +alpha abc +Warnings: +Warning 1265 Data truncated for column 'y' at row 1 +DROP PROCEDURE p1; + +--------------------------------------------------------------- +BUG#13675 +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1; +CREATE PROCEDURE p1(x DATETIME) +BEGIN +CREATE TABLE t1 SELECT x; +SHOW CREATE TABLE t1; +DROP TABLE t1; +END| +CALL p1(NOW()); +Table Create Table +t1 CREATE TABLE "t1" ( + "x" varbinary(19) default NULL +) +CALL p1('test'); +Table Create Table +t1 CREATE TABLE "t1" ( + "x" varbinary(19) default NULL +) +Warnings: +Warning 1264 Out of range value adjusted for column 'x' at row 1 +DROP PROCEDURE p1; + +--------------------------------------------------------------- +BUG#12976 +--------------------------------------------------------------- + +DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +CREATE TABLE t1(b BIT(1)); +INSERT INTO t1(b) VALUES(b'0'), (b'1'); +CREATE PROCEDURE p1() +BEGIN +SELECT HEX(b), +b = 0, +b = FALSE, +b IS FALSE, +b = 1, +b = TRUE, +b IS TRUE +FROM t1; +END| +CREATE PROCEDURE p2() +BEGIN +DECLARE vb BIT(1); +SELECT b INTO vb FROM t1 WHERE b = 0; +SELECT HEX(vb), +vb = 0, +vb = FALSE, +vb IS FALSE, +vb = 1, +vb = TRUE, +vb IS TRUE; +SELECT b INTO vb FROM t1 WHERE b = 1; +SELECT HEX(vb), +vb = 0, +vb = FALSE, +vb IS FALSE, +vb = 1, +vb = TRUE, +vb IS TRUE; +END| +call p1(); +HEX(b) b = 0 b = FALSE b IS FALSE b = 1 b = TRUE b IS TRUE + +0 1 1 1 0 0 0 +1 0 0 0 1 1 1 +call p2(); +HEX(vb) vb = 0 vb = FALSE vb IS FALSE vb = 1 vb = TRUE vb IS TRUE +00 1 1 1 0 0 0 +HEX(vb) vb = 0 vb = FALSE vb IS FALSE vb = 1 vb = TRUE vb IS TRUE +01 0 0 1 1 1 0 +DROP TABLE t1; +DROP PROCEDURE p1; +DROP PROCEDURE p2; + +--------------------------------------------------------------- +BUG#9572 +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +DROP PROCEDURE IF EXISTS p4; +DROP PROCEDURE IF EXISTS p5; +DROP PROCEDURE IF EXISTS p6; +SET @@sql_mode = 'traditional'; +CREATE PROCEDURE p1() +BEGIN +DECLARE v TINYINT DEFAULT 1e200; +SELECT v; +END| +CREATE PROCEDURE p2() +BEGIN +DECLARE v DECIMAL(5) DEFAULT 1e200; +SELECT v; +END| +CREATE PROCEDURE p3() +BEGIN +DECLARE v CHAR(5) DEFAULT 'abcdef'; +SELECT v LIKE 'abc___'; +END| +CREATE PROCEDURE p4(arg VARCHAR(2)) +BEGIN +DECLARE var VARCHAR(1); +SET var := arg; +SELECT arg, var; +END| +CREATE PROCEDURE p5(arg CHAR(2)) +BEGIN +DECLARE var CHAR(1); +SET var := arg; +SELECT arg, var; +END| +CREATE PROCEDURE p6(arg DECIMAL(2)) +BEGIN +DECLARE var DECIMAL(1); +SET var := arg; +SELECT arg, var; +END| +CALL p1(); +ERROR 22003: Out of range value adjusted for column 'v' at row 1 +CALL p2(); +ERROR 22003: Out of range value adjusted for column 'v' at row 1 +CALL p3(); +ERROR 22001: Data too long for column 'v' at row 1 +CALL p4('aaa'); +ERROR 22001: Data too long for column 'arg' at row 1 +CALL p5('aa'); +ERROR 22001: Data too long for column 'var' at row 1 +CALL p6(10); +ERROR 22003: Out of range value adjusted for column 'var' at row 1 +SET @@sql_mode = 'ansi'; +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; +DROP PROCEDURE p4; +DROP PROCEDURE p5; +DROP PROCEDURE p6; + +--------------------------------------------------------------- +BUG#9078 +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +CREATE PROCEDURE p1 (arg DECIMAL(64,2)) +BEGIN +DECLARE var DECIMAL(64,2); +SET var = arg; +SELECT var; +END| +CALL p1(1929); +var +1929.00 +CALL p1(1929.00); +var +1929.00 +CALL p1(1929.003); +var +1929.00 +Warnings: +Note 1265 Data truncated for column 'arg' at row 1 +DROP PROCEDURE p1; + +--------------------------------------------------------------- +BUG#8768 +--------------------------------------------------------------- + +DROP FUNCTION IF EXISTS f1; +CREATE FUNCTION f1(arg TINYINT UNSIGNED) RETURNS TINYINT +BEGIN +RETURN arg; +END| +SELECT f1(-2500); +f1(-2500) +0 +Warnings: +Warning 1264 Out of range value adjusted for column 'arg' at row 1 +SET @@sql_mode = 'traditional'; +SELECT f1(-2500); +ERROR 22003: Out of range value adjusted for column 'arg' at row 1 +DROP FUNCTION f1; +CREATE FUNCTION f1(arg TINYINT UNSIGNED) RETURNS TINYINT +BEGIN +RETURN arg; +END| +SELECT f1(-2500); +ERROR 22003: Out of range value adjusted for column 'arg' at row 1 +SET @@sql_mode = 'ansi'; +DROP FUNCTION f1; + +--------------------------------------------------------------- +BUG#8769 +--------------------------------------------------------------- + +DROP FUNCTION IF EXISTS f1; +CREATE FUNCTION f1(arg MEDIUMINT) RETURNS MEDIUMINT +BEGIN +RETURN arg; +END| +SELECT f1(8388699); +f1(8388699) +8388607 +Warnings: +Warning 1264 Out of range value adjusted for column 'arg' at row 1 +SET @@sql_mode = 'traditional'; +SELECT f1(8388699); +ERROR 22003: Out of range value adjusted for column 'arg' at row 1 +DROP FUNCTION f1; +CREATE FUNCTION f1(arg MEDIUMINT) RETURNS MEDIUMINT +BEGIN +RETURN arg; +END| +SELECT f1(8388699); +ERROR 22003: Out of range value adjusted for column 'arg' at row 1 +SET @@sql_mode = 'ansi'; +DROP FUNCTION f1; + +--------------------------------------------------------------- +BUG#8702 +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(col VARCHAR(255)); +INSERT INTO t1(col) VALUES('Hello, world!'); +CREATE PROCEDURE p1() +BEGIN +DECLARE sp_var INTEGER; +SELECT col INTO sp_var FROM t1 LIMIT 1; +SET @user_var = sp_var; +SELECT sp_var; +SELECT @user_var; +END| +CALL p1(); +sp_var +0 +@user_var +0 +Warnings: +Warning 1264 Out of range value adjusted for column 'sp_var' at row 1 +DROP PROCEDURE p1; +DROP TABLE t1; + +--------------------------------------------------------------- +BUG#12903 +--------------------------------------------------------------- + +DROP FUNCTION IF EXISTS f1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(txt VARCHAR(255)); +CREATE FUNCTION f1(arg VARCHAR(255)) RETURNS VARCHAR(255) +BEGIN +DECLARE v1 VARCHAR(255); +DECLARE v2 VARCHAR(255); +SET v1 = CONCAT(LOWER(arg), UPPER(arg)); +SET v2 = CONCAT(LOWER(v1), UPPER(v1)); +INSERT INTO t1 VALUES(v1), (v2); +RETURN CONCAT(LOWER(arg), UPPER(arg)); +END| +SELECT f1('_aBcDe_'); +f1('_aBcDe_') +_abcde__ABCDE_ +SELECT * FROM t1; +txt +_abcde__ABCDE_ +_abcde__abcde__ABCDE__ABCDE_ +DROP FUNCTION f1; +DROP TABLE t1; + +--------------------------------------------------------------- +BUG#13808 +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP FUNCTION IF EXISTS f1; +CREATE PROCEDURE p1(arg ENUM('a', 'b')) +BEGIN +SELECT arg; +END| +CREATE PROCEDURE p2(arg ENUM('a', 'b')) +BEGIN +DECLARE var ENUM('c', 'd') DEFAULT arg; +SELECT arg, var; +END| +CREATE FUNCTION f1(arg ENUM('a', 'b')) RETURNS ENUM('c', 'd') +BEGIN +RETURN arg; +END| +CALL p1('c'); +arg + +Warnings: +Warning 1265 Data truncated for column 'arg' at row 1 +CALL p2('a'); +arg var +a +Warnings: +Warning 1265 Data truncated for column 'var' at row 1 +SELECT f1('a'); +f1('a') + +Warnings: +Warning 1265 Data truncated for column 'f1('a')' at row 1 +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP FUNCTION f1; + +--------------------------------------------------------------- +BUG#13909 +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +CREATE PROCEDURE p1(arg VARCHAR(255)) +BEGIN +SELECT CHARSET(arg); +END| +CREATE PROCEDURE p2(arg VARCHAR(255) CHARACTER SET UTF8) +BEGIN +SELECT CHARSET(arg); +END| +CALL p1('t'); +CHARSET(arg) +latin1 +CALL p1(_UTF8 't'); +CHARSET(arg) +latin1 +CALL p2('t'); +CHARSET(arg) +utf8 +CALL p2(_LATIN1 't'); +CHARSET(arg) +utf8 +DROP PROCEDURE p1; +DROP PROCEDURE p2; + +--------------------------------------------------------------- +BUG#14188 +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +CREATE PROCEDURE p1(arg1 BINARY(2), arg2 VARBINARY(2)) +BEGIN +DECLARE var1 BINARY(2) DEFAULT 0x41; +DECLARE var2 VARBINARY(2) DEFAULT 0x42; +SELECT HEX(arg1), HEX(arg2); +SELECT HEX(var1), HEX(var2); +END| +CALL p1(0x41, 0x42); +HEX(arg1) HEX(arg2) +4100 42 +HEX(var1) HEX(var2) +4100 42 +DROP PROCEDURE p1; + +--------------------------------------------------------------- +BUG#15148 +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(col1 TINYINT, col2 TINYINT); +INSERT INTO t1 VALUES(1, 2), (11, 12); +CREATE PROCEDURE p1(arg TINYINT) +BEGIN +SELECT arg; +END| +CALL p1((1, 2)); +ERROR 21000: Operand should contain 1 column(s) +CALL p1((SELECT * FROM t1 LIMIT 1)); +ERROR 21000: Operand should contain 1 column(s) +CALL p1((SELECT col1, col2 FROM t1 LIMIT 1)); +ERROR 21000: Operand should contain 1 column(s) +DROP PROCEDURE p1; +DROP TABLE t1; + +--------------------------------------------------------------- +BUG#13613 +--------------------------------------------------------------- + +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +CREATE PROCEDURE p1(x VARCHAR(50)) +BEGIN +SET x = SUBSTRING(x, 1, 3); +SELECT x; +END| +CREATE FUNCTION f1(x VARCHAR(50)) RETURNS VARCHAR(50) +BEGIN +RETURN SUBSTRING(x, 1, 3); +END| +CALL p1('abcdef'); +x +abc +SELECT f1('ABCDEF'); +f1('ABCDEF') +ABC +DROP PROCEDURE p1; +DROP FUNCTION f1; + +--------------------------------------------------------------- +BUG#13665 +--------------------------------------------------------------- + +DROP FUNCTION IF EXISTS f1; +CREATE FUNCTION f1() RETURNS VARCHAR(20000) +BEGIN +DECLARE var VARCHAR(2000); +SET var = ''; +SET var = CONCAT(var, 'abc'); +SET var = CONCAT(var, ''); +RETURN var; +END| +SELECT f1(); +f1() +abc +DROP FUNCTION f1; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index f91aadc02b6..ded9754f172 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -248,13 +248,13 @@ return i+1| call sub1("sub1a", (select 7))| call sub1("sub1b", (select max(i) from t2))| call sub1("sub1c", (select i,d from t2 limit 1))| +ERROR 21000: Operand should contain 1 column(s) call sub1("sub1d", (select 1 from (select 1) a))| call sub2("sub2")| select * from t1| id data sub1a 7 sub1b 3 -sub1c 1 sub1d 1 sub2 6 select sub3((select max(i) from t2))| @@ -988,6 +988,10 @@ end| select f5(1)| f5(1) 1 +select f5(2)| +ERROR HY000: Recursive stored functions and triggers are not allowed. +select f5(3)| +ERROR HY000: Recursive stored functions and triggers are not allowed. create function f6() returns int begin declare n int; @@ -1032,9 +1036,15 @@ a f8() 3 1 drop function f1| select * from v1| -ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them create function f1() returns int return (select sum(data) from t1) + (select sum(data) from v1)| +select f1()| +ERROR HY000: Recursive stored functions and triggers are not allowed. +select * from v1| +ERROR HY000: Recursive stored functions and triggers are not allowed. +select * from v2| +ERROR HY000: Recursive stored functions and triggers are not allowed. drop function f1| create function f1() returns int return (select sum(data) from t1)| @@ -1053,7 +1063,7 @@ f0() select *, f0() from v0| f0() f0() 100 100 -lock tables t1 read, t1 as t11 read, mysql.proc read| +lock tables t1 read, t1 as t11 read| select f3()| f3() 1 @@ -1251,6 +1261,62 @@ drop procedure opp| drop procedure ip| show procedure status like '%p%'| Db Name Type Definer Modified Created Security_type Comment +drop table if exists fib| +create table fib ( f bigint unsigned not null )| +drop procedure if exists fib| +create procedure fib(n int unsigned) +begin +if n > 1 then +begin +declare x, y bigint unsigned; +declare c cursor for select f from fib order by f desc limit 2; +open c; +fetch c into y; +fetch c into x; +close c; +insert into fib values (x+y); +call fib(n-1); +end; +end if; +end| +set @@max_sp_recursion_depth= 20| +insert into fib values (0), (1)| +call fib(3)| +select * from fib order by f asc| +f +0 +1 +1 +2 +delete from fib| +insert into fib values (0), (1)| +call fib(20)| +select * from fib order by f asc| +f +0 +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +89 +144 +233 +377 +610 +987 +1597 +2584 +4181 +6765 +drop table fib| +drop procedure fib| +set @@max_sp_recursion_depth= 0| drop procedure if exists bar| create procedure bar(x char(16), y int) comment "111111111111" sql security invoker @@ -1479,6 +1545,52 @@ select @x2| @x2 2 drop procedure bug2260| +drop procedure if exists bug2267_1| +create procedure bug2267_1() +begin +show procedure status; +end| +drop procedure if exists bug2267_2| +create procedure bug2267_2() +begin +show function status; +end| +drop procedure if exists bug2267_3| +create procedure bug2267_3() +begin +show create procedure bug2267_1; +end| +drop procedure if exists bug2267_4| +drop function if exists bug2267_4| +create procedure bug2267_4() +begin +show create function bug2267_4; +end| +create function bug2267_4() returns int return 100| +call bug2267_1()| +Db Name Type Definer Modified Created Security_type Comment +test bug2267_1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +test bug2267_2 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +test bug2267_3 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +test bug2267_4 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +call bug2267_2()| +Db Name Type Definer Modified Created Security_type Comment +test bug2267_4 FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +call bug2267_3()| +Procedure sql_mode Create Procedure +bug2267_1 CREATE PROCEDURE `bug2267_1`() +begin +show procedure status; +end +call bug2267_4()| +Function sql_mode Create Function +bug2267_4 CREATE FUNCTION `bug2267_4`() RETURNS int(11) +return 100 +drop procedure bug2267_1| +drop procedure bug2267_2| +drop procedure bug2267_3| +drop procedure bug2267_4| +drop function bug2267_4| drop procedure if exists bug2227| create procedure bug2227(x int) begin @@ -1490,6 +1602,18 @@ call bug2227(9)| 1.3 x y 42 z 1.3 9 2.6 42 zzz drop procedure bug2227| +drop procedure if exists bug2614| +create procedure bug2614() +begin +drop table if exists t3; +create table t3 (id int default '0' not null); +insert into t3 select 12; +insert into t3 select * from t3; +end| +call bug2614()| +call bug2614()| +drop table t3| +drop procedure bug2614| drop function if exists bug2674| create function bug2674() returns int return @@sort_buffer_size| @@ -2562,7 +2686,7 @@ call bug8937()| s x y z 16 3 1 6 a -3.2000 +3.2 drop procedure bug8937| delete from t1| drop procedure if exists bug6900| @@ -2766,21 +2890,30 @@ create function bug9775(v1 char(1)) returns enum('a','b') return v1| select bug9775('a'),bug9775('b'),bug9775('c')| bug9775('a') bug9775('b') bug9775('c') a b +Warnings: +Warning 1265 Data truncated for column 'bug9775('c')' at row 1 drop function bug9775| create function bug9775(v1 int) returns enum('a','b') return v1| select bug9775(1),bug9775(2),bug9775(3)| bug9775(1) bug9775(2) bug9775(3) a b +Warnings: +Warning 1265 Data truncated for column 'bug9775(3)' at row 1 drop function bug9775| create function bug9775(v1 char(1)) returns set('a','b') return v1| select bug9775('a'),bug9775('b'),bug9775('a,b'),bug9775('c')| bug9775('a') bug9775('b') bug9775('a,b') bug9775('c') -a b a,b +a b a +Warnings: +Warning 1265 Data truncated for column 'v1' at row 1 +Warning 1265 Data truncated for column 'bug9775('c')' at row 1 drop function bug9775| create function bug9775(v1 int) returns set('a','b') return v1| select bug9775(1),bug9775(2),bug9775(3),bug9775(4)| bug9775(1) bug9775(2) bug9775(3) bug9775(4) a b a,b +Warnings: +Warning 1265 Data truncated for column 'bug9775(4)' at row 1 drop function bug9775| drop function if exists bug8861| create function bug8861(v1 int) returns year return v1| @@ -2803,12 +2936,10 @@ create procedure bug9004_2(x char(16)) call bug9004_1(x)| call bug9004_1('12345678901234567')| Warnings: -Warning 1265 Data truncated for column 'id' at row 1 -Warning 1265 Data truncated for column 'id' at row 2 +Warning 1265 Data truncated for column 'x' at row 1 call bug9004_2('12345678901234567890')| Warnings: -Warning 1265 Data truncated for column 'id' at row 1 -Warning 1265 Data truncated for column 'id' at row 2 +Warning 1265 Data truncated for column 'x' at row 1 delete from t1| drop procedure bug9004_1| drop procedure bug9004_2| @@ -3403,20 +3534,24 @@ end| call bug12589_1()| Table Create Table tm1 CREATE TEMPORARY TABLE `tm1` ( - `spv1` decimal(1,0) unsigned default NULL + `spv1` decimal(3,3) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 Warnings: -Warning 1292 Truncated incorrect DECIMAL value: 'test' +Warning 1264 Out of range value adjusted for column 'spv1' at row 1 +Warning 1366 Incorrect decimal value: 'test' for column 'spv1' at row 1 call bug12589_2()| Table Create Table tm1 CREATE TEMPORARY TABLE `tm1` ( - `spv1` decimal(6,3) unsigned default NULL + `spv1` decimal(6,3) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 call bug12589_3()| Table Create Table tm1 CREATE TEMPORARY TABLE `tm1` ( `spv1` decimal(6,3) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop procedure bug12589_1| +drop procedure bug12589_2| +drop procedure bug12589_3| drop table if exists t3| drop procedure if exists bug7049_1| drop procedure if exists bug7049_2| @@ -3575,4 +3710,614 @@ DROP VIEW bug13095_v1 DROP PROCEDURE IF EXISTS bug13095; DROP VIEW IF EXISTS bug13095_v1; DROP TABLE IF EXISTS bug13095_t1; +drop procedure if exists bug14210| +set @@session.max_heap_table_size=16384| +select @@session.max_heap_table_size| +@@session.max_heap_table_size +16384 +create table t3 (a char(255)) engine=InnoDB| +create procedure bug14210_fill_table() +begin +declare table_size, max_table_size int default 0; +select @@session.max_heap_table_size into max_table_size; +delete from t3; +insert into t3 (a) values (repeat('a', 255)); +repeat +insert into t3 select a from t3; +select count(*)*255 from t3 into table_size; +until table_size > max_table_size*2 end repeat; +end| +call bug14210_fill_table()| +drop procedure bug14210_fill_table| +create table t4 like t3| +create procedure bug14210() +begin +declare a char(255); +declare done int default 0; +declare c cursor for select * from t3; +declare continue handler for sqlstate '02000' set done = 1; +open c; +repeat +fetch c into a; +if not done then +insert into t4 values (upper(a)); +end if; +until done end repeat; +close c; +end| +call bug14210()| +select count(*) from t4| +count(*) +256 +drop table t3, t4| +drop procedure bug14210| +set @@session.max_heap_table_size=default| +drop function if exists bug14723| +drop procedure if exists bug14723| +/*!50003 create function bug14723() +returns bigint(20) +main_loop: begin +return 42; +end */;; +show create function bug14723;; +Function sql_mode Create Function +bug14723 CREATE FUNCTION `bug14723`() RETURNS bigint(20) +main_loop: begin +return 42; +end +select bug14723();; +bug14723() +42 +/*!50003 create procedure bug14723() +main_loop: begin +select 42; +end */;; +show create procedure bug14723;; +Procedure sql_mode Create Procedure +bug14723 CREATE PROCEDURE `bug14723`() +main_loop: begin +select 42; +end +call bug14723();; +42 +42 +drop function bug14723| +drop procedure bug14723| +create procedure bug14845() +begin +declare a char(255); +declare done int default 0; +declare c cursor for select count(*) from t1 where 1 = 0; +declare continue handler for sqlstate '02000' set done = 1; +open c; +repeat +fetch c into a; +if not done then +select a; +end if; +until done end repeat; +close c; +end| +call bug14845()| +a +0 +drop procedure bug14845| +drop procedure if exists bug13549_1| +drop procedure if exists bug13549_2| +CREATE PROCEDURE `bug13549_2`() +begin +call bug13549_1(); +end| +CREATE PROCEDURE `bug13549_1`() +begin +declare done int default 0; +set done= not done; +end| +CALL bug13549_2()| +drop procedure bug13549_2| +drop procedure bug13549_1| +drop function if exists bug10100f| +drop procedure if exists bug10100p| +drop procedure if exists bug10100t| +drop procedure if exists bug10100pt| +drop procedure if exists bug10100pv| +drop procedure if exists bug10100pd| +drop procedure if exists bug10100pc| +create function bug10100f(prm int) returns int +begin +if prm > 1 then +return prm * bug10100f(prm - 1); +end if; +return 1; +end| +create procedure bug10100p(prm int, inout res int) +begin +set res = res * prm; +if prm > 1 then +call bug10100p(prm - 1, res); +end if; +end| +create procedure bug10100t(prm int) +begin +declare res int; +set res = 1; +call bug10100p(prm, res); +select res; +end| +create table t3 (a int)| +insert into t3 values (0)| +create view v1 as select a from t3; +create procedure bug10100pt(level int, lim int) +begin +if level < lim then +update t3 set a=level; +FLUSH TABLES; +call bug10100pt(level+1, lim); +else +select * from t3; +end if; +end| +create procedure bug10100pv(level int, lim int) +begin +if level < lim then +update v1 set a=level; +FLUSH TABLES; +call bug10100pv(level+1, lim); +else +select * from v1; +end if; +end| +prepare stmt2 from "select * from t3;"; +create procedure bug10100pd(level int, lim int) +begin +if level < lim then +select level; +prepare stmt1 from "update t3 set a=a+2"; +execute stmt1; +FLUSH TABLES; +execute stmt1; +FLUSH TABLES; +execute stmt1; +FLUSH TABLES; +deallocate prepare stmt1; +execute stmt2; +select * from t3; +call bug10100pd(level+1, lim); +else +execute stmt2; +end if; +end| +create procedure bug10100pc(level int, lim int) +begin +declare lv int; +declare c cursor for select a from t3; +open c; +if level < lim then +select level; +fetch c into lv; +select lv; +update t3 set a=level+lv; +FLUSH TABLES; +call bug10100pc(level+1, lim); +else +select * from t3; +end if; +close c; +end| +set @@max_sp_recursion_depth=4| +select @@max_sp_recursion_depth| +@@max_sp_recursion_depth +4 +select bug10100f(3)| +ERROR HY000: Recursive stored functions and triggers are not allowed. +select bug10100f(6)| +ERROR HY000: Recursive stored functions and triggers are not allowed. +call bug10100t(5)| +res +120 +call bug10100pt(1,5)| +a +4 +call bug10100pv(1,5)| +a +4 +update t3 set a=1| +call bug10100pd(1,5)| +level +1 +a +7 +a +7 +level +2 +a +13 +a +13 +level +3 +a +19 +a +19 +level +4 +a +25 +a +25 +a +25 +select * from t3| +a +25 +update t3 set a=1| +call bug10100pc(1,5)| +level +1 +lv +1 +level +2 +lv +2 +level +3 +lv +4 +level +4 +lv +7 +a +11 +select * from t3| +a +11 +set @@max_sp_recursion_depth=0| +select @@max_sp_recursion_depth| +@@max_sp_recursion_depth +0 +select bug10100f(5)| +ERROR HY000: Recursive stored functions and triggers are not allowed. +call bug10100t(5)| +ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine bug10100p +set @@max_sp_recursion_depth=255| +set @var=1| +call bug10100p(255, @var)| +call bug10100pt(1,255)| +call bug10100pv(1,255)| +call bug10100pd(1,255)| +call bug10100pc(1,255)| +set @@max_sp_recursion_depth=0| +deallocate prepare stmt2| +drop function bug10100f| +drop procedure bug10100p| +drop procedure bug10100t| +drop procedure bug10100pt| +drop procedure bug10100pv| +drop procedure bug10100pd| +drop procedure bug10100pc| +drop view v1| +drop procedure if exists bug13729| +drop table if exists t3| +create table t3 (s1 int, primary key (s1))| +insert into t3 values (1),(2)| +create procedure bug13729() +begin +declare continue handler for sqlexception select 55; +update t3 set s1 = 1; +end| +call bug13729()| +55 +55 +select * from t3| +s1 +1 +2 +drop procedure bug13729| +drop table t3| +drop procedure if exists bug14643_1| +drop procedure if exists bug14643_2| +create procedure bug14643_1() +begin +declare continue handler for sqlexception select 'boo' as 'Handler'; +begin +declare v int default undefined_var; +if v = 1 then +select 1; +else +select v, isnull(v); +end if; +end; +end| +create procedure bug14643_2() +begin +declare continue handler for sqlexception select 'boo' as 'Handler'; +case undefined_var +when 1 then +select 1; +else +select 2; +end case; +select undefined_var; +end| +call bug14643_1()| +Handler +boo +v isnull(v) +NULL 1 +call bug14643_2()| +Handler +boo +2 +2 +Handler +boo +drop procedure bug14643_1| +drop procedure bug14643_2| +drop procedure if exists bug14304| +drop table if exists t3, t4| +create table t3(a int primary key auto_increment)| +create table t4(a int primary key auto_increment)| +create procedure bug14304() +begin +insert into t3 set a=null; +insert into t4 set a=null; +insert into t4 set a=null; +insert into t4 set a=null; +insert into t4 set a=null; +insert into t4 set a=null; +insert into t4 select null as a; +insert into t3 set a=null; +insert into t3 set a=null; +select * from t3; +end| +call bug14304()| +a +1 +2 +3 +drop procedure bug14304| +drop table t3, t4| +drop procedure if exists bug14376| +create procedure bug14376() +begin +declare x int default x; +end| +call bug14376()| +ERROR 42S22: Unknown column 'x' in 'field list' +drop procedure bug14376| +create procedure bug14376() +begin +declare x int default 42; +begin +declare x int default x; +select x; +end; +end| +call bug14376()| +x +42 +drop procedure bug14376| +create procedure bug14376(x int) +begin +declare x int default x; +select x; +end| +call bug14376(4711)| +x +4711 +drop procedure bug14376| +drop procedure if exists bug5967| +drop table if exists t3| +create table t3 (a varchar(255))| +insert into t3 (a) values ("a - table column")| +create procedure bug5967(a varchar(255)) +begin +declare i varchar(255); +declare c cursor for select a from t3; +select a; +select a from t3 into i; +select i as 'Parameter takes precedence over table column'; open c; +fetch c into i; +close c; +select i as 'Parameter takes precedence over table column in cursors'; +begin +declare a varchar(255) default 'a - local variable'; +declare c1 cursor for select a from t3; +select a as 'A local variable takes precedence over parameter'; +open c1; +fetch c1 into i; +close c1; +select i as 'A local variable takes precedence over parameter in cursors'; +begin +declare a varchar(255) default 'a - local variable in a nested compound statement'; +declare c2 cursor for select a from t3; +select a as 'A local variable in a nested compound statement takes precedence over a local variable in the outer statement'; +select a from t3 into i; +select i as 'A local variable in a nested compound statement takes precedence over table column'; +open c2; +fetch c2 into i; +close c2; +select i as 'A local variable in a nested compound statement takes precedence over table column in cursors'; +end; +end; +end| +call bug5967("a - stored procedure parameter")| +a +a - stored procedure parameter +Parameter takes precedence over table column +a - stored procedure parameter +Parameter takes precedence over table column in cursors +a - stored procedure parameter +A local variable takes precedence over parameter +a - local variable +A local variable takes precedence over parameter in cursors +a - local variable +A local variable in a nested compound statement takes precedence over a local variable in the outer statement +a - local variable in a nested compound statement +A local variable in a nested compound statement takes precedence over table column +a - local variable in a nested compound statement +A local variable in a nested compound statement takes precedence over table column in cursors +a - local variable in a nested compound statement +drop procedure bug5967| +drop procedure if exists bug13012| +create procedure bug13012() +BEGIN +REPAIR TABLE t1; +BACKUP TABLE t1 to '../tmp'; +DROP TABLE t1; +RESTORE TABLE t1 FROM '../tmp'; +END| +call bug13012()| +Table Op Msg_type Msg_text +test.t1 repair status OK +Table Op Msg_type Msg_text +test.t1 backup status OK +Table Op Msg_type Msg_text +test.t1 restore status OK +drop procedure bug13012| +create view v1 as select * from t1| +create procedure bug13012() +BEGIN +REPAIR TABLE t1,t2,t3,v1; +OPTIMIZE TABLE t1,t2,t3,v1; +ANALYZE TABLE t1,t2,t3,v1; +END| +call bug13012()| +Table Op Msg_type Msg_text +test.t1 repair status OK +test.t2 repair status OK +test.t3 repair status OK +test.v1 repair error 'test.v1' is not BASE TABLE +Table Op Msg_type Msg_text +test.t1 optimize status OK +test.t2 optimize status OK +test.t3 optimize status OK +test.v1 optimize error 'test.v1' is not BASE TABLE +Table Op Msg_type Msg_text +test.t1 analyze status Table is already up to date +test.t2 analyze status Table is already up to date +test.t3 analyze status Table is already up to date +test.v1 analyze error 'test.v1' is not BASE TABLE +Warnings: +Error 1347 'test.v1' is not BASE TABLE +call bug13012()| +Table Op Msg_type Msg_text +test.t1 repair status OK +test.t2 repair status OK +test.t3 repair status OK +test.v1 repair error 'test.v1' is not BASE TABLE +Table Op Msg_type Msg_text +test.t1 optimize status OK +test.t2 optimize status OK +test.t3 optimize status OK +test.v1 optimize error 'test.v1' is not BASE TABLE +Table Op Msg_type Msg_text +test.t1 analyze status Table is already up to date +test.t2 analyze status Table is already up to date +test.t3 analyze status Table is already up to date +test.v1 analyze error 'test.v1' is not BASE TABLE +Warnings: +Error 1347 'test.v1' is not BASE TABLE +call bug13012()| +Table Op Msg_type Msg_text +test.t1 repair status OK +test.t2 repair status OK +test.t3 repair status OK +test.v1 repair error 'test.v1' is not BASE TABLE +Table Op Msg_type Msg_text +test.t1 optimize status OK +test.t2 optimize status OK +test.t3 optimize status OK +test.v1 optimize error 'test.v1' is not BASE TABLE +Table Op Msg_type Msg_text +test.t1 analyze status Table is already up to date +test.t2 analyze status Table is already up to date +test.t3 analyze status Table is already up to date +test.v1 analyze error 'test.v1' is not BASE TABLE +Warnings: +Error 1347 'test.v1' is not BASE TABLE +drop procedure bug13012| +drop view v1; +select * from t1| +id data +aa 0 +aa 1 +aa 2 +aa 3 +aa 4 +aa 5 +aa 6 +aa 7 +aa 8 +aa 9 +drop schema if exists mysqltest1| +Warnings: +Note 1008 Can't drop database 'mysqltest1'; database doesn't exist +drop schema if exists mysqltest2| +Warnings: +Note 1008 Can't drop database 'mysqltest2'; database doesn't exist +drop schema if exists mysqltest3| +Warnings: +Note 1008 Can't drop database 'mysqltest3'; database doesn't exist +create schema mysqltest1| +create schema mysqltest2| +create schema mysqltest3| +use mysqltest3| +create procedure mysqltest1.p1 (out prequestid varchar(100)) +begin +call mysqltest2.p2('call mysqltest3.p3(1, 2)'); +end| +create procedure mysqltest2.p2(in psql text) +begin +declare lsql text; +set @lsql= psql; +prepare lstatement from @lsql; +execute lstatement; +deallocate prepare lstatement; +end| +create procedure mysqltest3.p3(in p1 int) +begin +select p1; +end| +call mysqltest1.p1(@rs)| +ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2 +call mysqltest1.p1(@rs)| +ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2 +call mysqltest1.p1(@rs)| +ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2 +drop schema if exists mysqltest1| +drop schema if exists mysqltest2| +drop schema if exists mysqltest3| +use test| +drop table if exists t3| +drop procedure if exists bug15441| +create table t3 (id int not null primary key, county varchar(25))| +insert into t3 (id, county) values (1, 'York')| +create procedure bug15441(c varchar(25)) +begin +update t3 set id=2, county=values(c); +end| +call bug15441('county')| +ERROR 42S22: Unknown column 'c' in 'field list' +drop procedure bug15441| +create procedure bug15441(county varchar(25)) +begin +declare c varchar(25) default "hello"; +insert into t3 (id, county) values (1, county) +on duplicate key update county= values(county); +select * from t3; +update t3 set id=2, county=values(id); +select * from t3; +end| +call bug15441('Yale')| +id county +1 Yale +id county +2 NULL +drop table t3| +drop procedure bug15441| drop table t1,t2; diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result index 6077087ab87..8f2bd9985fc 100644 --- a/mysql-test/r/sp_trans.result +++ b/mysql-test/r/sp_trans.result @@ -174,3 +174,254 @@ ERROR HY000: Explicit or implicit commit is not allowed in stored function or tr drop procedure bug10015_8| drop function bug10015_7| drop table t1, t2| +drop function if exists bug13825_0| +drop function if exists bug13825_1| +drop function if exists bug13825_2| +drop function if exists bug13825_3| +drop function if exists bug13825_4| +drop function if exists bug13825_5| +drop procedure if exists bug13825_0| +drop procedure if exists bug13825_1| +drop procedure if exists bug13825_2| +drop table if exists t1| +create table t1 (i int) engine=innodb| +create table t2 (i int) engine=innodb| +create function bug13825_0() returns int +begin +rollback to savepoint x; +return 1; +end| +create function bug13825_1() returns int +begin +release savepoint x; +return 1; +end| +create function bug13825_2() returns int +begin +insert into t1 values (2); +savepoint x; +insert into t1 values (3); +rollback to savepoint x; +insert into t1 values (4); +return 1; +end| +create procedure bug13825_0() +begin +rollback to savepoint x; +end| +create procedure bug13825_1() +begin +release savepoint x; +end| +create procedure bug13825_2() +begin +savepoint x; +end| +insert into t2 values (1)| +create trigger t2_bi before insert on t2 for each row +rollback to savepoint x| +create trigger t2_bu before update on t2 for each row +release savepoint x| +create trigger t2_bd before delete on t2 for each row +begin +insert into t1 values (2); +savepoint x; +insert into t1 values (3); +rollback to savepoint x; +insert into t1 values (4); +end| +create function bug13825_3(rb int) returns int +begin +insert into t1 values(1); +savepoint x; +insert into t1 values(2); +if rb then +rollback to savepoint x; +end if; +insert into t1 values(3); +return rb; +end| +create function bug13825_4() returns int +begin +savepoint x; +insert into t1 values(2); +rollback to savepoint x; +return 0; +end| +create function bug13825_5(p int) returns int +begin +savepoint x; +insert into t2 values(p); +rollback to savepoint x; +insert into t2 values(p+1); +return p; +end| +set autocommit= 0| +begin | +insert into t1 values (1)| +savepoint x| +set @a:= bug13825_0()| +ERROR 42000: SAVEPOINT x does not exist +insert into t2 values (2)| +ERROR 42000: SAVEPOINT x does not exist +set @a:= bug13825_1()| +ERROR 42000: SAVEPOINT x does not exist +update t2 set i = 2| +ERROR 42000: SAVEPOINT x does not exist +set @a:= bug13825_2()| +select * from t1| +i +1 +2 +4 +rollback to savepoint x| +select * from t1| +i +1 +delete from t2| +select * from t1| +i +1 +2 +4 +rollback to savepoint x| +select * from t1| +i +1 +release savepoint x| +set @a:= bug13825_2()| +select * from t1| +i +1 +2 +4 +rollback to savepoint x| +ERROR 42000: SAVEPOINT x does not exist +delete from t1| +commit| +begin| +insert into t1 values (5)| +savepoint x| +insert into t1 values (6)| +call bug13825_0()| +select * from t1| +i +5 +call bug13825_1()| +rollback to savepoint x| +ERROR 42000: SAVEPOINT x does not exist +savepoint x| +insert into t1 values (7)| +call bug13825_2()| +rollback to savepoint x| +select * from t1| +i +5 +7 +delete from t1| +commit| +set autocommit= 1| +select bug13825_3(0)| +bug13825_3(0) +0 +select * from t1| +i +1 +2 +3 +delete from t1| +select bug13825_3(1)| +bug13825_3(1) +1 +select * from t1| +i +1 +3 +delete from t1| +set autocommit= 0| +begin| +insert into t1 values (1)| +set @a:= bug13825_4()| +select * from t1| +i +1 +delete from t1| +commit| +set autocommit= 1| +drop table t2| +create table t2 (i int) engine=innodb| +insert into t1 values (1), (bug13825_5(2)), (3)| +select * from t1| +i +1 +2 +3 +select * from t2| +i +3 +drop function bug13825_0| +drop function bug13825_1| +drop function bug13825_2| +drop function bug13825_3| +drop function bug13825_4| +drop function bug13825_5| +drop procedure bug13825_0| +drop procedure bug13825_1| +drop procedure bug13825_2| +drop table t1, t2| +drop table if exists t3| +drop procedure if exists bug14840_1| +drop procedure if exists bug14840_2| +create table t3 +( +x int, +y int, +primary key (x) +) engine=InnoDB| +create procedure bug14840_1() +begin +declare err int default 0; +declare continue handler for sqlexception +set err = err + 1; +start transaction; +update t3 set x = 1, y = 42 where x = 2; +insert into t3 values (3, 4711); +if err > 0 then +rollback; +else +commit; +end if; +select * from t3; +end| +create procedure bug14840_2() +begin +declare err int default 0; +declare continue handler for sqlexception +begin +set err = err + 1; +select err as 'Ping'; +end; +update t3 set x = 1, y = 42 where x = 2; +update t3 set x = 1, y = 42 where x = 2; +insert into t3 values (3, 4711); +select * from t3; +end| +insert into t3 values (1, 3), (2, 5)| +call bug14840_1()| +x y +1 3 +2 5 +delete from t3| +insert into t3 values (1, 3), (2, 5)| +call bug14840_2()| +Ping +1 +Ping +2 +x y +1 3 +2 5 +3 4711 +drop procedure bug14840_1| +drop procedure bug14840_2| +drop table t3| diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index 83099623e23..7d9d7fb333c 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -1,4 +1,5 @@ -drop table if exists t1; +drop table if exists t1,t2,v1,v2; +drop view if exists t1,t2,v1,v2; CREATE TABLE `t1` ( a int not null auto_increment, `pseudo` varchar(35) character set latin2 NOT NULL default '', diff --git a/mysql-test/r/ssl.result b/mysql-test/r/ssl.result new file mode 100644 index 00000000000..bb7297d6807 --- /dev/null +++ b/mysql-test/r/ssl.result @@ -0,0 +1,2159 @@ +SHOW STATUS LIKE 'Ssl_cipher'; +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA +drop table if exists t1,t2,t3,t4; +CREATE TABLE t1 ( +Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL +); +INSERT INTO t1 VALUES (9410,9412); +select period from t1; +period +9410 +select * from t1; +Period Varor_period +9410 9412 +select t1.* from t1; +Period Varor_period +9410 9412 +CREATE TABLE t2 ( +auto int not null auto_increment, +fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL, +companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL, +fld3 char(30) DEFAULT '' NOT NULL, +fld4 char(35) DEFAULT '' NOT NULL, +fld5 char(35) DEFAULT '' NOT NULL, +fld6 char(4) DEFAULT '' NOT NULL, +UNIQUE fld1 (fld1), +KEY fld3 (fld3), +PRIMARY KEY (auto) +); +select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%"; +fld3 +imaginable +select fld3 from t2 where fld3 like "%cultivation" ; +fld3 +cultivation +select t2.fld3,companynr from t2 where companynr = 57+1 order by fld3; +fld3 companynr +concoct 58 +druggists 58 +engrossing 58 +Eurydice 58 +exclaimers 58 +ferociousness 58 +hopelessness 58 +Huey 58 +imaginable 58 +judges 58 +merging 58 +ostrich 58 +peering 58 +Phelps 58 +presumes 58 +Ruth 58 +sentences 58 +Shylock 58 +straggled 58 +synergy 58 +thanking 58 +tying 58 +unlocks 58 +select fld3,companynr from t2 where companynr = 58 order by fld3; +fld3 companynr +concoct 58 +druggists 58 +engrossing 58 +Eurydice 58 +exclaimers 58 +ferociousness 58 +hopelessness 58 +Huey 58 +imaginable 58 +judges 58 +merging 58 +ostrich 58 +peering 58 +Phelps 58 +presumes 58 +Ruth 58 +sentences 58 +Shylock 58 +straggled 58 +synergy 58 +thanking 58 +tying 58 +unlocks 58 +select fld3 from t2 order by fld3 desc limit 10; +fld3 +youthfulness +yelped +Wotan +workers +Witt +witchcraft +Winsett +Willy +willed +wildcats +select fld3 from t2 order by fld3 desc limit 5; +fld3 +youthfulness +yelped +Wotan +workers +Witt +select fld3 from t2 order by fld3 desc limit 5,5; +fld3 +witchcraft +Winsett +Willy +willed +wildcats +select t2.fld3 from t2 where fld3 = 'honeysuckle'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'honeysuckl_'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'hon_ysuckl_'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'honeysuckle%'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'h%le'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'honeysuckle_'; +fld3 +select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%'; +fld3 +explain select t2.fld3 from t2 where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index +explain select fld3 from t2 ignore index (fld3) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select fld3 from t2 use index (fld1) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select fld3 from t2 use index (fld3) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index +explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index +explain select fld3 from t2 ignore index (fld3,not_used); +ERROR 42000: Key column 'not_used' doesn't exist in table +explain select fld3 from t2 use index (not_used); +ERROR 42000: Key column 'not_used' doesn't exist in table +select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3; +fld3 +honeysuckle +honoring +explain select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range fld3 fld3 30 NULL 2 Using where; Using index +select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3; +fld1 fld3 +148504 Colombo +068305 Colombo +000000 nondecreasing +select fld1,fld3 from t2 where companynr = 37 and fld3 = 'appendixes'; +fld1 fld3 +232605 appendixes +1232605 appendixes +1232606 appendixes +1232607 appendixes +1232608 appendixes +1232609 appendixes +select fld1 from t2 where fld1=250501 or fld1="250502"; +fld1 +250501 +250502 +explain select fld1 from t2 where fld1=250501 or fld1="250502"; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range fld1 fld1 4 NULL 2 Using where; Using index +select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502; +fld1 +250501 +250502 +250505 +250601 +explain select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range fld1 fld1 4 NULL 4 Using where; Using index +select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%'; +fld1 fld3 +218401 faithful +018007 fanatic +228311 fated +018017 featherweight +218022 feed +088303 feminine +058004 Fenton +038017 fetched +018054 fetters +208101 fiftieth +238007 filial +013606 fingerings +218008 finishers +038205 firearm +188505 fitting +202301 Fitzpatrick +238008 fixedly +012001 flanking +018103 flint +018104 flopping +188007 flurried +013602 foldout +226205 foothill +232102 forgivably +228306 forthcoming +186002 freakish +208113 freest +231315 freezes +036002 funereal +226209 furnishings +198006 furthermore +select fld3 from t2 where fld3 like "L%" and fld3 = "ok"; +fld3 +select fld3 from t2 where (fld3 like "C%" and fld3 = "Chantilly"); +fld3 +Chantilly +select fld1,fld3 from t2 where fld1 like "25050%"; +fld1 fld3 +250501 poisoning +250502 Iraqis +250503 heaving +250504 population +250505 bomb +select fld1,fld3 from t2 where fld1 like "25050_"; +fld1 fld3 +250501 poisoning +250502 Iraqis +250503 heaving +250504 population +250505 bomb +select distinct companynr from t2; +companynr +00 +37 +36 +50 +58 +29 +40 +53 +65 +41 +34 +68 +select distinct companynr from t2 order by companynr; +companynr +00 +29 +34 +36 +37 +40 +41 +50 +53 +58 +65 +68 +select distinct companynr from t2 order by companynr desc; +companynr +68 +65 +58 +53 +50 +41 +40 +37 +36 +34 +29 +00 +select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period +obliterates 9410 +offload 9410 +opaquely 9410 +organizer 9410 +overestimating 9410 +overlay 9410 +select distinct fld3 from t2 where companynr = 34 order by fld3; +fld3 +absentee +accessed +ahead +alphabetic +Asiaticizations +attitude +aye +bankruptcies +belays +Blythe +bomb +boulevard +bulldozes +cannot +caressing +charcoal +checksumming +chess +clubroom +colorful +cosy +creator +crying +Darius +diffusing +duality +Eiffel +Epiphany +Ernestine +explorers +exterminated +famine +forked +Gershwins +heaving +Hodges +Iraqis +Italianization +Lagos +landslide +libretto +Majorca +mastering +narrowed +occurred +offerers +Palestine +Peruvianizes +pharmaceutic +poisoning +population +Pygmalion +rats +realest +recording +regimented +retransmitting +reviver +rouses +scars +sicker +sleepwalk +stopped +sugars +translatable +uncles +unexpected +uprisings +versatility +vest +select distinct fld3 from t2 limit 10; +fld3 +abates +abiding +Abraham +abrogating +absentee +abut +accessed +accruing +accumulating +accuracies +select distinct fld3 from t2 having fld3 like "A%" limit 10; +fld3 +abates +abiding +Abraham +abrogating +absentee +abut +accessed +accruing +accumulating +accuracies +select distinct substring(fld3,1,3) from t2 where fld3 like "A%"; +substring(fld3,1,3) +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +Adl +adm +Ado +ads +adv +aer +aff +afi +afl +afo +agi +ahe +aim +air +Ald +alg +ali +all +alp +alr +ama +ame +amm +ana +and +ane +Ang +ani +Ann +Ant +api +app +aqu +Ara +arc +Arm +arr +Art +Asi +ask +asp +ass +ast +att +aud +Aug +aut +ave +avo +awe +aye +Azt +select distinct substring(fld3,1,3) as a from t2 having a like "A%" order by a limit 10; +a +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +select distinct substring(fld3,1,3) from t2 where fld3 like "A%" limit 10; +substring(fld3,1,3) +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +select distinct substring(fld3,1,3) as a from t2 having a like "A%" limit 10; +a +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +create table t3 ( +period int not null, +name char(32) not null, +companynr int not null, +price double(11,0), +price2 double(11,0), +key (period), +key (name) +); +create temporary table tmp engine = myisam select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +alter table t3 add t2nr int not null auto_increment primary key first; +drop table tmp; +SET SQL_BIG_TABLES=1; +select distinct concat(fld3," ",fld3) as namn from t2,t3 where t2.fld1=t3.t2nr order by namn limit 10; +namn +Abraham Abraham +abrogating abrogating +admonishing admonishing +Adolph Adolph +afield afield +aging aging +ammonium ammonium +analyzable analyzable +animals animals +animized animized +SET SQL_BIG_TABLES=0; +select distinct concat(fld3," ",fld3) from t2,t3 where t2.fld1=t3.t2nr order by fld3 limit 10; +concat(fld3," ",fld3) +Abraham Abraham +abrogating abrogating +admonishing admonishing +Adolph Adolph +afield afield +aging aging +ammonium ammonium +analyzable analyzable +animals animals +animized animized +select distinct fld5 from t2 limit 10; +fld5 +neat +Steinberg +jarring +tinily +balled +persist +attainments +fanatic +measures +rightfulness +select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10; +fld3 count(*) +affixed 1 +and 1 +annoyers 1 +Anthony 1 +assayed 1 +assurers 1 +attendants 1 +bedlam 1 +bedpost 1 +boasted 1 +SET SQL_BIG_TABLES=1; +select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10; +fld3 count(*) +affixed 1 +and 1 +annoyers 1 +Anthony 1 +assayed 1 +assurers 1 +attendants 1 +bedlam 1 +bedpost 1 +boasted 1 +SET SQL_BIG_TABLES=0; +select distinct fld3,repeat("a",length(fld3)),count(*) from t2 group by companynr,fld3 limit 100,10; +fld3 repeat("a",length(fld3)) count(*) +circus aaaaaa 1 +cited aaaaa 1 +Colombo aaaaaaa 1 +congresswoman aaaaaaaaaaaaa 1 +contrition aaaaaaaaaa 1 +corny aaaaa 1 +cultivation aaaaaaaaaaa 1 +definiteness aaaaaaaaaaaa 1 +demultiplex aaaaaaaaaaa 1 +disappointing aaaaaaaaaaaaa 1 +select distinct companynr,rtrim(space(512+companynr)) from t3 order by 1,2; +companynr rtrim(space(512+companynr)) +37 +78 +101 +154 +311 +447 +512 +select distinct fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by fld3; +fld3 +explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index +explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort +1 SIMPLE t3 ref period period 4 test.t1.period 4181 +explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 index period period 4 NULL 41810 +1 SIMPLE t1 ref period period 4 test.t3.period 4181 +explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index period period 4 NULL 41810 +1 SIMPLE t3 ref period period 4 test.t1.period 4181 +select period from t1; +period +9410 +select period from t1 where period=1900; +period +select fld3,period from t1,t2 where fld1 = 011401 order by period; +fld3 period +breaking 9410 +select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; +fld3 period +breaking 1001 +explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 const fld1 fld1 4 const 1 +1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 +select fld3,period from t2,t1 where companynr*10 = 37*10; +fld3 period +breaking 9410 +Romans 9410 +intercepted 9410 +bewilderingly 9410 +astound 9410 +admonishing 9410 +sumac 9410 +flanking 9410 +combed 9410 +subjective 9410 +scatterbrain 9410 +Eulerian 9410 +Kane 9410 +overlay 9410 +perturb 9410 +goblins 9410 +annihilates 9410 +Wotan 9410 +snatching 9410 +concludes 9410 +laterally 9410 +yelped 9410 +grazing 9410 +Baird 9410 +celery 9410 +misunderstander 9410 +handgun 9410 +foldout 9410 +mystic 9410 +succumbed 9410 +Nabisco 9410 +fingerings 9410 +aging 9410 +afield 9410 +ammonium 9410 +boat 9410 +intelligibility 9410 +Augustine 9410 +teethe 9410 +dreaded 9410 +scholastics 9410 +audiology 9410 +wallet 9410 +parters 9410 +eschew 9410 +quitter 9410 +neat 9410 +Steinberg 9410 +jarring 9410 +tinily 9410 +balled 9410 +persist 9410 +attainments 9410 +fanatic 9410 +measures 9410 +rightfulness 9410 +capably 9410 +impulsive 9410 +starlet 9410 +terminators 9410 +untying 9410 +announces 9410 +featherweight 9410 +pessimist 9410 +daughter 9410 +decliner 9410 +lawgiver 9410 +stated 9410 +readable 9410 +attrition 9410 +cascade 9410 +motors 9410 +interrogate 9410 +pests 9410 +stairway 9410 +dopers 9410 +testicle 9410 +Parsifal 9410 +leavings 9410 +postulation 9410 +squeaking 9410 +contrasted 9410 +leftover 9410 +whiteners 9410 +erases 9410 +Punjab 9410 +Merritt 9410 +Quixotism 9410 +sweetish 9410 +dogging 9410 +scornfully 9410 +bellow 9410 +bills 9410 +cupboard 9410 +sureties 9410 +puddings 9410 +fetters 9410 +bivalves 9410 +incurring 9410 +Adolph 9410 +pithed 9410 +Miles 9410 +trimmings 9410 +tragedies 9410 +skulking 9410 +flint 9410 +flopping 9410 +relaxing 9410 +offload 9410 +suites 9410 +lists 9410 +animized 9410 +multilayer 9410 +standardizes 9410 +Judas 9410 +vacuuming 9410 +dentally 9410 +humanness 9410 +inch 9410 +Weissmuller 9410 +irresponsibly 9410 +luckily 9410 +culled 9410 +medical 9410 +bloodbath 9410 +subschema 9410 +animals 9410 +Micronesia 9410 +repetitions 9410 +Antares 9410 +ventilate 9410 +pityingly 9410 +interdependent 9410 +Graves 9410 +neonatal 9410 +chafe 9410 +honoring 9410 +realtor 9410 +elite 9410 +funereal 9410 +abrogating 9410 +sorters 9410 +Conley 9410 +lectured 9410 +Abraham 9410 +Hawaii 9410 +cage 9410 +hushes 9410 +Simla 9410 +reporters 9410 +Dutchman 9410 +descendants 9410 +groupings 9410 +dissociate 9410 +coexist 9410 +Beebe 9410 +Taoism 9410 +Connally 9410 +fetched 9410 +checkpoints 9410 +rusting 9410 +galling 9410 +obliterates 9410 +traitor 9410 +resumes 9410 +analyzable 9410 +terminator 9410 +gritty 9410 +firearm 9410 +minima 9410 +Selfridge 9410 +disable 9410 +witchcraft 9410 +betroth 9410 +Manhattanize 9410 +imprint 9410 +peeked 9410 +swelling 9410 +interrelationships 9410 +riser 9410 +Gandhian 9410 +peacock 9410 +bee 9410 +kanji 9410 +dental 9410 +scarf 9410 +chasm 9410 +insolence 9410 +syndicate 9410 +alike 9410 +imperial 9410 +convulsion 9410 +railway 9410 +validate 9410 +normalizes 9410 +comprehensive 9410 +chewing 9410 +denizen 9410 +schemer 9410 +chronicle 9410 +Kline 9410 +Anatole 9410 +partridges 9410 +brunch 9410 +recruited 9410 +dimensions 9410 +Chicana 9410 +announced 9410 +praised 9410 +employing 9410 +linear 9410 +quagmire 9410 +western 9410 +relishing 9410 +serving 9410 +scheduling 9410 +lore 9410 +eventful 9410 +arteriole 9410 +disentangle 9410 +cured 9410 +Fenton 9410 +avoidable 9410 +drains 9410 +detectably 9410 +husky 9410 +impelling 9410 +undoes 9410 +evened 9410 +squeezes 9410 +destroyer 9410 +rudeness 9410 +beaner 9410 +boorish 9410 +Everhart 9410 +encompass 9410 +mushrooms 9410 +Alison 9410 +externally 9410 +pellagra 9410 +cult 9410 +creek 9410 +Huffman 9410 +Majorca 9410 +governing 9410 +gadfly 9410 +reassigned 9410 +intentness 9410 +craziness 9410 +psychic 9410 +squabbled 9410 +burlesque 9410 +capped 9410 +extracted 9410 +DiMaggio 9410 +exclamation 9410 +subdirectory 9410 +Gothicism 9410 +feminine 9410 +metaphysically 9410 +sanding 9410 +Miltonism 9410 +freakish 9410 +index 9410 +straight 9410 +flurried 9410 +denotative 9410 +coming 9410 +commencements 9410 +gentleman 9410 +gifted 9410 +Shanghais 9410 +sportswriting 9410 +sloping 9410 +navies 9410 +leaflet 9410 +shooter 9410 +Joplin 9410 +babies 9410 +assails 9410 +admiring 9410 +swaying 9410 +Goldstine 9410 +fitting 9410 +Norwalk 9410 +analogy 9410 +deludes 9410 +cokes 9410 +Clayton 9410 +exhausts 9410 +causality 9410 +sating 9410 +icon 9410 +throttles 9410 +communicants 9410 +dehydrate 9410 +priceless 9410 +publicly 9410 +incidentals 9410 +commonplace 9410 +mumbles 9410 +furthermore 9410 +cautioned 9410 +parametrized 9410 +registration 9410 +sadly 9410 +positioning 9410 +babysitting 9410 +eternal 9410 +hoarder 9410 +congregates 9410 +rains 9410 +workers 9410 +sags 9410 +unplug 9410 +garage 9410 +boulder 9410 +specifics 9410 +Teresa 9410 +Winsett 9410 +convenient 9410 +buckboards 9410 +amenities 9410 +resplendent 9410 +sews 9410 +participated 9410 +Simon 9410 +certificates 9410 +Fitzpatrick 9410 +Evanston 9410 +misted 9410 +textures 9410 +save 9410 +count 9410 +rightful 9410 +chaperone 9410 +Lizzy 9410 +clenched 9410 +effortlessly 9410 +accessed 9410 +beaters 9410 +Hornblower 9410 +vests 9410 +indulgences 9410 +infallibly 9410 +unwilling 9410 +excrete 9410 +spools 9410 +crunches 9410 +overestimating 9410 +ineffective 9410 +humiliation 9410 +sophomore 9410 +star 9410 +rifles 9410 +dialysis 9410 +arriving 9410 +indulge 9410 +clockers 9410 +languages 9410 +Antarctica 9410 +percentage 9410 +ceiling 9410 +specification 9410 +regimented 9410 +ciphers 9410 +pictures 9410 +serpents 9410 +allot 9410 +realized 9410 +mayoral 9410 +opaquely 9410 +hostess 9410 +fiftieth 9410 +incorrectly 9410 +decomposition 9410 +stranglings 9410 +mixture 9410 +electroencephalography 9410 +similarities 9410 +charges 9410 +freest 9410 +Greenberg 9410 +tinting 9410 +expelled 9410 +warm 9410 +smoothed 9410 +deductions 9410 +Romano 9410 +bitterroot 9410 +corset 9410 +securing 9410 +environing 9410 +cute 9410 +Crays 9410 +heiress 9410 +inform 9410 +avenge 9410 +universals 9410 +Kinsey 9410 +ravines 9410 +bestseller 9410 +equilibrium 9410 +extents 9410 +relatively 9410 +pressure 9410 +critiques 9410 +befouled 9410 +rightfully 9410 +mechanizing 9410 +Latinizes 9410 +timesharing 9410 +Aden 9410 +embassies 9410 +males 9410 +shapelessly 9410 +mastering 9410 +Newtonian 9410 +finishers 9410 +abates 9410 +teem 9410 +kiting 9410 +stodgy 9410 +feed 9410 +guitars 9410 +airships 9410 +store 9410 +denounces 9410 +Pyle 9410 +Saxony 9410 +serializations 9410 +Peruvian 9410 +taxonomically 9410 +kingdom 9410 +stint 9410 +Sault 9410 +faithful 9410 +Ganymede 9410 +tidiness 9410 +gainful 9410 +contrary 9410 +Tipperary 9410 +tropics 9410 +theorizers 9410 +renew 9410 +already 9410 +terminal 9410 +Hegelian 9410 +hypothesizer 9410 +warningly 9410 +journalizing 9410 +nested 9410 +Lars 9410 +saplings 9410 +foothill 9410 +labeled 9410 +imperiously 9410 +reporters 9410 +furnishings 9410 +precipitable 9410 +discounts 9410 +excises 9410 +Stalin 9410 +despot 9410 +ripeness 9410 +Arabia 9410 +unruly 9410 +mournfulness 9410 +boom 9410 +slaughter 9410 +Sabine 9410 +handy 9410 +rural 9410 +organizer 9410 +shipyard 9410 +civics 9410 +inaccuracy 9410 +rules 9410 +juveniles 9410 +comprised 9410 +investigations 9410 +stabilizes 9410 +seminaries 9410 +Hunter 9410 +sporty 9410 +test 9410 +weasels 9410 +CERN 9410 +tempering 9410 +afore 9410 +Galatean 9410 +techniques 9410 +error 9410 +veranda 9410 +severely 9410 +Cassites 9410 +forthcoming 9410 +guides 9410 +vanish 9410 +lied 9410 +sawtooth 9410 +fated 9410 +gradually 9410 +widens 9410 +preclude 9410 +evenhandedly 9410 +percentage 9410 +disobedience 9410 +humility 9410 +gleaning 9410 +petted 9410 +bloater 9410 +minion 9410 +marginal 9410 +apiary 9410 +measures 9410 +precaution 9410 +repelled 9410 +primary 9410 +coverings 9410 +Artemia 9410 +navigate 9410 +spatial 9410 +Gurkha 9410 +meanwhile 9410 +Melinda 9410 +Butterfield 9410 +Aldrich 9410 +previewing 9410 +glut 9410 +unaffected 9410 +inmate 9410 +mineral 9410 +impending 9410 +meditation 9410 +ideas 9410 +miniaturizes 9410 +lewdly 9410 +title 9410 +youthfulness 9410 +creak 9410 +Chippewa 9410 +clamored 9410 +freezes 9410 +forgivably 9410 +reduce 9410 +McGovern 9410 +Nazis 9410 +epistle 9410 +socializes 9410 +conceptions 9410 +Kevin 9410 +uncovering 9410 +chews 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +raining 9410 +infest 9410 +compartment 9410 +minting 9410 +ducks 9410 +roped 9410 +waltz 9410 +Lillian 9410 +repressions 9410 +chillingly 9410 +noncritical 9410 +lithograph 9410 +spongers 9410 +parenthood 9410 +posed 9410 +instruments 9410 +filial 9410 +fixedly 9410 +relives 9410 +Pandora 9410 +watering 9410 +ungrateful 9410 +secures 9410 +poison 9410 +dusted 9410 +encompasses 9410 +presentation 9410 +Kantian 9410 +select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; +fld3 period price price2 +admonishing 1002 28357832 8723648 +analyzable 1002 28357832 8723648 +annihilates 1001 5987435 234724 +Antares 1002 28357832 8723648 +astound 1001 5987435 234724 +audiology 1001 5987435 234724 +Augustine 1002 28357832 8723648 +Baird 1002 28357832 8723648 +bewilderingly 1001 5987435 234724 +breaking 1001 5987435 234724 +Conley 1001 5987435 234724 +dentally 1002 28357832 8723648 +dissociate 1002 28357832 8723648 +elite 1001 5987435 234724 +eschew 1001 5987435 234724 +Eulerian 1001 5987435 234724 +flanking 1001 5987435 234724 +foldout 1002 28357832 8723648 +funereal 1002 28357832 8723648 +galling 1002 28357832 8723648 +Graves 1001 5987435 234724 +grazing 1001 5987435 234724 +groupings 1001 5987435 234724 +handgun 1001 5987435 234724 +humility 1002 28357832 8723648 +impulsive 1002 28357832 8723648 +inch 1001 5987435 234724 +intelligibility 1001 5987435 234724 +jarring 1001 5987435 234724 +lawgiver 1001 5987435 234724 +lectured 1002 28357832 8723648 +Merritt 1002 28357832 8723648 +neonatal 1001 5987435 234724 +offload 1002 28357832 8723648 +parters 1002 28357832 8723648 +pityingly 1002 28357832 8723648 +puddings 1002 28357832 8723648 +Punjab 1001 5987435 234724 +quitter 1002 28357832 8723648 +realtor 1001 5987435 234724 +relaxing 1001 5987435 234724 +repetitions 1001 5987435 234724 +resumes 1001 5987435 234724 +Romans 1002 28357832 8723648 +rusting 1001 5987435 234724 +scholastics 1001 5987435 234724 +skulking 1002 28357832 8723648 +stated 1002 28357832 8723648 +suites 1002 28357832 8723648 +sureties 1001 5987435 234724 +testicle 1002 28357832 8723648 +tinily 1002 28357832 8723648 +tragedies 1001 5987435 234724 +trimmings 1001 5987435 234724 +vacuuming 1001 5987435 234724 +ventilate 1001 5987435 234724 +wallet 1001 5987435 234724 +Weissmuller 1002 28357832 8723648 +Wotan 1002 28357832 8723648 +select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; +fld1 fld3 period price price2 +018201 relaxing 1001 5987435 234724 +018601 vacuuming 1001 5987435 234724 +018801 inch 1001 5987435 234724 +018811 repetitions 1001 5987435 234724 +create table t4 ( +companynr tinyint(2) unsigned zerofill NOT NULL default '00', +companyname char(30) NOT NULL default '', +PRIMARY KEY (companynr), +UNIQUE KEY companyname(companyname) +) ENGINE=MyISAM MAX_ROWS=50 PACK_KEYS=1 COMMENT='companynames'; +select STRAIGHT_JOIN t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr; +companynr companyname +00 Unknown +29 company 1 +34 company 2 +36 company 3 +37 company 4 +40 company 5 +41 company 6 +50 company 11 +53 company 7 +58 company 8 +65 company 9 +68 company 10 +select SQL_SMALL_RESULT t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr; +companynr companyname +00 Unknown +29 company 1 +34 company 2 +36 company 3 +37 company 4 +40 company 5 +41 company 6 +50 company 11 +53 company 7 +58 company 8 +65 company 9 +68 company 10 +select * from t1,t1 t12; +Period Varor_period Period Varor_period +9410 9412 9410 9412 +select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; +fld1 fld1 +250501 250501 +250502 250501 +250503 250501 +250504 250501 +250505 250501 +250501 250502 +250502 250502 +250503 250502 +250504 250502 +250505 250502 +250501 250503 +250502 250503 +250503 250503 +250504 250503 +250505 250503 +250501 250504 +250502 250504 +250503 250504 +250504 250504 +250505 250504 +250501 250505 +250502 250505 +250503 250505 +250504 250505 +250505 250505 +insert into t2 (fld1, companynr) values (999999,99); +select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +companynr companyname +99 NULL +select count(*) from t2 left join t4 using (companynr) where t4.companynr is not null; +count(*) +1199 +explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 Using where; Not exists +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Not exists +select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; +companynr companyname +select count(*) from t2 left join t4 using (companynr) where companynr is not null; +count(*) +1200 +explain select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +delete from t2 where fld1=999999; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; +companynr companynr +37 36 +41 40 +explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; +fld1 companynr fld3 period +038008 37 reporters 1008 +038208 37 Selfridge 1008 +select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; +fld1 companynr fld3 period +038008 37 reporters 1008 +038208 37 Selfridge 1008 +select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; +fld1 companynr fld3 period +038008 37 reporters 1008 +038208 37 Selfridge 1008 +select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); +period +9410 +select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); +period +9410 +select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; +fld1 +250501 +250502 +250503 +250505 +select fld1 from t2 where fld1 in (250502,98005,98006,250503,250605,250606) and fld1 >=250502 and fld1 not in (250605,250606); +fld1 +250502 +250503 +select fld1 from t2 where fld1 between 250502 and 250504; +fld1 +250502 +250503 +250504 +select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld3 like "L%" or fld3 like "G%")) and fld3 like "L%" ; +fld3 +label +labeled +labeled +landslide +laterally +leaflet +lewdly +Lillian +luckily +select count(*) from t1; +count(*) +1 +select companynr,count(*),sum(fld1) from t2 group by companynr; +companynr count(*) sum(fld1) +00 82 10355753 +29 95 14473298 +34 70 17788966 +36 215 22786296 +37 588 83602098 +40 37 6618386 +41 52 12816335 +50 11 1595438 +53 4 793210 +58 23 2254293 +65 10 2284055 +68 12 3097288 +select companynr,count(*) from t2 group by companynr order by companynr desc limit 5; +companynr count(*) +68 12 +65 10 +58 23 +53 4 +50 11 +select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>""; +count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1) +70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069 +explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>""; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +Warnings: +Note 1003 select count(0) AS `count(*)`,min(`test`.`t2`.`fld4`) AS `min(fld4)`,max(`test`.`t2`.`fld4`) AS `max(fld4)`,sum(`test`.`t2`.`fld1`) AS `sum(fld1)`,avg(`test`.`t2`.`fld1`) AS `avg(fld1)`,std(`test`.`t2`.`fld1`) AS `std(fld1)`,variance(`test`.`t2`.`fld1`) AS `variance(fld1)` from `test`.`t2` where ((`test`.`t2`.`companynr` = 34) and (`test`.`t2`.`fld4` <> _latin1'')) +select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3; +companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1) +00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087 +29 95 abut wetness 14473298 152350.5053 8368.5480 70032594.9026 +34 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069 +select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; +companynr t2nr count(price) sum(price) min(price) max(price) avg(price) +37 1 1 5987435 5987435 5987435 5987435.0000 +37 2 1 28357832 28357832 28357832 28357832.0000 +37 3 1 39654943 39654943 39654943 39654943.0000 +37 11 1 5987435 5987435 5987435 5987435.0000 +37 12 1 28357832 28357832 28357832 28357832.0000 +37 13 1 39654943 39654943 39654943 39654943.0000 +37 21 1 5987435 5987435 5987435 5987435.0000 +37 22 1 28357832 28357832 28357832 28357832.0000 +37 23 1 39654943 39654943 39654943 39654943.0000 +37 31 1 5987435 5987435 5987435 5987435.0000 +select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; +companynr t2nr count(price) sum(price) min(price) max(price) avg(price) +37 1 1 5987435 5987435 5987435 5987435.0000 +37 2 1 28357832 28357832 28357832 28357832.0000 +37 3 1 39654943 39654943 39654943 39654943.0000 +37 11 1 5987435 5987435 5987435 5987435.0000 +37 12 1 28357832 28357832 28357832 28357832.0000 +37 13 1 39654943 39654943 39654943 39654943.0000 +37 21 1 5987435 5987435 5987435 5987435.0000 +37 22 1 28357832 28357832 28357832 28357832.0000 +37 23 1 39654943 39654943 39654943 39654943.0000 +37 31 1 5987435 5987435 5987435 5987435.0000 +select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ; +companynr count(price) sum(price) min(price) max(price) avg(price) +37 12543 309394878010 5987435 39654943 24666736.6667 +78 8362 414611089292 726498 98439034 49582766.0000 +101 4181 3489454238 834598 834598 834598.0000 +154 4181 4112197254950 983543950 983543950 983543950.0000 +311 4181 979599938 234298 234298 234298.0000 +447 4181 9929180954 2374834 2374834 2374834.0000 +512 4181 3288532102 786542 786542 786542.0000 +select distinct mod(companynr,10) from t4 group by companynr; +mod(companynr,10) +0 +9 +4 +6 +7 +1 +3 +8 +5 +select distinct 1 from t4 group by companynr; +1 +1 +select count(distinct fld1) from t2; +count(distinct fld1) +1199 +select companynr,count(distinct fld1) from t2 group by companynr; +companynr count(distinct fld1) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(*) from t2 group by companynr; +companynr count(*) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(distinct concat(fld1,repeat(65,1000))) from t2 group by companynr; +companynr count(distinct concat(fld1,repeat(65,1000))) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(distinct concat(fld1,repeat(65,200))) from t2 group by companynr; +companynr count(distinct concat(fld1,repeat(65,200))) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(distinct floor(fld1/100)) from t2 group by companynr; +companynr count(distinct floor(fld1/100)) +00 47 +29 35 +34 14 +36 69 +37 108 +40 16 +41 11 +50 9 +53 1 +58 1 +65 1 +68 1 +select companynr,count(distinct concat(repeat(65,1000),floor(fld1/100))) from t2 group by companynr; +companynr count(distinct concat(repeat(65,1000),floor(fld1/100))) +00 47 +29 35 +34 14 +36 69 +37 108 +40 16 +41 11 +50 9 +53 1 +58 1 +65 1 +68 1 +select sum(fld1),fld3 from t2 where fld3="Romans" group by fld1 limit 10; +sum(fld1) fld3 +11402 Romans +select name,count(*) from t3 where name='cloakroom' group by name; +name count(*) +cloakroom 4181 +select name,count(*) from t3 where name='cloakroom' and price>10 group by name; +name count(*) +cloakroom 4181 +select count(*) from t3 where name='cloakroom' and price2=823742; +count(*) +4181 +select name,count(*) from t3 where name='cloakroom' and price2=823742 group by name; +name count(*) +cloakroom 4181 +select name,count(*) from t3 where name >= "extramarital" and price <= 39654943 group by name; +name count(*) +extramarital 4181 +gazer 4181 +gems 4181 +Iranizes 4181 +spates 4181 +tucked 4181 +violinist 4181 +select t2.fld3,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; +fld3 count(*) +spates 4181 +select companynr|0,companyname from t4 group by 1; +companynr|0 companyname +0 Unknown +29 company 1 +34 company 2 +36 company 3 +37 company 4 +40 company 5 +41 company 6 +50 company 11 +53 company 7 +58 company 8 +65 company 9 +68 company 10 +select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by t2.companynr order by companyname; +companynr companyname count(*) +29 company 1 95 +68 company 10 12 +50 company 11 11 +34 company 2 70 +36 company 3 215 +37 company 4 588 +40 company 5 37 +41 company 6 52 +53 company 7 4 +58 company 8 23 +65 company 9 10 +00 Unknown 82 +select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; +fld1 count(*) +158402 4181 +select sum(Period)/count(*) from t1; +sum(Period)/count(*) +9410.0000 +select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; +companynr count sum diff func +37 12543 309394878010 0.0000 464091 +78 8362 414611089292 0.0000 652236 +101 4181 3489454238 0.0000 422281 +154 4181 4112197254950 0.0000 643874 +311 4181 979599938 0.0000 1300291 +447 4181 9929180954 0.0000 1868907 +512 4181 3288532102 0.0000 2140672 +select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg; +companynr avg +154 983543950.0000 +select companynr,count(*) from t2 group by companynr order by 2 desc; +companynr count(*) +37 588 +36 215 +29 95 +00 82 +34 70 +41 52 +40 37 +58 23 +68 12 +50 11 +65 10 +53 4 +select companynr,count(*) from t2 where companynr > 40 group by companynr order by 2 desc; +companynr count(*) +41 52 +58 23 +68 12 +50 11 +65 10 +53 4 +select t2.fld4,t2.fld1,count(price),sum(price),min(price),max(price),avg(price) from t3,t2 where t3.companynr = 37 and t2.fld1 = t3.t2nr group by fld1,t2.fld4; +fld4 fld1 count(price) sum(price) min(price) max(price) avg(price) +teethe 000001 1 5987435 5987435 5987435 5987435.0000 +dreaded 011401 1 5987435 5987435 5987435 5987435.0000 +scholastics 011402 1 28357832 28357832 28357832 28357832.0000 +audiology 011403 1 39654943 39654943 39654943 39654943.0000 +wallet 011501 1 5987435 5987435 5987435 5987435.0000 +parters 011701 1 5987435 5987435 5987435 5987435.0000 +eschew 011702 1 28357832 28357832 28357832 28357832.0000 +quitter 011703 1 39654943 39654943 39654943 39654943.0000 +neat 012001 1 5987435 5987435 5987435 5987435.0000 +Steinberg 012003 1 39654943 39654943 39654943 39654943.0000 +balled 012301 1 5987435 5987435 5987435 5987435.0000 +persist 012302 1 28357832 28357832 28357832 28357832.0000 +attainments 012303 1 39654943 39654943 39654943 39654943.0000 +capably 012501 1 5987435 5987435 5987435 5987435.0000 +impulsive 012602 1 28357832 28357832 28357832 28357832.0000 +starlet 012603 1 39654943 39654943 39654943 39654943.0000 +featherweight 012701 1 5987435 5987435 5987435 5987435.0000 +pessimist 012702 1 28357832 28357832 28357832 28357832.0000 +daughter 012703 1 39654943 39654943 39654943 39654943.0000 +lawgiver 013601 1 5987435 5987435 5987435 5987435.0000 +stated 013602 1 28357832 28357832 28357832 28357832.0000 +readable 013603 1 39654943 39654943 39654943 39654943.0000 +testicle 013801 1 5987435 5987435 5987435 5987435.0000 +Parsifal 013802 1 28357832 28357832 28357832 28357832.0000 +leavings 013803 1 39654943 39654943 39654943 39654943.0000 +squeaking 013901 1 5987435 5987435 5987435 5987435.0000 +contrasted 016001 1 5987435 5987435 5987435 5987435.0000 +leftover 016201 1 5987435 5987435 5987435 5987435.0000 +whiteners 016202 1 28357832 28357832 28357832 28357832.0000 +erases 016301 1 5987435 5987435 5987435 5987435.0000 +Punjab 016302 1 28357832 28357832 28357832 28357832.0000 +Merritt 016303 1 39654943 39654943 39654943 39654943.0000 +sweetish 018001 1 5987435 5987435 5987435 5987435.0000 +dogging 018002 1 28357832 28357832 28357832 28357832.0000 +scornfully 018003 1 39654943 39654943 39654943 39654943.0000 +fetters 018012 1 28357832 28357832 28357832 28357832.0000 +bivalves 018013 1 39654943 39654943 39654943 39654943.0000 +skulking 018021 1 5987435 5987435 5987435 5987435.0000 +flint 018022 1 28357832 28357832 28357832 28357832.0000 +flopping 018023 1 39654943 39654943 39654943 39654943.0000 +Judas 018032 1 28357832 28357832 28357832 28357832.0000 +vacuuming 018033 1 39654943 39654943 39654943 39654943.0000 +medical 018041 1 5987435 5987435 5987435 5987435.0000 +bloodbath 018042 1 28357832 28357832 28357832 28357832.0000 +subschema 018043 1 39654943 39654943 39654943 39654943.0000 +interdependent 018051 1 5987435 5987435 5987435 5987435.0000 +Graves 018052 1 28357832 28357832 28357832 28357832.0000 +neonatal 018053 1 39654943 39654943 39654943 39654943.0000 +sorters 018061 1 5987435 5987435 5987435 5987435.0000 +epistle 018062 1 28357832 28357832 28357832 28357832.0000 +Conley 018101 1 5987435 5987435 5987435 5987435.0000 +lectured 018102 1 28357832 28357832 28357832 28357832.0000 +Abraham 018103 1 39654943 39654943 39654943 39654943.0000 +cage 018201 1 5987435 5987435 5987435 5987435.0000 +hushes 018202 1 28357832 28357832 28357832 28357832.0000 +Simla 018402 1 28357832 28357832 28357832 28357832.0000 +reporters 018403 1 39654943 39654943 39654943 39654943.0000 +coexist 018601 1 5987435 5987435 5987435 5987435.0000 +Beebe 018602 1 28357832 28357832 28357832 28357832.0000 +Taoism 018603 1 39654943 39654943 39654943 39654943.0000 +Connally 018801 1 5987435 5987435 5987435 5987435.0000 +fetched 018802 1 28357832 28357832 28357832 28357832.0000 +checkpoints 018803 1 39654943 39654943 39654943 39654943.0000 +gritty 018811 1 5987435 5987435 5987435 5987435.0000 +firearm 018812 1 28357832 28357832 28357832 28357832.0000 +minima 019101 1 5987435 5987435 5987435 5987435.0000 +Selfridge 019102 1 28357832 28357832 28357832 28357832.0000 +disable 019103 1 39654943 39654943 39654943 39654943.0000 +witchcraft 019201 1 5987435 5987435 5987435 5987435.0000 +betroth 030501 1 5987435 5987435 5987435 5987435.0000 +Manhattanize 030502 1 28357832 28357832 28357832 28357832.0000 +imprint 030503 1 39654943 39654943 39654943 39654943.0000 +swelling 031901 1 5987435 5987435 5987435 5987435.0000 +interrelationships 036001 1 5987435 5987435 5987435 5987435.0000 +riser 036002 1 28357832 28357832 28357832 28357832.0000 +bee 038001 1 5987435 5987435 5987435 5987435.0000 +kanji 038002 1 28357832 28357832 28357832 28357832.0000 +dental 038003 1 39654943 39654943 39654943 39654943.0000 +railway 038011 1 5987435 5987435 5987435 5987435.0000 +validate 038012 1 28357832 28357832 28357832 28357832.0000 +normalizes 038013 1 39654943 39654943 39654943 39654943.0000 +Kline 038101 1 5987435 5987435 5987435 5987435.0000 +Anatole 038102 1 28357832 28357832 28357832 28357832.0000 +partridges 038103 1 39654943 39654943 39654943 39654943.0000 +recruited 038201 1 5987435 5987435 5987435 5987435.0000 +dimensions 038202 1 28357832 28357832 28357832 28357832.0000 +Chicana 038203 1 39654943 39654943 39654943 39654943.0000 +select t3.companynr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 group by companynr,fld3; +companynr fld3 sum(price) +512 boat 786542 +512 capably 786542 +512 cupboard 786542 +512 decliner 786542 +512 descendants 786542 +512 dopers 786542 +512 erases 786542 +512 Micronesia 786542 +512 Miles 786542 +512 skies 786542 +select t2.companynr,count(*),min(fld3),max(fld3),sum(price),avg(price) from t2,t3 where t3.companynr >= 30 and t3.companynr <= 58 and t3.t2nr = t2.fld1 and 1+1=2 group by t2.companynr; +companynr count(*) min(fld3) max(fld3) sum(price) avg(price) +00 1 Omaha Omaha 5987435 5987435.0000 +36 1 dubbed dubbed 28357832 28357832.0000 +37 83 Abraham Wotan 1908978016 22999735.1325 +50 2 scribbled tapestry 68012775 34006387.5000 +select t3.companynr+0,t3.t2nr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 37 group by 1,t3.t2nr,fld3,fld3,fld3,fld3,fld3 order by fld1; +t3.companynr+0 t2nr fld3 sum(price) +37 1 Omaha 5987435 +37 11401 breaking 5987435 +37 11402 Romans 28357832 +37 11403 intercepted 39654943 +37 11501 bewilderingly 5987435 +37 11701 astound 5987435 +37 11702 admonishing 28357832 +37 11703 sumac 39654943 +37 12001 flanking 5987435 +37 12003 combed 39654943 +37 12301 Eulerian 5987435 +37 12302 dubbed 28357832 +37 12303 Kane 39654943 +37 12501 annihilates 5987435 +37 12602 Wotan 28357832 +37 12603 snatching 39654943 +37 12701 grazing 5987435 +37 12702 Baird 28357832 +37 12703 celery 39654943 +37 13601 handgun 5987435 +37 13602 foldout 28357832 +37 13603 mystic 39654943 +37 13801 intelligibility 5987435 +37 13802 Augustine 28357832 +37 13803 teethe 39654943 +37 13901 scholastics 5987435 +37 16001 audiology 5987435 +37 16201 wallet 5987435 +37 16202 parters 28357832 +37 16301 eschew 5987435 +37 16302 quitter 28357832 +37 16303 neat 39654943 +37 18001 jarring 5987435 +37 18002 tinily 28357832 +37 18003 balled 39654943 +37 18012 impulsive 28357832 +37 18013 starlet 39654943 +37 18021 lawgiver 5987435 +37 18022 stated 28357832 +37 18023 readable 39654943 +37 18032 testicle 28357832 +37 18033 Parsifal 39654943 +37 18041 Punjab 5987435 +37 18042 Merritt 28357832 +37 18043 Quixotism 39654943 +37 18051 sureties 5987435 +37 18052 puddings 28357832 +37 18053 tapestry 39654943 +37 18061 trimmings 5987435 +37 18062 humility 28357832 +37 18101 tragedies 5987435 +37 18102 skulking 28357832 +37 18103 flint 39654943 +37 18201 relaxing 5987435 +37 18202 offload 28357832 +37 18402 suites 28357832 +37 18403 lists 39654943 +37 18601 vacuuming 5987435 +37 18602 dentally 28357832 +37 18603 humanness 39654943 +37 18801 inch 5987435 +37 18802 Weissmuller 28357832 +37 18803 irresponsibly 39654943 +37 18811 repetitions 5987435 +37 18812 Antares 28357832 +37 19101 ventilate 5987435 +37 19102 pityingly 28357832 +37 19103 interdependent 39654943 +37 19201 Graves 5987435 +37 30501 neonatal 5987435 +37 30502 scribbled 28357832 +37 30503 chafe 39654943 +37 31901 realtor 5987435 +37 36001 elite 5987435 +37 36002 funereal 28357832 +37 38001 Conley 5987435 +37 38002 lectured 28357832 +37 38003 Abraham 39654943 +37 38011 groupings 5987435 +37 38012 dissociate 28357832 +37 38013 coexist 39654943 +37 38101 rusting 5987435 +37 38102 galling 28357832 +37 38103 obliterates 39654943 +37 38201 resumes 5987435 +37 38202 analyzable 28357832 +37 38203 terminator 39654943 +select sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1= t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008; +sum(price) +234298 +select t2.fld1,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1 = t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008 or t3.t2nr = t2.fld1 and t2.fld1 = 38008 group by t2.fld1; +fld1 sum(price) +038008 234298 +explain select fld3 from t2 where 1>2 or 2>3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +explain select fld3 from t2 where fld1=fld1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502; +companynr fld1 +34 250501 +34 250502 +select companynr,fld1 from t2 WHERE fld1>=250501 HAVING fld1<=250502; +companynr fld1 +34 250501 +34 250502 +select companynr,count(*) as count,sum(fld1) as sum from t2 group by companynr having count > 40 and sum/count >= 120000; +companynr count sum +00 82 10355753 +29 95 14473298 +34 70 17788966 +37 588 83602098 +41 52 12816335 +select companynr from t2 group by companynr having count(*) > 40 and sum(fld1)/count(*) >= 120000 ; +companynr +00 +29 +34 +37 +41 +select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by companyname having t2.companynr >= 40; +companynr companyname count(*) +68 company 10 12 +50 company 11 11 +40 company 5 37 +41 company 6 52 +53 company 7 4 +58 company 8 23 +65 company 9 10 +select count(*) from t2; +count(*) +1199 +select count(*) from t2 where fld1 < 098024; +count(*) +387 +select min(fld1) from t2 where fld1>= 098024; +min(fld1) +98024 +select max(fld1) from t2 where fld1>= 098024; +max(fld1) +1232609 +select count(*) from t3 where price2=76234234; +count(*) +4181 +select count(*) from t3 where companynr=512 and price2=76234234; +count(*) +4181 +explain select min(fld1),max(fld1),count(*) from t2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +select min(fld1),max(fld1),count(*) from t2; +min(fld1) max(fld1) count(*) +0 1232609 1199 +select min(t2nr),max(t2nr) from t3 where t2nr=2115 and price2=823742; +min(t2nr) max(t2nr) +2115 2115 +select count(*),min(t2nr),max(t2nr) from t3 where name='spates' and companynr=78; +count(*) min(t2nr) max(t2nr) +4181 4 41804 +select t2nr,count(*) from t3 where name='gems' group by t2nr limit 20; +t2nr count(*) +9 1 +19 1 +29 1 +39 1 +49 1 +59 1 +69 1 +79 1 +89 1 +99 1 +109 1 +119 1 +129 1 +139 1 +149 1 +159 1 +169 1 +179 1 +189 1 +199 1 +select max(t2nr) from t3 where price=983543950; +max(t2nr) +41807 +select t1.period from t3 = t1 limit 1; +period +1001 +select t1.period from t1 as t1 limit 1; +period +9410 +select t1.period as "Nuvarande period" from t1 as t1 limit 1; +Nuvarande period +9410 +select period as ok_period from t1 limit 1; +ok_period +9410 +select period as ok_period from t1 group by ok_period limit 1; +ok_period +9410 +select 1+1 as summa from t1 group by summa limit 1; +summa +2 +select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; +Nuvarande period +9410 +show tables; +Tables_in_test +t1 +t2 +t3 +t4 +show tables from test like "s%"; +Tables_in_test (s%) +show tables from test like "t?"; +Tables_in_test (t?) +show full columns from t2; +Field Type Collation Null Key Default Extra Privileges Comment +auto int(11) NULL NO PRI NULL auto_increment # +fld1 int(6) unsigned zerofill NULL NO UNI 000000 # +companynr tinyint(2) unsigned zerofill NULL NO 00 # +fld3 char(30) latin1_swedish_ci NO MUL # +fld4 char(35) latin1_swedish_ci NO # +fld5 char(35) latin1_swedish_ci NO # +fld6 char(4) latin1_swedish_ci NO # +show full columns from t2 from test like 'f%'; +Field Type Collation Null Key Default Extra Privileges Comment +fld1 int(6) unsigned zerofill NULL NO UNI 000000 # +fld3 char(30) latin1_swedish_ci NO MUL # +fld4 char(35) latin1_swedish_ci NO # +fld5 char(35) latin1_swedish_ci NO # +fld6 char(4) latin1_swedish_ci NO # +show full columns from t2 from test like 's%'; +Field Type Collation Null Key Default Extra Privileges Comment +show keys from t2; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE +t2 0 fld1 1 fld1 A 1199 NULL NULL BTREE +t2 1 fld3 1 fld3 A NULL NULL NULL BTREE +drop table t4, t3, t2, t1; +CREATE TABLE t1 ( +cont_nr int(11) NOT NULL auto_increment, +ver_nr int(11) NOT NULL default '0', +aufnr int(11) NOT NULL default '0', +username varchar(50) NOT NULL default '', +hdl_nr int(11) NOT NULL default '0', +eintrag date NOT NULL default '0000-00-00', +st_klasse varchar(40) NOT NULL default '', +st_wert varchar(40) NOT NULL default '', +st_zusatz varchar(40) NOT NULL default '', +st_bemerkung varchar(255) NOT NULL default '', +kunden_art varchar(40) NOT NULL default '', +mcbs_knr int(11) default NULL, +mcbs_aufnr int(11) NOT NULL default '0', +schufa_status char(1) default '?', +bemerkung text, +wirknetz text, +wf_igz int(11) NOT NULL default '0', +tarifcode varchar(80) default NULL, +recycle char(1) default NULL, +sim varchar(30) default NULL, +mcbs_tpl varchar(30) default NULL, +emp_nr int(11) NOT NULL default '0', +laufzeit int(11) default NULL, +hdl_name varchar(30) default NULL, +prov_hdl_nr int(11) NOT NULL default '0', +auto_wirknetz varchar(50) default NULL, +auto_billing varchar(50) default NULL, +touch timestamp NOT NULL, +kategorie varchar(50) default NULL, +kundentyp varchar(20) NOT NULL default '', +sammel_rech_msisdn varchar(30) NOT NULL default '', +p_nr varchar(9) NOT NULL default '', +suffix char(3) NOT NULL default '', +PRIMARY KEY (cont_nr), +KEY idx_aufnr(aufnr), +KEY idx_hdl_nr(hdl_nr), +KEY idx_st_klasse(st_klasse), +KEY ver_nr(ver_nr), +KEY eintrag_idx(eintrag), +KEY emp_nr_idx(emp_nr), +KEY wf_igz(wf_igz), +KEY touch(touch), +KEY hdl_tag(eintrag,hdl_nr), +KEY prov_hdl_nr(prov_hdl_nr), +KEY mcbs_aufnr(mcbs_aufnr), +KEY kundentyp(kundentyp), +KEY p_nr(p_nr,suffix) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES (3359356,405,3359356,'Mustermann Musterfrau',52500,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1485525,2122316,'+','','N',1909160,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',3,24,'MobilCom Shop Koeln',52500,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359357,468,3359357,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1503580,2139699,'+','','P',1909171,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359358,407,3359358,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1501358,2137473,'N','','N',1909159,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359359,468,3359359,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1507831,2143894,'+','','P',1909162,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359360,0,0,'Mustermann Musterfrau',29674907,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1900169997,2414578,'+',NULL,'N',1909148,'',NULL,NULL,'RV99066_2',20,NULL,'POS',29674907,NULL,NULL,20010202105916,'Mobilfunk','','','97317481','007'); +INSERT INTO t1 VALUES (3359361,406,3359361,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag storniert','','(7001-84):Storno, Kd. möchte nicht mehr','privat',NULL,0,'+','','P',1909150,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1509984,2145874,'+','','P',1909154,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie; +Kundentyp kategorie +Privat (Private Nutzung) Mobilfunk +Warnings: +Warning 1052 Column 'kundentyp' in group statement is ambiguous +drop table t1; +SHOW STATUS LIKE 'Ssl_cipher'; +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA diff --git a/mysql-test/r/ssl_compress.result b/mysql-test/r/ssl_compress.result new file mode 100644 index 00000000000..9c1cf4b0ec3 --- /dev/null +++ b/mysql-test/r/ssl_compress.result @@ -0,0 +1,2165 @@ +SHOW STATUS LIKE 'Ssl_cipher'; +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA +SHOW STATUS LIKE 'Compression'; +Variable_name Value +Compression ON +drop table if exists t1,t2,t3,t4; +CREATE TABLE t1 ( +Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, +Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL +); +INSERT INTO t1 VALUES (9410,9412); +select period from t1; +period +9410 +select * from t1; +Period Varor_period +9410 9412 +select t1.* from t1; +Period Varor_period +9410 9412 +CREATE TABLE t2 ( +auto int not null auto_increment, +fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL, +companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL, +fld3 char(30) DEFAULT '' NOT NULL, +fld4 char(35) DEFAULT '' NOT NULL, +fld5 char(35) DEFAULT '' NOT NULL, +fld6 char(4) DEFAULT '' NOT NULL, +UNIQUE fld1 (fld1), +KEY fld3 (fld3), +PRIMARY KEY (auto) +); +select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%"; +fld3 +imaginable +select fld3 from t2 where fld3 like "%cultivation" ; +fld3 +cultivation +select t2.fld3,companynr from t2 where companynr = 57+1 order by fld3; +fld3 companynr +concoct 58 +druggists 58 +engrossing 58 +Eurydice 58 +exclaimers 58 +ferociousness 58 +hopelessness 58 +Huey 58 +imaginable 58 +judges 58 +merging 58 +ostrich 58 +peering 58 +Phelps 58 +presumes 58 +Ruth 58 +sentences 58 +Shylock 58 +straggled 58 +synergy 58 +thanking 58 +tying 58 +unlocks 58 +select fld3,companynr from t2 where companynr = 58 order by fld3; +fld3 companynr +concoct 58 +druggists 58 +engrossing 58 +Eurydice 58 +exclaimers 58 +ferociousness 58 +hopelessness 58 +Huey 58 +imaginable 58 +judges 58 +merging 58 +ostrich 58 +peering 58 +Phelps 58 +presumes 58 +Ruth 58 +sentences 58 +Shylock 58 +straggled 58 +synergy 58 +thanking 58 +tying 58 +unlocks 58 +select fld3 from t2 order by fld3 desc limit 10; +fld3 +youthfulness +yelped +Wotan +workers +Witt +witchcraft +Winsett +Willy +willed +wildcats +select fld3 from t2 order by fld3 desc limit 5; +fld3 +youthfulness +yelped +Wotan +workers +Witt +select fld3 from t2 order by fld3 desc limit 5,5; +fld3 +witchcraft +Winsett +Willy +willed +wildcats +select t2.fld3 from t2 where fld3 = 'honeysuckle'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'honeysuckl_'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'hon_ysuckl_'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'honeysuckle%'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'h%le'; +fld3 +honeysuckle +select t2.fld3 from t2 where fld3 LIKE 'honeysuckle_'; +fld3 +select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%'; +fld3 +explain select t2.fld3 from t2 where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index +explain select fld3 from t2 ignore index (fld3) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select fld3 from t2 use index (fld1) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select fld3 from t2 use index (fld3) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index +explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index +explain select fld3 from t2 ignore index (fld3,not_used); +ERROR 42000: Key column 'not_used' doesn't exist in table +explain select fld3 from t2 use index (not_used); +ERROR 42000: Key column 'not_used' doesn't exist in table +select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3; +fld3 +honeysuckle +honoring +explain select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range fld3 fld3 30 NULL 2 Using where; Using index +select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3; +fld1 fld3 +148504 Colombo +068305 Colombo +000000 nondecreasing +select fld1,fld3 from t2 where companynr = 37 and fld3 = 'appendixes'; +fld1 fld3 +232605 appendixes +1232605 appendixes +1232606 appendixes +1232607 appendixes +1232608 appendixes +1232609 appendixes +select fld1 from t2 where fld1=250501 or fld1="250502"; +fld1 +250501 +250502 +explain select fld1 from t2 where fld1=250501 or fld1="250502"; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range fld1 fld1 4 NULL 2 Using where; Using index +select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502; +fld1 +250501 +250502 +250505 +250601 +explain select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range fld1 fld1 4 NULL 4 Using where; Using index +select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%'; +fld1 fld3 +218401 faithful +018007 fanatic +228311 fated +018017 featherweight +218022 feed +088303 feminine +058004 Fenton +038017 fetched +018054 fetters +208101 fiftieth +238007 filial +013606 fingerings +218008 finishers +038205 firearm +188505 fitting +202301 Fitzpatrick +238008 fixedly +012001 flanking +018103 flint +018104 flopping +188007 flurried +013602 foldout +226205 foothill +232102 forgivably +228306 forthcoming +186002 freakish +208113 freest +231315 freezes +036002 funereal +226209 furnishings +198006 furthermore +select fld3 from t2 where fld3 like "L%" and fld3 = "ok"; +fld3 +select fld3 from t2 where (fld3 like "C%" and fld3 = "Chantilly"); +fld3 +Chantilly +select fld1,fld3 from t2 where fld1 like "25050%"; +fld1 fld3 +250501 poisoning +250502 Iraqis +250503 heaving +250504 population +250505 bomb +select fld1,fld3 from t2 where fld1 like "25050_"; +fld1 fld3 +250501 poisoning +250502 Iraqis +250503 heaving +250504 population +250505 bomb +select distinct companynr from t2; +companynr +00 +37 +36 +50 +58 +29 +40 +53 +65 +41 +34 +68 +select distinct companynr from t2 order by companynr; +companynr +00 +29 +34 +36 +37 +40 +41 +50 +53 +58 +65 +68 +select distinct companynr from t2 order by companynr desc; +companynr +68 +65 +58 +53 +50 +41 +40 +37 +36 +34 +29 +00 +select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; +fld3 period +obliterates 9410 +offload 9410 +opaquely 9410 +organizer 9410 +overestimating 9410 +overlay 9410 +select distinct fld3 from t2 where companynr = 34 order by fld3; +fld3 +absentee +accessed +ahead +alphabetic +Asiaticizations +attitude +aye +bankruptcies +belays +Blythe +bomb +boulevard +bulldozes +cannot +caressing +charcoal +checksumming +chess +clubroom +colorful +cosy +creator +crying +Darius +diffusing +duality +Eiffel +Epiphany +Ernestine +explorers +exterminated +famine +forked +Gershwins +heaving +Hodges +Iraqis +Italianization +Lagos +landslide +libretto +Majorca +mastering +narrowed +occurred +offerers +Palestine +Peruvianizes +pharmaceutic +poisoning +population +Pygmalion +rats +realest +recording +regimented +retransmitting +reviver +rouses +scars +sicker +sleepwalk +stopped +sugars +translatable +uncles +unexpected +uprisings +versatility +vest +select distinct fld3 from t2 limit 10; +fld3 +abates +abiding +Abraham +abrogating +absentee +abut +accessed +accruing +accumulating +accuracies +select distinct fld3 from t2 having fld3 like "A%" limit 10; +fld3 +abates +abiding +Abraham +abrogating +absentee +abut +accessed +accruing +accumulating +accuracies +select distinct substring(fld3,1,3) from t2 where fld3 like "A%"; +substring(fld3,1,3) +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +Adl +adm +Ado +ads +adv +aer +aff +afi +afl +afo +agi +ahe +aim +air +Ald +alg +ali +all +alp +alr +ama +ame +amm +ana +and +ane +Ang +ani +Ann +Ant +api +app +aqu +Ara +arc +Arm +arr +Art +Asi +ask +asp +ass +ast +att +aud +Aug +aut +ave +avo +awe +aye +Azt +select distinct substring(fld3,1,3) as a from t2 having a like "A%" order by a limit 10; +a +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +select distinct substring(fld3,1,3) from t2 where fld3 like "A%" limit 10; +substring(fld3,1,3) +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +select distinct substring(fld3,1,3) as a from t2 having a like "A%" limit 10; +a +aba +abi +Abr +abs +abu +acc +acq +acu +Ade +adj +create table t3 ( +period int not null, +name char(32) not null, +companynr int not null, +price double(11,0), +price2 double(11,0), +key (period), +key (name) +); +create temporary table tmp engine = myisam select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +insert into tmp select * from t3; +insert into t3 select * from tmp; +alter table t3 add t2nr int not null auto_increment primary key first; +drop table tmp; +SET SQL_BIG_TABLES=1; +select distinct concat(fld3," ",fld3) as namn from t2,t3 where t2.fld1=t3.t2nr order by namn limit 10; +namn +Abraham Abraham +abrogating abrogating +admonishing admonishing +Adolph Adolph +afield afield +aging aging +ammonium ammonium +analyzable analyzable +animals animals +animized animized +SET SQL_BIG_TABLES=0; +select distinct concat(fld3," ",fld3) from t2,t3 where t2.fld1=t3.t2nr order by fld3 limit 10; +concat(fld3," ",fld3) +Abraham Abraham +abrogating abrogating +admonishing admonishing +Adolph Adolph +afield afield +aging aging +ammonium ammonium +analyzable analyzable +animals animals +animized animized +select distinct fld5 from t2 limit 10; +fld5 +neat +Steinberg +jarring +tinily +balled +persist +attainments +fanatic +measures +rightfulness +select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10; +fld3 count(*) +affixed 1 +and 1 +annoyers 1 +Anthony 1 +assayed 1 +assurers 1 +attendants 1 +bedlam 1 +bedpost 1 +boasted 1 +SET SQL_BIG_TABLES=1; +select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10; +fld3 count(*) +affixed 1 +and 1 +annoyers 1 +Anthony 1 +assayed 1 +assurers 1 +attendants 1 +bedlam 1 +bedpost 1 +boasted 1 +SET SQL_BIG_TABLES=0; +select distinct fld3,repeat("a",length(fld3)),count(*) from t2 group by companynr,fld3 limit 100,10; +fld3 repeat("a",length(fld3)) count(*) +circus aaaaaa 1 +cited aaaaa 1 +Colombo aaaaaaa 1 +congresswoman aaaaaaaaaaaaa 1 +contrition aaaaaaaaaa 1 +corny aaaaa 1 +cultivation aaaaaaaaaaa 1 +definiteness aaaaaaaaaaaa 1 +demultiplex aaaaaaaaaaa 1 +disappointing aaaaaaaaaaaaa 1 +select distinct companynr,rtrim(space(512+companynr)) from t3 order by 1,2; +companynr rtrim(space(512+companynr)) +37 +78 +101 +154 +311 +447 +512 +select distinct fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by fld3; +fld3 +explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index +explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort +1 SIMPLE t3 ref period period 4 test.t1.period 4181 +explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 index period period 4 NULL 41810 +1 SIMPLE t1 ref period period 4 test.t3.period 4181 +explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index period period 4 NULL 41810 +1 SIMPLE t3 ref period period 4 test.t1.period 4181 +select period from t1; +period +9410 +select period from t1 where period=1900; +period +select fld3,period from t1,t2 where fld1 = 011401 order by period; +fld3 period +breaking 9410 +select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; +fld3 period +breaking 1001 +explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 const fld1 fld1 4 const 1 +1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 +select fld3,period from t2,t1 where companynr*10 = 37*10; +fld3 period +breaking 9410 +Romans 9410 +intercepted 9410 +bewilderingly 9410 +astound 9410 +admonishing 9410 +sumac 9410 +flanking 9410 +combed 9410 +subjective 9410 +scatterbrain 9410 +Eulerian 9410 +Kane 9410 +overlay 9410 +perturb 9410 +goblins 9410 +annihilates 9410 +Wotan 9410 +snatching 9410 +concludes 9410 +laterally 9410 +yelped 9410 +grazing 9410 +Baird 9410 +celery 9410 +misunderstander 9410 +handgun 9410 +foldout 9410 +mystic 9410 +succumbed 9410 +Nabisco 9410 +fingerings 9410 +aging 9410 +afield 9410 +ammonium 9410 +boat 9410 +intelligibility 9410 +Augustine 9410 +teethe 9410 +dreaded 9410 +scholastics 9410 +audiology 9410 +wallet 9410 +parters 9410 +eschew 9410 +quitter 9410 +neat 9410 +Steinberg 9410 +jarring 9410 +tinily 9410 +balled 9410 +persist 9410 +attainments 9410 +fanatic 9410 +measures 9410 +rightfulness 9410 +capably 9410 +impulsive 9410 +starlet 9410 +terminators 9410 +untying 9410 +announces 9410 +featherweight 9410 +pessimist 9410 +daughter 9410 +decliner 9410 +lawgiver 9410 +stated 9410 +readable 9410 +attrition 9410 +cascade 9410 +motors 9410 +interrogate 9410 +pests 9410 +stairway 9410 +dopers 9410 +testicle 9410 +Parsifal 9410 +leavings 9410 +postulation 9410 +squeaking 9410 +contrasted 9410 +leftover 9410 +whiteners 9410 +erases 9410 +Punjab 9410 +Merritt 9410 +Quixotism 9410 +sweetish 9410 +dogging 9410 +scornfully 9410 +bellow 9410 +bills 9410 +cupboard 9410 +sureties 9410 +puddings 9410 +fetters 9410 +bivalves 9410 +incurring 9410 +Adolph 9410 +pithed 9410 +Miles 9410 +trimmings 9410 +tragedies 9410 +skulking 9410 +flint 9410 +flopping 9410 +relaxing 9410 +offload 9410 +suites 9410 +lists 9410 +animized 9410 +multilayer 9410 +standardizes 9410 +Judas 9410 +vacuuming 9410 +dentally 9410 +humanness 9410 +inch 9410 +Weissmuller 9410 +irresponsibly 9410 +luckily 9410 +culled 9410 +medical 9410 +bloodbath 9410 +subschema 9410 +animals 9410 +Micronesia 9410 +repetitions 9410 +Antares 9410 +ventilate 9410 +pityingly 9410 +interdependent 9410 +Graves 9410 +neonatal 9410 +chafe 9410 +honoring 9410 +realtor 9410 +elite 9410 +funereal 9410 +abrogating 9410 +sorters 9410 +Conley 9410 +lectured 9410 +Abraham 9410 +Hawaii 9410 +cage 9410 +hushes 9410 +Simla 9410 +reporters 9410 +Dutchman 9410 +descendants 9410 +groupings 9410 +dissociate 9410 +coexist 9410 +Beebe 9410 +Taoism 9410 +Connally 9410 +fetched 9410 +checkpoints 9410 +rusting 9410 +galling 9410 +obliterates 9410 +traitor 9410 +resumes 9410 +analyzable 9410 +terminator 9410 +gritty 9410 +firearm 9410 +minima 9410 +Selfridge 9410 +disable 9410 +witchcraft 9410 +betroth 9410 +Manhattanize 9410 +imprint 9410 +peeked 9410 +swelling 9410 +interrelationships 9410 +riser 9410 +Gandhian 9410 +peacock 9410 +bee 9410 +kanji 9410 +dental 9410 +scarf 9410 +chasm 9410 +insolence 9410 +syndicate 9410 +alike 9410 +imperial 9410 +convulsion 9410 +railway 9410 +validate 9410 +normalizes 9410 +comprehensive 9410 +chewing 9410 +denizen 9410 +schemer 9410 +chronicle 9410 +Kline 9410 +Anatole 9410 +partridges 9410 +brunch 9410 +recruited 9410 +dimensions 9410 +Chicana 9410 +announced 9410 +praised 9410 +employing 9410 +linear 9410 +quagmire 9410 +western 9410 +relishing 9410 +serving 9410 +scheduling 9410 +lore 9410 +eventful 9410 +arteriole 9410 +disentangle 9410 +cured 9410 +Fenton 9410 +avoidable 9410 +drains 9410 +detectably 9410 +husky 9410 +impelling 9410 +undoes 9410 +evened 9410 +squeezes 9410 +destroyer 9410 +rudeness 9410 +beaner 9410 +boorish 9410 +Everhart 9410 +encompass 9410 +mushrooms 9410 +Alison 9410 +externally 9410 +pellagra 9410 +cult 9410 +creek 9410 +Huffman 9410 +Majorca 9410 +governing 9410 +gadfly 9410 +reassigned 9410 +intentness 9410 +craziness 9410 +psychic 9410 +squabbled 9410 +burlesque 9410 +capped 9410 +extracted 9410 +DiMaggio 9410 +exclamation 9410 +subdirectory 9410 +Gothicism 9410 +feminine 9410 +metaphysically 9410 +sanding 9410 +Miltonism 9410 +freakish 9410 +index 9410 +straight 9410 +flurried 9410 +denotative 9410 +coming 9410 +commencements 9410 +gentleman 9410 +gifted 9410 +Shanghais 9410 +sportswriting 9410 +sloping 9410 +navies 9410 +leaflet 9410 +shooter 9410 +Joplin 9410 +babies 9410 +assails 9410 +admiring 9410 +swaying 9410 +Goldstine 9410 +fitting 9410 +Norwalk 9410 +analogy 9410 +deludes 9410 +cokes 9410 +Clayton 9410 +exhausts 9410 +causality 9410 +sating 9410 +icon 9410 +throttles 9410 +communicants 9410 +dehydrate 9410 +priceless 9410 +publicly 9410 +incidentals 9410 +commonplace 9410 +mumbles 9410 +furthermore 9410 +cautioned 9410 +parametrized 9410 +registration 9410 +sadly 9410 +positioning 9410 +babysitting 9410 +eternal 9410 +hoarder 9410 +congregates 9410 +rains 9410 +workers 9410 +sags 9410 +unplug 9410 +garage 9410 +boulder 9410 +specifics 9410 +Teresa 9410 +Winsett 9410 +convenient 9410 +buckboards 9410 +amenities 9410 +resplendent 9410 +sews 9410 +participated 9410 +Simon 9410 +certificates 9410 +Fitzpatrick 9410 +Evanston 9410 +misted 9410 +textures 9410 +save 9410 +count 9410 +rightful 9410 +chaperone 9410 +Lizzy 9410 +clenched 9410 +effortlessly 9410 +accessed 9410 +beaters 9410 +Hornblower 9410 +vests 9410 +indulgences 9410 +infallibly 9410 +unwilling 9410 +excrete 9410 +spools 9410 +crunches 9410 +overestimating 9410 +ineffective 9410 +humiliation 9410 +sophomore 9410 +star 9410 +rifles 9410 +dialysis 9410 +arriving 9410 +indulge 9410 +clockers 9410 +languages 9410 +Antarctica 9410 +percentage 9410 +ceiling 9410 +specification 9410 +regimented 9410 +ciphers 9410 +pictures 9410 +serpents 9410 +allot 9410 +realized 9410 +mayoral 9410 +opaquely 9410 +hostess 9410 +fiftieth 9410 +incorrectly 9410 +decomposition 9410 +stranglings 9410 +mixture 9410 +electroencephalography 9410 +similarities 9410 +charges 9410 +freest 9410 +Greenberg 9410 +tinting 9410 +expelled 9410 +warm 9410 +smoothed 9410 +deductions 9410 +Romano 9410 +bitterroot 9410 +corset 9410 +securing 9410 +environing 9410 +cute 9410 +Crays 9410 +heiress 9410 +inform 9410 +avenge 9410 +universals 9410 +Kinsey 9410 +ravines 9410 +bestseller 9410 +equilibrium 9410 +extents 9410 +relatively 9410 +pressure 9410 +critiques 9410 +befouled 9410 +rightfully 9410 +mechanizing 9410 +Latinizes 9410 +timesharing 9410 +Aden 9410 +embassies 9410 +males 9410 +shapelessly 9410 +mastering 9410 +Newtonian 9410 +finishers 9410 +abates 9410 +teem 9410 +kiting 9410 +stodgy 9410 +feed 9410 +guitars 9410 +airships 9410 +store 9410 +denounces 9410 +Pyle 9410 +Saxony 9410 +serializations 9410 +Peruvian 9410 +taxonomically 9410 +kingdom 9410 +stint 9410 +Sault 9410 +faithful 9410 +Ganymede 9410 +tidiness 9410 +gainful 9410 +contrary 9410 +Tipperary 9410 +tropics 9410 +theorizers 9410 +renew 9410 +already 9410 +terminal 9410 +Hegelian 9410 +hypothesizer 9410 +warningly 9410 +journalizing 9410 +nested 9410 +Lars 9410 +saplings 9410 +foothill 9410 +labeled 9410 +imperiously 9410 +reporters 9410 +furnishings 9410 +precipitable 9410 +discounts 9410 +excises 9410 +Stalin 9410 +despot 9410 +ripeness 9410 +Arabia 9410 +unruly 9410 +mournfulness 9410 +boom 9410 +slaughter 9410 +Sabine 9410 +handy 9410 +rural 9410 +organizer 9410 +shipyard 9410 +civics 9410 +inaccuracy 9410 +rules 9410 +juveniles 9410 +comprised 9410 +investigations 9410 +stabilizes 9410 +seminaries 9410 +Hunter 9410 +sporty 9410 +test 9410 +weasels 9410 +CERN 9410 +tempering 9410 +afore 9410 +Galatean 9410 +techniques 9410 +error 9410 +veranda 9410 +severely 9410 +Cassites 9410 +forthcoming 9410 +guides 9410 +vanish 9410 +lied 9410 +sawtooth 9410 +fated 9410 +gradually 9410 +widens 9410 +preclude 9410 +evenhandedly 9410 +percentage 9410 +disobedience 9410 +humility 9410 +gleaning 9410 +petted 9410 +bloater 9410 +minion 9410 +marginal 9410 +apiary 9410 +measures 9410 +precaution 9410 +repelled 9410 +primary 9410 +coverings 9410 +Artemia 9410 +navigate 9410 +spatial 9410 +Gurkha 9410 +meanwhile 9410 +Melinda 9410 +Butterfield 9410 +Aldrich 9410 +previewing 9410 +glut 9410 +unaffected 9410 +inmate 9410 +mineral 9410 +impending 9410 +meditation 9410 +ideas 9410 +miniaturizes 9410 +lewdly 9410 +title 9410 +youthfulness 9410 +creak 9410 +Chippewa 9410 +clamored 9410 +freezes 9410 +forgivably 9410 +reduce 9410 +McGovern 9410 +Nazis 9410 +epistle 9410 +socializes 9410 +conceptions 9410 +Kevin 9410 +uncovering 9410 +chews 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +appendixes 9410 +raining 9410 +infest 9410 +compartment 9410 +minting 9410 +ducks 9410 +roped 9410 +waltz 9410 +Lillian 9410 +repressions 9410 +chillingly 9410 +noncritical 9410 +lithograph 9410 +spongers 9410 +parenthood 9410 +posed 9410 +instruments 9410 +filial 9410 +fixedly 9410 +relives 9410 +Pandora 9410 +watering 9410 +ungrateful 9410 +secures 9410 +poison 9410 +dusted 9410 +encompasses 9410 +presentation 9410 +Kantian 9410 +select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; +fld3 period price price2 +admonishing 1002 28357832 8723648 +analyzable 1002 28357832 8723648 +annihilates 1001 5987435 234724 +Antares 1002 28357832 8723648 +astound 1001 5987435 234724 +audiology 1001 5987435 234724 +Augustine 1002 28357832 8723648 +Baird 1002 28357832 8723648 +bewilderingly 1001 5987435 234724 +breaking 1001 5987435 234724 +Conley 1001 5987435 234724 +dentally 1002 28357832 8723648 +dissociate 1002 28357832 8723648 +elite 1001 5987435 234724 +eschew 1001 5987435 234724 +Eulerian 1001 5987435 234724 +flanking 1001 5987435 234724 +foldout 1002 28357832 8723648 +funereal 1002 28357832 8723648 +galling 1002 28357832 8723648 +Graves 1001 5987435 234724 +grazing 1001 5987435 234724 +groupings 1001 5987435 234724 +handgun 1001 5987435 234724 +humility 1002 28357832 8723648 +impulsive 1002 28357832 8723648 +inch 1001 5987435 234724 +intelligibility 1001 5987435 234724 +jarring 1001 5987435 234724 +lawgiver 1001 5987435 234724 +lectured 1002 28357832 8723648 +Merritt 1002 28357832 8723648 +neonatal 1001 5987435 234724 +offload 1002 28357832 8723648 +parters 1002 28357832 8723648 +pityingly 1002 28357832 8723648 +puddings 1002 28357832 8723648 +Punjab 1001 5987435 234724 +quitter 1002 28357832 8723648 +realtor 1001 5987435 234724 +relaxing 1001 5987435 234724 +repetitions 1001 5987435 234724 +resumes 1001 5987435 234724 +Romans 1002 28357832 8723648 +rusting 1001 5987435 234724 +scholastics 1001 5987435 234724 +skulking 1002 28357832 8723648 +stated 1002 28357832 8723648 +suites 1002 28357832 8723648 +sureties 1001 5987435 234724 +testicle 1002 28357832 8723648 +tinily 1002 28357832 8723648 +tragedies 1001 5987435 234724 +trimmings 1001 5987435 234724 +vacuuming 1001 5987435 234724 +ventilate 1001 5987435 234724 +wallet 1001 5987435 234724 +Weissmuller 1002 28357832 8723648 +Wotan 1002 28357832 8723648 +select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; +fld1 fld3 period price price2 +018201 relaxing 1001 5987435 234724 +018601 vacuuming 1001 5987435 234724 +018801 inch 1001 5987435 234724 +018811 repetitions 1001 5987435 234724 +create table t4 ( +companynr tinyint(2) unsigned zerofill NOT NULL default '00', +companyname char(30) NOT NULL default '', +PRIMARY KEY (companynr), +UNIQUE KEY companyname(companyname) +) ENGINE=MyISAM MAX_ROWS=50 PACK_KEYS=1 COMMENT='companynames'; +select STRAIGHT_JOIN t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr; +companynr companyname +00 Unknown +29 company 1 +34 company 2 +36 company 3 +37 company 4 +40 company 5 +41 company 6 +50 company 11 +53 company 7 +58 company 8 +65 company 9 +68 company 10 +select SQL_SMALL_RESULT t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr; +companynr companyname +00 Unknown +29 company 1 +34 company 2 +36 company 3 +37 company 4 +40 company 5 +41 company 6 +50 company 11 +53 company 7 +58 company 8 +65 company 9 +68 company 10 +select * from t1,t1 t12; +Period Varor_period Period Varor_period +9410 9412 9410 9412 +select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; +fld1 fld1 +250501 250501 +250502 250501 +250503 250501 +250504 250501 +250505 250501 +250501 250502 +250502 250502 +250503 250502 +250504 250502 +250505 250502 +250501 250503 +250502 250503 +250503 250503 +250504 250503 +250505 250503 +250501 250504 +250502 250504 +250503 250504 +250504 250504 +250505 250504 +250501 250505 +250502 250505 +250503 250505 +250504 250505 +250505 250505 +insert into t2 (fld1, companynr) values (999999,99); +select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +companynr companyname +99 NULL +select count(*) from t2 left join t4 using (companynr) where t4.companynr is not null; +count(*) +1199 +explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 Using where; Not exists +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Not exists +select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; +companynr companyname +select count(*) from t2 left join t4 using (companynr) where companynr is not null; +count(*) +1200 +explain select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +delete from t2 where fld1=999999; +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; +companynr companynr +37 36 +41 40 +explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; +fld1 companynr fld3 period +038008 37 reporters 1008 +038208 37 Selfridge 1008 +select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; +fld1 companynr fld3 period +038008 37 reporters 1008 +038208 37 Selfridge 1008 +select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; +fld1 companynr fld3 period +038008 37 reporters 1008 +038208 37 Selfridge 1008 +select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); +period +9410 +select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); +period +9410 +select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; +fld1 +250501 +250502 +250503 +250505 +select fld1 from t2 where fld1 in (250502,98005,98006,250503,250605,250606) and fld1 >=250502 and fld1 not in (250605,250606); +fld1 +250502 +250503 +select fld1 from t2 where fld1 between 250502 and 250504; +fld1 +250502 +250503 +250504 +select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld3 like "L%" or fld3 like "G%")) and fld3 like "L%" ; +fld3 +label +labeled +labeled +landslide +laterally +leaflet +lewdly +Lillian +luckily +select count(*) from t1; +count(*) +1 +select companynr,count(*),sum(fld1) from t2 group by companynr; +companynr count(*) sum(fld1) +00 82 10355753 +29 95 14473298 +34 70 17788966 +36 215 22786296 +37 588 83602098 +40 37 6618386 +41 52 12816335 +50 11 1595438 +53 4 793210 +58 23 2254293 +65 10 2284055 +68 12 3097288 +select companynr,count(*) from t2 group by companynr order by companynr desc limit 5; +companynr count(*) +68 12 +65 10 +58 23 +53 4 +50 11 +select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>""; +count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1) +70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069 +explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>""; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where +Warnings: +Note 1003 select count(0) AS `count(*)`,min(`test`.`t2`.`fld4`) AS `min(fld4)`,max(`test`.`t2`.`fld4`) AS `max(fld4)`,sum(`test`.`t2`.`fld1`) AS `sum(fld1)`,avg(`test`.`t2`.`fld1`) AS `avg(fld1)`,std(`test`.`t2`.`fld1`) AS `std(fld1)`,variance(`test`.`t2`.`fld1`) AS `variance(fld1)` from `test`.`t2` where ((`test`.`t2`.`companynr` = 34) and (`test`.`t2`.`fld4` <> _latin1'')) +select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3; +companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1) +00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087 +29 95 abut wetness 14473298 152350.5053 8368.5480 70032594.9026 +34 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069 +select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; +companynr t2nr count(price) sum(price) min(price) max(price) avg(price) +37 1 1 5987435 5987435 5987435 5987435.0000 +37 2 1 28357832 28357832 28357832 28357832.0000 +37 3 1 39654943 39654943 39654943 39654943.0000 +37 11 1 5987435 5987435 5987435 5987435.0000 +37 12 1 28357832 28357832 28357832 28357832.0000 +37 13 1 39654943 39654943 39654943 39654943.0000 +37 21 1 5987435 5987435 5987435 5987435.0000 +37 22 1 28357832 28357832 28357832 28357832.0000 +37 23 1 39654943 39654943 39654943 39654943.0000 +37 31 1 5987435 5987435 5987435 5987435.0000 +select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; +companynr t2nr count(price) sum(price) min(price) max(price) avg(price) +37 1 1 5987435 5987435 5987435 5987435.0000 +37 2 1 28357832 28357832 28357832 28357832.0000 +37 3 1 39654943 39654943 39654943 39654943.0000 +37 11 1 5987435 5987435 5987435 5987435.0000 +37 12 1 28357832 28357832 28357832 28357832.0000 +37 13 1 39654943 39654943 39654943 39654943.0000 +37 21 1 5987435 5987435 5987435 5987435.0000 +37 22 1 28357832 28357832 28357832 28357832.0000 +37 23 1 39654943 39654943 39654943 39654943.0000 +37 31 1 5987435 5987435 5987435 5987435.0000 +select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ; +companynr count(price) sum(price) min(price) max(price) avg(price) +37 12543 309394878010 5987435 39654943 24666736.6667 +78 8362 414611089292 726498 98439034 49582766.0000 +101 4181 3489454238 834598 834598 834598.0000 +154 4181 4112197254950 983543950 983543950 983543950.0000 +311 4181 979599938 234298 234298 234298.0000 +447 4181 9929180954 2374834 2374834 2374834.0000 +512 4181 3288532102 786542 786542 786542.0000 +select distinct mod(companynr,10) from t4 group by companynr; +mod(companynr,10) +0 +9 +4 +6 +7 +1 +3 +8 +5 +select distinct 1 from t4 group by companynr; +1 +1 +select count(distinct fld1) from t2; +count(distinct fld1) +1199 +select companynr,count(distinct fld1) from t2 group by companynr; +companynr count(distinct fld1) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(*) from t2 group by companynr; +companynr count(*) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(distinct concat(fld1,repeat(65,1000))) from t2 group by companynr; +companynr count(distinct concat(fld1,repeat(65,1000))) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(distinct concat(fld1,repeat(65,200))) from t2 group by companynr; +companynr count(distinct concat(fld1,repeat(65,200))) +00 82 +29 95 +34 70 +36 215 +37 588 +40 37 +41 52 +50 11 +53 4 +58 23 +65 10 +68 12 +select companynr,count(distinct floor(fld1/100)) from t2 group by companynr; +companynr count(distinct floor(fld1/100)) +00 47 +29 35 +34 14 +36 69 +37 108 +40 16 +41 11 +50 9 +53 1 +58 1 +65 1 +68 1 +select companynr,count(distinct concat(repeat(65,1000),floor(fld1/100))) from t2 group by companynr; +companynr count(distinct concat(repeat(65,1000),floor(fld1/100))) +00 47 +29 35 +34 14 +36 69 +37 108 +40 16 +41 11 +50 9 +53 1 +58 1 +65 1 +68 1 +select sum(fld1),fld3 from t2 where fld3="Romans" group by fld1 limit 10; +sum(fld1) fld3 +11402 Romans +select name,count(*) from t3 where name='cloakroom' group by name; +name count(*) +cloakroom 4181 +select name,count(*) from t3 where name='cloakroom' and price>10 group by name; +name count(*) +cloakroom 4181 +select count(*) from t3 where name='cloakroom' and price2=823742; +count(*) +4181 +select name,count(*) from t3 where name='cloakroom' and price2=823742 group by name; +name count(*) +cloakroom 4181 +select name,count(*) from t3 where name >= "extramarital" and price <= 39654943 group by name; +name count(*) +extramarital 4181 +gazer 4181 +gems 4181 +Iranizes 4181 +spates 4181 +tucked 4181 +violinist 4181 +select t2.fld3,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; +fld3 count(*) +spates 4181 +select companynr|0,companyname from t4 group by 1; +companynr|0 companyname +0 Unknown +29 company 1 +34 company 2 +36 company 3 +37 company 4 +40 company 5 +41 company 6 +50 company 11 +53 company 7 +58 company 8 +65 company 9 +68 company 10 +select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by t2.companynr order by companyname; +companynr companyname count(*) +29 company 1 95 +68 company 10 12 +50 company 11 11 +34 company 2 70 +36 company 3 215 +37 company 4 588 +40 company 5 37 +41 company 6 52 +53 company 7 4 +58 company 8 23 +65 company 9 10 +00 Unknown 82 +select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; +fld1 count(*) +158402 4181 +select sum(Period)/count(*) from t1; +sum(Period)/count(*) +9410.0000 +select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; +companynr count sum diff func +37 12543 309394878010 0.0000 464091 +78 8362 414611089292 0.0000 652236 +101 4181 3489454238 0.0000 422281 +154 4181 4112197254950 0.0000 643874 +311 4181 979599938 0.0000 1300291 +447 4181 9929180954 0.0000 1868907 +512 4181 3288532102 0.0000 2140672 +select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg; +companynr avg +154 983543950.0000 +select companynr,count(*) from t2 group by companynr order by 2 desc; +companynr count(*) +37 588 +36 215 +29 95 +00 82 +34 70 +41 52 +40 37 +58 23 +68 12 +50 11 +65 10 +53 4 +select companynr,count(*) from t2 where companynr > 40 group by companynr order by 2 desc; +companynr count(*) +41 52 +58 23 +68 12 +50 11 +65 10 +53 4 +select t2.fld4,t2.fld1,count(price),sum(price),min(price),max(price),avg(price) from t3,t2 where t3.companynr = 37 and t2.fld1 = t3.t2nr group by fld1,t2.fld4; +fld4 fld1 count(price) sum(price) min(price) max(price) avg(price) +teethe 000001 1 5987435 5987435 5987435 5987435.0000 +dreaded 011401 1 5987435 5987435 5987435 5987435.0000 +scholastics 011402 1 28357832 28357832 28357832 28357832.0000 +audiology 011403 1 39654943 39654943 39654943 39654943.0000 +wallet 011501 1 5987435 5987435 5987435 5987435.0000 +parters 011701 1 5987435 5987435 5987435 5987435.0000 +eschew 011702 1 28357832 28357832 28357832 28357832.0000 +quitter 011703 1 39654943 39654943 39654943 39654943.0000 +neat 012001 1 5987435 5987435 5987435 5987435.0000 +Steinberg 012003 1 39654943 39654943 39654943 39654943.0000 +balled 012301 1 5987435 5987435 5987435 5987435.0000 +persist 012302 1 28357832 28357832 28357832 28357832.0000 +attainments 012303 1 39654943 39654943 39654943 39654943.0000 +capably 012501 1 5987435 5987435 5987435 5987435.0000 +impulsive 012602 1 28357832 28357832 28357832 28357832.0000 +starlet 012603 1 39654943 39654943 39654943 39654943.0000 +featherweight 012701 1 5987435 5987435 5987435 5987435.0000 +pessimist 012702 1 28357832 28357832 28357832 28357832.0000 +daughter 012703 1 39654943 39654943 39654943 39654943.0000 +lawgiver 013601 1 5987435 5987435 5987435 5987435.0000 +stated 013602 1 28357832 28357832 28357832 28357832.0000 +readable 013603 1 39654943 39654943 39654943 39654943.0000 +testicle 013801 1 5987435 5987435 5987435 5987435.0000 +Parsifal 013802 1 28357832 28357832 28357832 28357832.0000 +leavings 013803 1 39654943 39654943 39654943 39654943.0000 +squeaking 013901 1 5987435 5987435 5987435 5987435.0000 +contrasted 016001 1 5987435 5987435 5987435 5987435.0000 +leftover 016201 1 5987435 5987435 5987435 5987435.0000 +whiteners 016202 1 28357832 28357832 28357832 28357832.0000 +erases 016301 1 5987435 5987435 5987435 5987435.0000 +Punjab 016302 1 28357832 28357832 28357832 28357832.0000 +Merritt 016303 1 39654943 39654943 39654943 39654943.0000 +sweetish 018001 1 5987435 5987435 5987435 5987435.0000 +dogging 018002 1 28357832 28357832 28357832 28357832.0000 +scornfully 018003 1 39654943 39654943 39654943 39654943.0000 +fetters 018012 1 28357832 28357832 28357832 28357832.0000 +bivalves 018013 1 39654943 39654943 39654943 39654943.0000 +skulking 018021 1 5987435 5987435 5987435 5987435.0000 +flint 018022 1 28357832 28357832 28357832 28357832.0000 +flopping 018023 1 39654943 39654943 39654943 39654943.0000 +Judas 018032 1 28357832 28357832 28357832 28357832.0000 +vacuuming 018033 1 39654943 39654943 39654943 39654943.0000 +medical 018041 1 5987435 5987435 5987435 5987435.0000 +bloodbath 018042 1 28357832 28357832 28357832 28357832.0000 +subschema 018043 1 39654943 39654943 39654943 39654943.0000 +interdependent 018051 1 5987435 5987435 5987435 5987435.0000 +Graves 018052 1 28357832 28357832 28357832 28357832.0000 +neonatal 018053 1 39654943 39654943 39654943 39654943.0000 +sorters 018061 1 5987435 5987435 5987435 5987435.0000 +epistle 018062 1 28357832 28357832 28357832 28357832.0000 +Conley 018101 1 5987435 5987435 5987435 5987435.0000 +lectured 018102 1 28357832 28357832 28357832 28357832.0000 +Abraham 018103 1 39654943 39654943 39654943 39654943.0000 +cage 018201 1 5987435 5987435 5987435 5987435.0000 +hushes 018202 1 28357832 28357832 28357832 28357832.0000 +Simla 018402 1 28357832 28357832 28357832 28357832.0000 +reporters 018403 1 39654943 39654943 39654943 39654943.0000 +coexist 018601 1 5987435 5987435 5987435 5987435.0000 +Beebe 018602 1 28357832 28357832 28357832 28357832.0000 +Taoism 018603 1 39654943 39654943 39654943 39654943.0000 +Connally 018801 1 5987435 5987435 5987435 5987435.0000 +fetched 018802 1 28357832 28357832 28357832 28357832.0000 +checkpoints 018803 1 39654943 39654943 39654943 39654943.0000 +gritty 018811 1 5987435 5987435 5987435 5987435.0000 +firearm 018812 1 28357832 28357832 28357832 28357832.0000 +minima 019101 1 5987435 5987435 5987435 5987435.0000 +Selfridge 019102 1 28357832 28357832 28357832 28357832.0000 +disable 019103 1 39654943 39654943 39654943 39654943.0000 +witchcraft 019201 1 5987435 5987435 5987435 5987435.0000 +betroth 030501 1 5987435 5987435 5987435 5987435.0000 +Manhattanize 030502 1 28357832 28357832 28357832 28357832.0000 +imprint 030503 1 39654943 39654943 39654943 39654943.0000 +swelling 031901 1 5987435 5987435 5987435 5987435.0000 +interrelationships 036001 1 5987435 5987435 5987435 5987435.0000 +riser 036002 1 28357832 28357832 28357832 28357832.0000 +bee 038001 1 5987435 5987435 5987435 5987435.0000 +kanji 038002 1 28357832 28357832 28357832 28357832.0000 +dental 038003 1 39654943 39654943 39654943 39654943.0000 +railway 038011 1 5987435 5987435 5987435 5987435.0000 +validate 038012 1 28357832 28357832 28357832 28357832.0000 +normalizes 038013 1 39654943 39654943 39654943 39654943.0000 +Kline 038101 1 5987435 5987435 5987435 5987435.0000 +Anatole 038102 1 28357832 28357832 28357832 28357832.0000 +partridges 038103 1 39654943 39654943 39654943 39654943.0000 +recruited 038201 1 5987435 5987435 5987435 5987435.0000 +dimensions 038202 1 28357832 28357832 28357832 28357832.0000 +Chicana 038203 1 39654943 39654943 39654943 39654943.0000 +select t3.companynr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 group by companynr,fld3; +companynr fld3 sum(price) +512 boat 786542 +512 capably 786542 +512 cupboard 786542 +512 decliner 786542 +512 descendants 786542 +512 dopers 786542 +512 erases 786542 +512 Micronesia 786542 +512 Miles 786542 +512 skies 786542 +select t2.companynr,count(*),min(fld3),max(fld3),sum(price),avg(price) from t2,t3 where t3.companynr >= 30 and t3.companynr <= 58 and t3.t2nr = t2.fld1 and 1+1=2 group by t2.companynr; +companynr count(*) min(fld3) max(fld3) sum(price) avg(price) +00 1 Omaha Omaha 5987435 5987435.0000 +36 1 dubbed dubbed 28357832 28357832.0000 +37 83 Abraham Wotan 1908978016 22999735.1325 +50 2 scribbled tapestry 68012775 34006387.5000 +select t3.companynr+0,t3.t2nr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 37 group by 1,t3.t2nr,fld3,fld3,fld3,fld3,fld3 order by fld1; +t3.companynr+0 t2nr fld3 sum(price) +37 1 Omaha 5987435 +37 11401 breaking 5987435 +37 11402 Romans 28357832 +37 11403 intercepted 39654943 +37 11501 bewilderingly 5987435 +37 11701 astound 5987435 +37 11702 admonishing 28357832 +37 11703 sumac 39654943 +37 12001 flanking 5987435 +37 12003 combed 39654943 +37 12301 Eulerian 5987435 +37 12302 dubbed 28357832 +37 12303 Kane 39654943 +37 12501 annihilates 5987435 +37 12602 Wotan 28357832 +37 12603 snatching 39654943 +37 12701 grazing 5987435 +37 12702 Baird 28357832 +37 12703 celery 39654943 +37 13601 handgun 5987435 +37 13602 foldout 28357832 +37 13603 mystic 39654943 +37 13801 intelligibility 5987435 +37 13802 Augustine 28357832 +37 13803 teethe 39654943 +37 13901 scholastics 5987435 +37 16001 audiology 5987435 +37 16201 wallet 5987435 +37 16202 parters 28357832 +37 16301 eschew 5987435 +37 16302 quitter 28357832 +37 16303 neat 39654943 +37 18001 jarring 5987435 +37 18002 tinily 28357832 +37 18003 balled 39654943 +37 18012 impulsive 28357832 +37 18013 starlet 39654943 +37 18021 lawgiver 5987435 +37 18022 stated 28357832 +37 18023 readable 39654943 +37 18032 testicle 28357832 +37 18033 Parsifal 39654943 +37 18041 Punjab 5987435 +37 18042 Merritt 28357832 +37 18043 Quixotism 39654943 +37 18051 sureties 5987435 +37 18052 puddings 28357832 +37 18053 tapestry 39654943 +37 18061 trimmings 5987435 +37 18062 humility 28357832 +37 18101 tragedies 5987435 +37 18102 skulking 28357832 +37 18103 flint 39654943 +37 18201 relaxing 5987435 +37 18202 offload 28357832 +37 18402 suites 28357832 +37 18403 lists 39654943 +37 18601 vacuuming 5987435 +37 18602 dentally 28357832 +37 18603 humanness 39654943 +37 18801 inch 5987435 +37 18802 Weissmuller 28357832 +37 18803 irresponsibly 39654943 +37 18811 repetitions 5987435 +37 18812 Antares 28357832 +37 19101 ventilate 5987435 +37 19102 pityingly 28357832 +37 19103 interdependent 39654943 +37 19201 Graves 5987435 +37 30501 neonatal 5987435 +37 30502 scribbled 28357832 +37 30503 chafe 39654943 +37 31901 realtor 5987435 +37 36001 elite 5987435 +37 36002 funereal 28357832 +37 38001 Conley 5987435 +37 38002 lectured 28357832 +37 38003 Abraham 39654943 +37 38011 groupings 5987435 +37 38012 dissociate 28357832 +37 38013 coexist 39654943 +37 38101 rusting 5987435 +37 38102 galling 28357832 +37 38103 obliterates 39654943 +37 38201 resumes 5987435 +37 38202 analyzable 28357832 +37 38203 terminator 39654943 +select sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1= t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008; +sum(price) +234298 +select t2.fld1,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1 = t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008 or t3.t2nr = t2.fld1 and t2.fld1 = 38008 group by t2.fld1; +fld1 sum(price) +038008 234298 +explain select fld3 from t2 where 1>2 or 2>3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +explain select fld3 from t2 where fld1=fld1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 +select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502; +companynr fld1 +34 250501 +34 250502 +select companynr,fld1 from t2 WHERE fld1>=250501 HAVING fld1<=250502; +companynr fld1 +34 250501 +34 250502 +select companynr,count(*) as count,sum(fld1) as sum from t2 group by companynr having count > 40 and sum/count >= 120000; +companynr count sum +00 82 10355753 +29 95 14473298 +34 70 17788966 +37 588 83602098 +41 52 12816335 +select companynr from t2 group by companynr having count(*) > 40 and sum(fld1)/count(*) >= 120000 ; +companynr +00 +29 +34 +37 +41 +select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by companyname having t2.companynr >= 40; +companynr companyname count(*) +68 company 10 12 +50 company 11 11 +40 company 5 37 +41 company 6 52 +53 company 7 4 +58 company 8 23 +65 company 9 10 +select count(*) from t2; +count(*) +1199 +select count(*) from t2 where fld1 < 098024; +count(*) +387 +select min(fld1) from t2 where fld1>= 098024; +min(fld1) +98024 +select max(fld1) from t2 where fld1>= 098024; +max(fld1) +1232609 +select count(*) from t3 where price2=76234234; +count(*) +4181 +select count(*) from t3 where companynr=512 and price2=76234234; +count(*) +4181 +explain select min(fld1),max(fld1),count(*) from t2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +select min(fld1),max(fld1),count(*) from t2; +min(fld1) max(fld1) count(*) +0 1232609 1199 +select min(t2nr),max(t2nr) from t3 where t2nr=2115 and price2=823742; +min(t2nr) max(t2nr) +2115 2115 +select count(*),min(t2nr),max(t2nr) from t3 where name='spates' and companynr=78; +count(*) min(t2nr) max(t2nr) +4181 4 41804 +select t2nr,count(*) from t3 where name='gems' group by t2nr limit 20; +t2nr count(*) +9 1 +19 1 +29 1 +39 1 +49 1 +59 1 +69 1 +79 1 +89 1 +99 1 +109 1 +119 1 +129 1 +139 1 +149 1 +159 1 +169 1 +179 1 +189 1 +199 1 +select max(t2nr) from t3 where price=983543950; +max(t2nr) +41807 +select t1.period from t3 = t1 limit 1; +period +1001 +select t1.period from t1 as t1 limit 1; +period +9410 +select t1.period as "Nuvarande period" from t1 as t1 limit 1; +Nuvarande period +9410 +select period as ok_period from t1 limit 1; +ok_period +9410 +select period as ok_period from t1 group by ok_period limit 1; +ok_period +9410 +select 1+1 as summa from t1 group by summa limit 1; +summa +2 +select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; +Nuvarande period +9410 +show tables; +Tables_in_test +t1 +t2 +t3 +t4 +show tables from test like "s%"; +Tables_in_test (s%) +show tables from test like "t?"; +Tables_in_test (t?) +show full columns from t2; +Field Type Collation Null Key Default Extra Privileges Comment +auto int(11) NULL NO PRI NULL auto_increment # +fld1 int(6) unsigned zerofill NULL NO UNI 000000 # +companynr tinyint(2) unsigned zerofill NULL NO 00 # +fld3 char(30) latin1_swedish_ci NO MUL # +fld4 char(35) latin1_swedish_ci NO # +fld5 char(35) latin1_swedish_ci NO # +fld6 char(4) latin1_swedish_ci NO # +show full columns from t2 from test like 'f%'; +Field Type Collation Null Key Default Extra Privileges Comment +fld1 int(6) unsigned zerofill NULL NO UNI 000000 # +fld3 char(30) latin1_swedish_ci NO MUL # +fld4 char(35) latin1_swedish_ci NO # +fld5 char(35) latin1_swedish_ci NO # +fld6 char(4) latin1_swedish_ci NO # +show full columns from t2 from test like 's%'; +Field Type Collation Null Key Default Extra Privileges Comment +show keys from t2; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE +t2 0 fld1 1 fld1 A 1199 NULL NULL BTREE +t2 1 fld3 1 fld3 A NULL NULL NULL BTREE +drop table t4, t3, t2, t1; +CREATE TABLE t1 ( +cont_nr int(11) NOT NULL auto_increment, +ver_nr int(11) NOT NULL default '0', +aufnr int(11) NOT NULL default '0', +username varchar(50) NOT NULL default '', +hdl_nr int(11) NOT NULL default '0', +eintrag date NOT NULL default '0000-00-00', +st_klasse varchar(40) NOT NULL default '', +st_wert varchar(40) NOT NULL default '', +st_zusatz varchar(40) NOT NULL default '', +st_bemerkung varchar(255) NOT NULL default '', +kunden_art varchar(40) NOT NULL default '', +mcbs_knr int(11) default NULL, +mcbs_aufnr int(11) NOT NULL default '0', +schufa_status char(1) default '?', +bemerkung text, +wirknetz text, +wf_igz int(11) NOT NULL default '0', +tarifcode varchar(80) default NULL, +recycle char(1) default NULL, +sim varchar(30) default NULL, +mcbs_tpl varchar(30) default NULL, +emp_nr int(11) NOT NULL default '0', +laufzeit int(11) default NULL, +hdl_name varchar(30) default NULL, +prov_hdl_nr int(11) NOT NULL default '0', +auto_wirknetz varchar(50) default NULL, +auto_billing varchar(50) default NULL, +touch timestamp NOT NULL, +kategorie varchar(50) default NULL, +kundentyp varchar(20) NOT NULL default '', +sammel_rech_msisdn varchar(30) NOT NULL default '', +p_nr varchar(9) NOT NULL default '', +suffix char(3) NOT NULL default '', +PRIMARY KEY (cont_nr), +KEY idx_aufnr(aufnr), +KEY idx_hdl_nr(hdl_nr), +KEY idx_st_klasse(st_klasse), +KEY ver_nr(ver_nr), +KEY eintrag_idx(eintrag), +KEY emp_nr_idx(emp_nr), +KEY wf_igz(wf_igz), +KEY touch(touch), +KEY hdl_tag(eintrag,hdl_nr), +KEY prov_hdl_nr(prov_hdl_nr), +KEY mcbs_aufnr(mcbs_aufnr), +KEY kundentyp(kundentyp), +KEY p_nr(p_nr,suffix) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES (3359356,405,3359356,'Mustermann Musterfrau',52500,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1485525,2122316,'+','','N',1909160,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',3,24,'MobilCom Shop Koeln',52500,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359357,468,3359357,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1503580,2139699,'+','','P',1909171,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359358,407,3359358,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1501358,2137473,'N','','N',1909159,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359359,468,3359359,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1507831,2143894,'+','','P',1909162,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359360,0,0,'Mustermann Musterfrau',29674907,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1900169997,2414578,'+',NULL,'N',1909148,'',NULL,NULL,'RV99066_2',20,NULL,'POS',29674907,NULL,NULL,20010202105916,'Mobilfunk','','','97317481','007'); +INSERT INTO t1 VALUES (3359361,406,3359361,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag storniert','','(7001-84):Storno, Kd. möchte nicht mehr','privat',NULL,0,'+','','P',1909150,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1509984,2145874,'+','','P',1909154,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); +SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie; +Kundentyp kategorie +Privat (Private Nutzung) Mobilfunk +Warnings: +Warning 1052 Column 'kundentyp' in group statement is ambiguous +drop table t1; +SHOW STATUS LIKE 'Ssl_cipher'; +Variable_name Value +Ssl_cipher DHE-RSA-AES256-SHA +SHOW STATUS LIKE 'Compression'; +Variable_name Value +Compression ON diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index d42e439f4de..6094d23b0d0 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2988,3 +2988,146 @@ max(fld) 1 drop table t1; purge master logs before (select adddate(current_timestamp(), interval -4 day)); +CREATE TABLE t1 (a int, b int); +CREATE TABLE t2 (c int, d int); +CREATE TABLE t3 (e int); +INSERT INTO t1 VALUES +(1,10), (2,10), (1,20), (2,20), (3,20), (2,30), (4,40); +INSERT INTO t2 VALUES +(2,10), (2,20), (4,10), (5,10), (3,20), (2,40); +INSERT INTO t3 VALUES (10), (30), (10), (20) ; +SELECT a, MAX(b), MIN(b) FROM t1 GROUP BY a; +a MAX(b) MIN(b) +1 20 10 +2 30 10 +3 20 20 +4 40 40 +SELECT * FROM t2; +c d +2 10 +2 20 +4 10 +5 10 +3 20 +2 40 +SELECT * FROM t3; +e +10 +30 +10 +20 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 WHERE MAX(b)>20); +a +2 +4 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 WHERE MAX(b)<d); +a +2 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 WHERE MAX(b)>d); +a +2 +4 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 +WHERE d >= SOME(SELECT e FROM t3 WHERE MAX(b)=e)); +a +2 +3 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 +WHERE EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e <= d)); +a +2 +3 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 +WHERE d > SOME(SELECT e FROM t3 WHERE MAX(b)=e)); +a +2 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 +WHERE EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e < d)); +a +2 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 +WHERE MIN(b) < d AND +EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e <= d)); +a +2 +SELECT a, SUM(a) FROM t1 GROUP BY a; +a SUM(a) +1 2 +2 6 +3 3 +4 4 +SELECT a FROM t1 +WHERE EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) = c) GROUP BY a; +a +3 +4 +SELECT a FROM t1 GROUP BY a +HAVING EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) = c); +a +1 +3 +4 +SELECT a FROM t1 +WHERE a < 3 AND +EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) != c) GROUP BY a; +a +1 +2 +SELECT a FROM t1 +WHERE a < 3 AND +EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) != c); +a +1 +2 +1 +2 +2 +SELECT t1.a FROM t1 GROUP BY t1.a +HAVING t1.a < ALL(SELECT t2.c FROM t2 GROUP BY t2.c +HAVING EXISTS(SELECT t3.e FROM t3 GROUP BY t3.e +HAVING SUM(t1.a+t2.c) < t3.e/4)); +a +1 +2 +SELECT t1.a FROM t1 GROUP BY t1.a +HAVING t1.a > ALL(SELECT t2.c FROM t2 +WHERE EXISTS(SELECT t3.e FROM t3 GROUP BY t3.e +HAVING SUM(t1.a+t2.c) < t3.e/4)); +a +4 +SELECT t1.a FROM t1 GROUP BY t1.a +HAVING t1.a > ALL(SELECT t2.c FROM t2 +WHERE EXISTS(SELECT t3.e FROM t3 +WHERE SUM(t1.a+t2.c) < t3.e/4)); +ERROR HY000: Invalid use of group function +SELECT t1.a from t1 GROUP BY t1.a HAVING AVG(SUM(t1.b)) > 20; +ERROR HY000: Invalid use of group function +SELECT t1.a FROM t1 GROUP BY t1.a +HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c +HAVING AVG(t2.c+SUM(t1.b)) > 20); +a +2 +3 +4 +SELECT t1.a FROM t1 GROUP BY t1.a +HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c +HAVING AVG(SUM(t1.b)) > 20); +a +2 +4 +SELECT t1.a, SUM(b) AS sum FROM t1 GROUP BY t1.a +HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c +HAVING t2.c+sum > 20); +a sum +2 60 +3 20 +4 40 +DROP TABLE t1,t2,t3; diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result index a23b584e510..4dec7882d58 100644 --- a/mysql-test/r/subselect_innodb.result +++ b/mysql-test/r/subselect_innodb.result @@ -172,3 +172,75 @@ group by country; countrycount smcnt country total_funds 1 1200 USA 1200 drop table t1; +CREATE TABLE `t1` ( +`t3_id` int NOT NULL, +`t1_id` int NOT NULL, +PRIMARY KEY (`t1_id`) +); +CREATE TABLE `t2` ( +`t2_id` int NOT NULL, +`t1_id` int NOT NULL, +`b` int NOT NULL, +PRIMARY KEY (`t2_id`), +UNIQUE KEY `idx_t2_t1_b` (`t1_id`,`b`) +) ENGINE=InnoDB; +CREATE TABLE `t3` ( +`t3_id` int NOT NULL +); +INSERT INTO `t3` VALUES (3); +select +(SELECT rs.t2_id +FROM t2 rs +WHERE rs.t1_id= +(SELECT lt.t1_id +FROM t1 lt +WHERE lt.t3_id=a.t3_id) +ORDER BY b DESC LIMIT 1) +from t3 AS a; +(SELECT rs.t2_id +FROM t2 rs +WHERE rs.t1_id= +(SELECT lt.t1_id +FROM t1 lt +WHERE lt.t3_id=a.t3_id) +ORDER BY b DESC LIMIT 1) +NULL +DROP PROCEDURE IF EXISTS p1; +create procedure p1() +begin +declare done int default 3; +repeat +select +(SELECT rs.t2_id +FROM t2 rs +WHERE rs.t1_id= +(SELECT lt.t1_id +FROM t1 lt +WHERE lt.t3_id=a.t3_id) +ORDER BY b DESC LIMIT 1) as x +from t3 AS a; +set done= done-1; +until done <= 0 end repeat; +end// +call p1(); +x +NULL +x +NULL +x +NULL +call p1(); +x +NULL +x +NULL +x +NULL +call p1(); +x +NULL +x +NULL +x +NULL +drop tables t1,t2,t3; diff --git a/mysql-test/r/sum_distinct-big.result b/mysql-test/r/sum_distinct-big.result index 06bfc6b1f78..9b55d59ab91 100644 --- a/mysql-test/r/sum_distinct-big.result +++ b/mysql-test/r/sum_distinct-big.result @@ -1,5 +1,4 @@ -using_big_test -0 +DROP TABLE IF EXISTS t1, t2; CREATE TABLE t1 (id INTEGER); CREATE TABLE t2 (id INTEGER); INSERT INTO t1 (id) VALUES (1), (1), (1),(1); @@ -40,19 +39,19 @@ AVG(DISTINCT id) 512.5000 SELECT SUM(DISTINCT id)/COUNT(DISTINCT id) FROM t1 GROUP BY id % 13; SUM(DISTINCT id)/COUNT(DISTINCT id) -513.50000 -508.00000 -509.00000 -510.00000 -511.00000 -512.00000 -513.00000 -514.00000 -515.00000 -516.00000 -517.00000 -511.50000 -512.50000 +513.5000 +508.0000 +509.0000 +510.0000 +511.0000 +512.0000 +513.0000 +514.0000 +515.0000 +516.0000 +517.0000 +511.5000 +512.5000 INSERT INTO t1 SELECT id+1024 FROM t1; INSERT INTO t1 SELECT id+2048 FROM t1; INSERT INTO t1 SELECT id+4096 FROM t1; diff --git a/mysql-test/r/trigger-compat.result b/mysql-test/r/trigger-compat.result new file mode 100644 index 00000000000..5c104a2d2d5 --- /dev/null +++ b/mysql-test/r/trigger-compat.result @@ -0,0 +1,40 @@ +DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.columns_priv WHERE User LIKE 'mysqltest_%'; +FLUSH PRIVILEGES; +DROP DATABASE IF EXISTS mysqltest_db1; +CREATE DATABASE mysqltest_db1; +CREATE USER mysqltest_dfn@localhost; +CREATE USER mysqltest_inv@localhost; +GRANT SUPER ON *.* TO mysqltest_dfn@localhost; +GRANT CREATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; + +---> connection: wl2818_definer_con +CREATE TABLE t1(num_value INT); +CREATE TABLE t2(user_str TEXT); +CREATE TRIGGER wl2818_trg1 BEFORE INSERT ON t1 +FOR EACH ROW +INSERT INTO t2 VALUES(CURRENT_USER()); + +---> patching t1.TRG... + +CREATE TRIGGER wl2818_trg2 AFTER INSERT ON t1 +FOR EACH ROW +INSERT INTO t2 VALUES(CURRENT_USER()); +Warnings: +Warning 1454 No definer attribute for trigger 'mysqltest_db1'.'wl2818_trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger. + +SELECT trigger_name, definer FROM INFORMATION_SCHEMA.TRIGGERS ORDER BY trigger_name; +trigger_name definer +wl2818_trg1 +wl2818_trg2 mysqltest_dfn@localhost +Warnings: +Warning 1454 No definer attribute for trigger 'mysqltest_db1'.'wl2818_trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger. + +SELECT * FROM INFORMATION_SCHEMA.TRIGGERS ORDER BY trigger_name; +TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE DEFINER +NULL mysqltest_db1 wl2818_trg1 INSERT NULL mysqltest_db1 t1 0 NULL +INSERT INTO t2 VALUES(CURRENT_USER()) ROW BEFORE NULL NULL OLD NEW NULL +NULL mysqltest_db1 wl2818_trg2 INSERT NULL mysqltest_db1 t1 0 NULL +INSERT INTO t2 VALUES(CURRENT_USER()) ROW AFTER NULL NULL OLD NEW NULL mysqltest_dfn@localhost diff --git a/mysql-test/r/trigger-grant.result b/mysql-test/r/trigger-grant.result new file mode 100644 index 00000000000..eda1adfdf65 --- /dev/null +++ b/mysql-test/r/trigger-grant.result @@ -0,0 +1,238 @@ +DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.columns_priv WHERE User LIKE 'mysqltest_%'; +FLUSH PRIVILEGES; +DROP DATABASE IF EXISTS mysqltest_db1; +CREATE DATABASE mysqltest_db1; +CREATE USER mysqltest_dfn@localhost; +CREATE USER mysqltest_inv@localhost; +GRANT SUPER ON *.* TO mysqltest_dfn@localhost; +GRANT CREATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; + +---> connection: wl2818_definer_con +CREATE TABLE t1(num_value INT); +CREATE TABLE t2(user_str TEXT); +CREATE TRIGGER trg1 AFTER INSERT ON t1 +FOR EACH ROW +INSERT INTO t2 VALUES(CURRENT_USER()); + +---> connection: default +GRANT ALL PRIVILEGES ON mysqltest_db1.t1 TO mysqltest_dfn@localhost; +GRANT ALL PRIVILEGES ON mysqltest_db1.t2 TO mysqltest_dfn@localhost; +GRANT ALL PRIVILEGES ON mysqltest_db1.t1 +TO 'mysqltest_inv'@localhost; +GRANT SELECT ON mysqltest_db1.t2 +TO 'mysqltest_inv'@localhost; + +---> connection: wl2818_definer_con +use mysqltest_db1; +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; +num_value +1 +SELECT * FROM t2; +user_str +mysqltest_dfn@localhost + +---> connection: wl2818_invoker_con +use mysqltest_db1; +INSERT INTO t1 VALUES(2); +SELECT * FROM t1; +num_value +1 +2 +SELECT * FROM t2; +user_str +mysqltest_dfn@localhost +mysqltest_dfn@localhost + +---> connection: default +use mysqltest_db1; +REVOKE INSERT ON mysqltest_db1.t2 FROM mysqltest_dfn@localhost; + +---> connection: wl2818_invoker_con +use mysqltest_db1; +INSERT INTO t1 VALUES(3); +ERROR 42000: INSERT command denied to user 'mysqltest_dfn'@'localhost' for table 't2' +SELECT * FROM t1; +num_value +1 +2 +3 +SELECT * FROM t2; +user_str +mysqltest_dfn@localhost +mysqltest_dfn@localhost + +---> connection: default +use mysqltest_db1; +REVOKE SELECT ON mysqltest_db1.t1 FROM mysqltest_dfn@localhost; + +---> connection: wl2818_definer_con +use mysqltest_db1; +DROP TRIGGER trg1; +SET @new_sum = 0; +SET @old_sum = 0; +---> INSERT INTO statement; BEFORE timing +CREATE TRIGGER trg1 BEFORE INSERT ON t1 +FOR EACH ROW +SET @new_sum = @new_sum + NEW.num_value; +INSERT INTO t1 VALUES(4); +ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for table 't1' +---> INSERT INTO statement; AFTER timing +DROP TRIGGER trg1; +CREATE TRIGGER trg1 AFTER INSERT ON t1 +FOR EACH ROW +SET @new_sum = @new_sum + NEW.num_value; +INSERT INTO t1 VALUES(5); +ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for table 't1' +---> UPDATE statement; BEFORE timing +DROP TRIGGER trg1; +CREATE TRIGGER trg1 BEFORE UPDATE ON t1 +FOR EACH ROW +SET @old_sum = @old_sum + OLD.num_value; +UPDATE t1 SET num_value = 10; +ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for table 't1' +---> UPDATE statement; AFTER timing +DROP TRIGGER trg1; +CREATE TRIGGER trg1 AFTER UPDATE ON t1 +FOR EACH ROW +SET @new_sum = @new_sum + NEW.num_value; +UPDATE t1 SET num_value = 20; +ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for table 't1' +---> DELETE statement; BEFORE timing +DROP TRIGGER trg1; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 +FOR EACH ROW +SET @old_sum = @old_sum + OLD.num_value; +DELETE FROM t1; +ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for table 't1' +---> DELETE statement; AFTER timing +DROP TRIGGER trg1; +CREATE TRIGGER trg1 AFTER DELETE ON t1 +FOR EACH ROW +SET @old_sum = @old_sum + OLD.num_value; +DELETE FROM t1; +ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for table 't1' + +---> connection: default +use mysqltest_db1; +GRANT SELECT ON mysqltest_db1.t1 TO mysqltest_dfn@localhost; +REVOKE UPDATE ON mysqltest_db1.t1 FROM mysqltest_dfn@localhost; + +---> connection: wl2818_definer_con +use mysqltest_db1; +DROP TRIGGER trg1; +SET @new_sum = 0; +SET @old_sum = 0; +---> INSERT INTO statement; BEFORE timing +CREATE TRIGGER trg1 BEFORE INSERT ON t1 +FOR EACH ROW +SET @new_sum = @new_sum + NEW.num_value; +INSERT INTO t1 VALUES(4); +ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for table 't1' +---> INSERT INTO statement; AFTER timing +DROP TRIGGER trg1; +CREATE TRIGGER trg1 AFTER INSERT ON t1 +FOR EACH ROW +SET @new_sum = @new_sum + NEW.num_value; +INSERT INTO t1 VALUES(5); +ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for table 't1' +---> UPDATE statement; BEFORE timing +DROP TRIGGER trg1; +CREATE TRIGGER trg1 BEFORE UPDATE ON t1 +FOR EACH ROW +SET @old_sum = @old_sum + OLD.num_value; +UPDATE t1 SET num_value = 10; +ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for table 't1' +---> UPDATE statement; AFTER timing +DROP TRIGGER trg1; +CREATE TRIGGER trg1 AFTER UPDATE ON t1 +FOR EACH ROW +SET @new_sum = @new_sum + NEW.num_value; +UPDATE t1 SET num_value = 20; +ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for table 't1' +---> DELETE statement; BEFORE timing +DROP TRIGGER trg1; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 +FOR EACH ROW +SET @old_sum = @old_sum + OLD.num_value; +DELETE FROM t1; +ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for table 't1' +---> DELETE statement; AFTER timing +DROP TRIGGER trg1; +CREATE TRIGGER trg1 AFTER DELETE ON t1 +FOR EACH ROW +SET @old_sum = @old_sum + OLD.num_value; +DELETE FROM t1; +ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for table 't1' + +---> connection: wl2818_definer_con +use mysqltest_db1; +DROP TRIGGER trg1; +CREATE DEFINER='mysqltest_inv'@'localhost' + TRIGGER trg1 BEFORE INSERT ON t1 +FOR EACH ROW +SET @new_sum = 0; +CREATE DEFINER='mysqltest_nonexs'@'localhost' + TRIGGER trg2 AFTER INSERT ON t1 +FOR EACH ROW +SET @new_sum = 0; +Warnings: +Note 1449 There is no 'mysqltest_nonexs'@'localhost' registered +INSERT INTO t1 VALUES(6); +ERROR 42000: Access denied; you need the SUPER privilege for this operation +SHOW TRIGGERS; +Trigger Event Table Statement Timing Created sql_mode Definer +trg1 INSERT t1 +SET @new_sum = 0 BEFORE NULL mysqltest_inv@localhost +trg2 INSERT t1 +SET @new_sum = 0 AFTER NULL mysqltest_nonexs@localhost +DROP TRIGGER trg1; +DROP TRIGGER trg2; +CREATE TRIGGER trg1 BEFORE INSERT ON t1 +FOR EACH ROW +SET @a = 1; +CREATE TRIGGER trg2 AFTER INSERT ON t1 +FOR EACH ROW +SET @a = 2; +CREATE TRIGGER trg3 BEFORE UPDATE ON t1 +FOR EACH ROW +SET @a = 3; +CREATE TRIGGER trg4 AFTER UPDATE ON t1 +FOR EACH ROW +SET @a = 4; +CREATE TRIGGER trg5 BEFORE DELETE ON t1 +FOR EACH ROW +SET @a = 5; + +SELECT trigger_name, definer FROM INFORMATION_SCHEMA.TRIGGERS ORDER BY trigger_name; +trigger_name definer +trg1 +trg2 @ +trg3 @abc@def@@ +trg4 @hostname +trg5 @abcdef@@@hostname +Warnings: +Warning 1454 No definer attribute for trigger 'mysqltest_db1'.'trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger. + +SELECT * FROM INFORMATION_SCHEMA.TRIGGERS ORDER BY trigger_name; +TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE DEFINER +NULL mysqltest_db1 trg1 INSERT NULL mysqltest_db1 t1 0 NULL +SET @a = 1 ROW BEFORE NULL NULL OLD NEW NULL +NULL mysqltest_db1 trg2 INSERT NULL mysqltest_db1 t1 0 NULL +SET @a = 2 ROW AFTER NULL NULL OLD NEW NULL @ +NULL mysqltest_db1 trg3 UPDATE NULL mysqltest_db1 t1 0 NULL +SET @a = 3 ROW BEFORE NULL NULL OLD NEW NULL @abc@def@@ +NULL mysqltest_db1 trg4 UPDATE NULL mysqltest_db1 t1 0 NULL +SET @a = 4 ROW AFTER NULL NULL OLD NEW NULL @hostname +NULL mysqltest_db1 trg5 DELETE NULL mysqltest_db1 t1 0 NULL +SET @a = 5 ROW BEFORE NULL NULL OLD NEW NULL @abcdef@@@hostname + +---> connection: default +DROP USER mysqltest_dfn@localhost; +DROP USER mysqltest_inv@localhost; +DROP DATABASE mysqltest_db1; +Warnings: +Warning 1454 No definer attribute for trigger 'mysqltest_db1'.'trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger. diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index b305691fa18..38dff6f8ca5 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -611,9 +611,9 @@ select @a; @a 10 show triggers; -Trigger Event Table Statement Timing Created sql_mode -t1_bi INSERT t1 set new."t1 column" = 5 BEFORE # REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI -t1_af INSERT t1 set @a=10 AFTER # +Trigger Event Table Statement Timing Created sql_mode Definer +t1_bi INSERT t1 set new."t1 column" = 5 BEFORE # REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI root@localhost +t1_af INSERT t1 set @a=10 AFTER # root@localhost drop table t1; set sql_mode="traditional"; create table t1 (a date); @@ -633,8 +633,8 @@ t1 CREATE TABLE `t1` ( `a` date default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 show triggers; -Trigger Event Table Statement Timing Created sql_mode -t1_bi INSERT t1 set new.a = '2004-01-00' BEFORE # +Trigger Event Table Statement Timing Created sql_mode Definer +t1_bi INSERT t1 set new.a = '2004-01-00' BEFORE # root@localhost drop table t1; create table t1 (id int); create trigger t1_ai after insert on t1 for each row flush tables; @@ -703,8 +703,11 @@ create trigger t1_ai after insert on t1 for each row insert into t2 values (new.f1+1); create trigger t2_ai after insert on t2 for each row insert into t1 values (new.f2+1); +set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth; +set @@max_sp_recursion_depth=100; insert into t1 values (1); ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. +set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS; select * from t1; f1 1 @@ -738,3 +741,47 @@ f1 1 drop trigger t1_bi; drop tables t1, t2; +create table t1 (id int); +create table t2 (id int); +create trigger t1_bi before insert on t1 for each row insert into t2 values (new.id); +prepare stmt1 from "insert into t1 values (10)"; +create procedure p1() insert into t1 values (10); +call p1(); +drop trigger t1_bi; +execute stmt1; +call p1(); +deallocate prepare stmt1; +drop procedure p1; +create table t3 (id int); +create trigger t1_bi after insert on t1 for each row insert into t2 values (new.id); +prepare stmt1 from "insert into t1 values (10)"; +create procedure p1() insert into t1 values (10); +call p1(); +drop trigger t1_bi; +create trigger t1_bi after insert on t1 for each row insert into t3 values (new.id); +execute stmt1; +ERROR HY000: Table 't3' was not locked with LOCK TABLES +call p1(); +ERROR HY000: Table 't3' was not locked with LOCK TABLES +deallocate prepare stmt1; +drop procedure p1; +drop table t1, t2, t3; +create table t1 (a int); +CREATE PROCEDURE `p1`() +begin +insert into t1 values (1); +end// +create trigger trg before insert on t1 for each row +begin +declare done int default 0; +set done= not done; +end// +CALL p1(); +drop procedure p1; +drop table t1; +create trigger t1_bi before insert on test.t1 for each row set @a:=0; +ERROR 3D000: No database selected +create trigger test.t1_bi before insert on t1 for each row set @a:=0; +ERROR 3D000: No database selected +drop trigger t1_bi; +ERROR 3D000: No database selected diff --git a/mysql-test/r/type_binary.result b/mysql-test/r/type_binary.result index 49fd7ba5633..597defb7a9b 100644 --- a/mysql-test/r/type_binary.result +++ b/mysql-test/r/type_binary.result @@ -111,3 +111,29 @@ select count(distinct s1) from t1; count(distinct s1) 3 drop table t1; +select hex(cast(0x10 as binary(2))); +hex(cast(0x10 as binary(2))) +1000 +create table t1 (b binary(2), vb varbinary(2)); +insert into t1 values(0x4120, 0x4120); +insert into t1 values(0x412020, 0x412020); +Warnings: +Warning 1265 Data truncated for column 'b' at row 1 +Warning 1265 Data truncated for column 'vb' at row 1 +drop table t1; +create table t1 (c char(2), vc varchar(2)); +insert into t1 values(0x4120, 0x4120); +insert into t1 values(0x412020, 0x412020); +Warnings: +Note 1265 Data truncated for column 'vc' at row 1 +drop table t1; +set @old_sql_mode= @@sql_mode, sql_mode= 'traditional'; +create table t1 (b binary(2), vb varbinary(2)); +insert into t1 values(0x4120, 0x4120); +insert into t1 values(0x412020, NULL); +ERROR 22001: Data too long for column 'b' at row 1 +insert into t1 values(NULL, 0x412020); +ERROR 22001: Data too long for column 'vb' at row 1 +drop table t1; +set @@sql_mode= @old_sql_mode; +End of 5.0 tests diff --git a/mysql-test/r/type_newdecimal-big.result b/mysql-test/r/type_newdecimal-big.result new file mode 100644 index 00000000000..4e694702d14 --- /dev/null +++ b/mysql-test/r/type_newdecimal-big.result @@ -0,0 +1,26 @@ +drop procedure if exists sp1; +CREATE PROCEDURE sp1() +BEGIN +DECLARE v1, v2, v3, v4 DECIMAL(28,12); +DECLARE v3_2, v4_2 DECIMAL(28, 12); +DECLARE counter INT; +SET v1 = 1; +SET v2 = 2; +SET v3 = 1000000000000; +SET v4 = 2000000000000; +SET counter = 0; +WHILE counter < 100000 DO +SET v1 = v1 + 0.000000000001; +SET v2 = v2 - 0.000000000001; +SET v3 = v3 + 1; +SET v4 = v4 - 1; +SET counter = counter + 1; +END WHILE; +SET v3_2 = v3 * 0.000000000001; +SET v4_2 = v4 * 0.000000000001; +SELECT v1, v2, v3, v3_2, v4, v4_2; +END// +call sp1()// +v1 v2 v3 v3_2 v4 v4_2 +1.000000100000 1.999999900000 1000000100000.000000000000 1.000000100000 1999999900000.000000000000 1.999999900000 +drop procedure sp1; diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index dbae646c362..938dccc864c 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -678,16 +678,6 @@ select -18.3=18.3; select 0.8 = 0.7 + 0.1; 0.8 = 0.7 + 0.1 1 -create procedure p1 () begin -declare v1, v2, v3, v4 decimal(16,12); declare v5 int; -set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; -while v5 < 100000 do -set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; -end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;// -call p1()// -v1 v2 v3 * 0.000000000001 v4 * 0.000000000001 -1.000000100000 1.999999900000 1.000000100000 1.999999900000 -drop procedure p1; drop table if exists t1; Warnings: Note 1051 Unknown table 't1' @@ -846,15 +836,14 @@ select 0/0; NULL select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 as x; x -999999999999999999999999999999999999999999999999999999999999999999999999999999999 +99999999999999999999999999999999999999999999999999999999999999999 Warnings: Error 1292 Truncated incorrect DECIMAL value: '' select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 1 as x; x -NULL +100000000000000000000000000000000000000000000000000000000000000000 Warnings: Error 1292 Truncated incorrect DECIMAL value: '' -Error 1292 Truncated incorrect DECIMAL value: '' select 0.190287977636363637 + 0.040372670 * 0 - 0; 0.190287977636363637 + 0.040372670 * 0 - 0 0.190287977636363637 @@ -1021,3 +1010,390 @@ cast(@non_existing_user_var/2 as DECIMAL) NULL create table t (d decimal(0,10)); ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 'd'). +CREATE TABLE t1 ( +my_float FLOAT, +my_double DOUBLE, +my_varchar VARCHAR(50), +my_decimal DECIMAL(65,30) +); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `my_float` float default NULL, + `my_double` double default NULL, + `my_varchar` varchar(50) default NULL, + `my_decimal` decimal(65,30) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 SET my_float = 1.175494345e-32, +my_double = 1.175494345e-32, +my_varchar = '1.175494345e-32'; +INSERT INTO t1 SET my_float = 1.175494345e-31, +my_double = 1.175494345e-31, +my_varchar = '1.175494345e-31'; +INSERT INTO t1 SET my_float = 1.175494345e-30, +my_double = 1.175494345e-30, +my_varchar = '1.175494345e-30'; +INSERT INTO t1 SET my_float = 1.175494345e-29, +my_double = 1.175494345e-29, +my_varchar = '1.175494345e-29'; +INSERT INTO t1 SET my_float = 1.175494345e-28, +my_double = 1.175494345e-28, +my_varchar = '1.175494345e-28'; +INSERT INTO t1 SET my_float = 1.175494345e-27, +my_double = 1.175494345e-27, +my_varchar = '1.175494345e-27'; +INSERT INTO t1 SET my_float = 1.175494345e-26, +my_double = 1.175494345e-26, +my_varchar = '1.175494345e-26'; +INSERT INTO t1 SET my_float = 1.175494345e-25, +my_double = 1.175494345e-25, +my_varchar = '1.175494345e-25'; +INSERT INTO t1 SET my_float = 1.175494345e-24, +my_double = 1.175494345e-24, +my_varchar = '1.175494345e-24'; +INSERT INTO t1 SET my_float = 1.175494345e-23, +my_double = 1.175494345e-23, +my_varchar = '1.175494345e-23'; +INSERT INTO t1 SET my_float = 1.175494345e-22, +my_double = 1.175494345e-22, +my_varchar = '1.175494345e-22'; +INSERT INTO t1 SET my_float = 1.175494345e-21, +my_double = 1.175494345e-21, +my_varchar = '1.175494345e-21'; +INSERT INTO t1 SET my_float = 1.175494345e-20, +my_double = 1.175494345e-20, +my_varchar = '1.175494345e-20'; +INSERT INTO t1 SET my_float = 1.175494345e-19, +my_double = 1.175494345e-19, +my_varchar = '1.175494345e-19'; +INSERT INTO t1 SET my_float = 1.175494345e-18, +my_double = 1.175494345e-18, +my_varchar = '1.175494345e-18'; +INSERT INTO t1 SET my_float = 1.175494345e-17, +my_double = 1.175494345e-17, +my_varchar = '1.175494345e-17'; +INSERT INTO t1 SET my_float = 1.175494345e-16, +my_double = 1.175494345e-16, +my_varchar = '1.175494345e-16'; +INSERT INTO t1 SET my_float = 1.175494345e-15, +my_double = 1.175494345e-15, +my_varchar = '1.175494345e-15'; +INSERT INTO t1 SET my_float = 1.175494345e-14, +my_double = 1.175494345e-14, +my_varchar = '1.175494345e-14'; +INSERT INTO t1 SET my_float = 1.175494345e-13, +my_double = 1.175494345e-13, +my_varchar = '1.175494345e-13'; +INSERT INTO t1 SET my_float = 1.175494345e-12, +my_double = 1.175494345e-12, +my_varchar = '1.175494345e-12'; +INSERT INTO t1 SET my_float = 1.175494345e-11, +my_double = 1.175494345e-11, +my_varchar = '1.175494345e-11'; +INSERT INTO t1 SET my_float = 1.175494345e-10, +my_double = 1.175494345e-10, +my_varchar = '1.175494345e-10'; +INSERT INTO t1 SET my_float = 1.175494345e-9, +my_double = 1.175494345e-9, +my_varchar = '1.175494345e-9'; +INSERT INTO t1 SET my_float = 1.175494345e-8, +my_double = 1.175494345e-8, +my_varchar = '1.175494345e-8'; +INSERT INTO t1 SET my_float = 1.175494345e-7, +my_double = 1.175494345e-7, +my_varchar = '1.175494345e-7'; +INSERT INTO t1 SET my_float = 1.175494345e-6, +my_double = 1.175494345e-6, +my_varchar = '1.175494345e-6'; +INSERT INTO t1 SET my_float = 1.175494345e-5, +my_double = 1.175494345e-5, +my_varchar = '1.175494345e-5'; +INSERT INTO t1 SET my_float = 1.175494345e-4, +my_double = 1.175494345e-4, +my_varchar = '1.175494345e-4'; +INSERT INTO t1 SET my_float = 1.175494345e-3, +my_double = 1.175494345e-3, +my_varchar = '1.175494345e-3'; +INSERT INTO t1 SET my_float = 1.175494345e-2, +my_double = 1.175494345e-2, +my_varchar = '1.175494345e-2'; +INSERT INTO t1 SET my_float = 1.175494345e-1, +my_double = 1.175494345e-1, +my_varchar = '1.175494345e-1'; +SELECT my_float, my_double, my_varchar FROM t1; +my_float my_double my_varchar +1.17549e-32 1.175494345e-32 1.175494345e-32 +1.17549e-31 1.175494345e-31 1.175494345e-31 +1.17549e-30 1.175494345e-30 1.175494345e-30 +1.17549e-29 1.175494345e-29 1.175494345e-29 +1.17549e-28 1.175494345e-28 1.175494345e-28 +1.17549e-27 1.175494345e-27 1.175494345e-27 +1.17549e-26 1.175494345e-26 1.175494345e-26 +1.17549e-25 1.175494345e-25 1.175494345e-25 +1.17549e-24 1.175494345e-24 1.175494345e-24 +1.17549e-23 1.175494345e-23 1.175494345e-23 +1.17549e-22 1.175494345e-22 1.175494345e-22 +1.17549e-21 1.175494345e-21 1.175494345e-21 +1.17549e-20 1.175494345e-20 1.175494345e-20 +1.17549e-19 1.175494345e-19 1.175494345e-19 +1.17549e-18 1.175494345e-18 1.175494345e-18 +1.17549e-17 1.175494345e-17 1.175494345e-17 +1.17549e-16 1.175494345e-16 1.175494345e-16 +1.17549e-15 1.175494345e-15 1.175494345e-15 +1.17549e-14 1.175494345e-14 1.175494345e-14 +1.17549e-13 1.175494345e-13 1.175494345e-13 +1.17549e-12 1.175494345e-12 1.175494345e-12 +1.17549e-11 1.175494345e-11 1.175494345e-11 +1.17549e-10 1.175494345e-10 1.175494345e-10 +1.17549e-09 1.175494345e-09 1.175494345e-9 +1.17549e-08 1.175494345e-08 1.175494345e-8 +1.17549e-07 1.175494345e-07 1.175494345e-7 +1.17549e-06 1.175494345e-06 1.175494345e-6 +1.17549e-05 1.175494345e-05 1.175494345e-5 +0.000117549 0.0001175494345 1.175494345e-4 +0.00117549 0.001175494345 1.175494345e-3 +0.0117549 0.01175494345 1.175494345e-2 +0.117549 0.1175494345 1.175494345e-1 +SELECT CAST(my_float AS DECIMAL(65,30)), my_float FROM t1; +CAST(my_float AS DECIMAL(65,30)) my_float +0.000000000000000000000000000000 1.17549e-32 +0.000000000000000000000000000000 1.17549e-31 +0.000000000000000000000000000001 1.17549e-30 +0.000000000000000000000000000012 1.17549e-29 +0.000000000000000000000000000118 1.17549e-28 +0.000000000000000000000000001175 1.17549e-27 +0.000000000000000000000000011755 1.17549e-26 +0.000000000000000000000000117549 1.17549e-25 +0.000000000000000000000001175494 1.17549e-24 +0.000000000000000000000011754943 1.17549e-23 +0.000000000000000000000117549438 1.17549e-22 +0.000000000000000000001175494332 1.17549e-21 +0.000000000000000000011754943324 1.17549e-20 +0.000000000000000000117549434853 1.17549e-19 +0.000000000000000001175494374380 1.17549e-18 +0.000000000000000011754943743802 1.17549e-17 +0.000000000000000117549432474939 1.17549e-16 +0.000000000000001175494324749389 1.17549e-15 +0.000000000000011754943671010360 1.17549e-14 +0.000000000000117549429933840000 1.17549e-13 +0.000000000001175494380653563000 1.17549e-12 +0.000000000011754943372854760000 1.17549e-11 +0.000000000117549428524377200000 1.17549e-10 +0.000000001175494368510499000000 1.17549e-09 +0.000000011754943685104990000000 1.17549e-08 +0.000000117549433298336200000000 1.17549e-07 +0.000001175494389826781000000000 1.17549e-06 +0.000011754943443520460000000000 1.17549e-05 +0.000117549432616215200000000000 0.000117549 +0.001175494398921728000000000000 0.00117549 +0.011754943057894710000000000000 0.0117549 +0.117549434304237400000000000000 0.117549 +SELECT CAST(my_double AS DECIMAL(65,30)), my_double FROM t1; +CAST(my_double AS DECIMAL(65,30)) my_double +0.000000000000000000000000000000 1.175494345e-32 +0.000000000000000000000000000000 1.175494345e-31 +0.000000000000000000000000000001 1.175494345e-30 +0.000000000000000000000000000012 1.175494345e-29 +0.000000000000000000000000000118 1.175494345e-28 +0.000000000000000000000000001175 1.175494345e-27 +0.000000000000000000000000011755 1.175494345e-26 +0.000000000000000000000000117549 1.175494345e-25 +0.000000000000000000000001175494 1.175494345e-24 +0.000000000000000000000011754943 1.175494345e-23 +0.000000000000000000000117549435 1.175494345e-22 +0.000000000000000000001175494345 1.175494345e-21 +0.000000000000000000011754943450 1.175494345e-20 +0.000000000000000000117549434500 1.175494345e-19 +0.000000000000000001175494345000 1.175494345e-18 +0.000000000000000011754943450000 1.175494345e-17 +0.000000000000000117549434500000 1.175494345e-16 +0.000000000000001175494345000000 1.175494345e-15 +0.000000000000011754943450000000 1.175494345e-14 +0.000000000000117549434500000000 1.175494345e-13 +0.000000000001175494345000000000 1.175494345e-12 +0.000000000011754943450000000000 1.175494345e-11 +0.000000000117549434500000000000 1.175494345e-10 +0.000000001175494345000000000000 1.175494345e-09 +0.000000011754943450000000000000 1.175494345e-08 +0.000000117549434500000000000000 1.175494345e-07 +0.000001175494345000000000000000 1.175494345e-06 +0.000011754943450000000000000000 1.175494345e-05 +0.000117549434500000000000000000 0.0001175494345 +0.001175494345000000000000000000 0.001175494345 +0.011754943450000000000000000000 0.01175494345 +0.117549434500000000000000000000 0.1175494345 +SELECT CAST(my_varchar AS DECIMAL(65,30)), my_varchar FROM t1; +CAST(my_varchar AS DECIMAL(65,30)) my_varchar +0.000000000000000000000000000000 1.175494345e-32 +0.000000000000000000000000000000 1.175494345e-31 +0.000000000000000000000000000001 1.175494345e-30 +0.000000000000000000000000000012 1.175494345e-29 +0.000000000000000000000000000118 1.175494345e-28 +0.000000000000000000000000001175 1.175494345e-27 +0.000000000000000000000000011755 1.175494345e-26 +0.000000000000000000000000117549 1.175494345e-25 +0.000000000000000000000001175494 1.175494345e-24 +0.000000000000000000000011754943 1.175494345e-23 +0.000000000000000000000117549435 1.175494345e-22 +0.000000000000000000001175494345 1.175494345e-21 +0.000000000000000000011754943450 1.175494345e-20 +0.000000000000000000117549434500 1.175494345e-19 +0.000000000000000001175494345000 1.175494345e-18 +0.000000000000000011754943450000 1.175494345e-17 +0.000000000000000117549434500000 1.175494345e-16 +0.000000000000001175494345000000 1.175494345e-15 +0.000000000000011754943450000000 1.175494345e-14 +0.000000000000117549434500000000 1.175494345e-13 +0.000000000001175494345000000000 1.175494345e-12 +0.000000000011754943450000000000 1.175494345e-11 +0.000000000117549434500000000000 1.175494345e-10 +0.000000001175494345000000000000 1.175494345e-9 +0.000000011754943450000000000000 1.175494345e-8 +0.000000117549434500000000000000 1.175494345e-7 +0.000001175494345000000000000000 1.175494345e-6 +0.000011754943450000000000000000 1.175494345e-5 +0.000117549434500000000000000000 1.175494345e-4 +0.001175494345000000000000000000 1.175494345e-3 +0.011754943450000000000000000000 1.175494345e-2 +0.117549434500000000000000000000 1.175494345e-1 +UPDATE t1 SET my_decimal = my_float; +SELECT my_decimal, my_float FROM t1; +my_decimal my_float +0.000000000000000000000000000000 1.17549e-32 +0.000000000000000000000000000000 1.17549e-31 +0.000000000000000000000000000001 1.17549e-30 +0.000000000000000000000000000012 1.17549e-29 +0.000000000000000000000000000118 1.17549e-28 +0.000000000000000000000000001175 1.17549e-27 +0.000000000000000000000000011755 1.17549e-26 +0.000000000000000000000000117549 1.17549e-25 +0.000000000000000000000001175494 1.17549e-24 +0.000000000000000000000011754943 1.17549e-23 +0.000000000000000000000117549438 1.17549e-22 +0.000000000000000000001175494332 1.17549e-21 +0.000000000000000000011754943324 1.17549e-20 +0.000000000000000000117549434853 1.17549e-19 +0.000000000000000001175494374380 1.17549e-18 +0.000000000000000011754943743802 1.17549e-17 +0.000000000000000117549432474939 1.17549e-16 +0.000000000000001175494324749389 1.17549e-15 +0.000000000000011754943671010360 1.17549e-14 +0.000000000000117549429933840000 1.17549e-13 +0.000000000001175494380653563000 1.17549e-12 +0.000000000011754943372854760000 1.17549e-11 +0.000000000117549428524377200000 1.17549e-10 +0.000000001175494368510499000000 1.17549e-09 +0.000000011754943685104990000000 1.17549e-08 +0.000000117549433298336200000000 1.17549e-07 +0.000001175494389826781000000000 1.17549e-06 +0.000011754943443520460000000000 1.17549e-05 +0.000117549432616215200000000000 0.000117549 +0.001175494398921728000000000000 0.00117549 +0.011754943057894710000000000000 0.0117549 +0.117549434304237400000000000000 0.117549 +UPDATE t1 SET my_decimal = my_double; +SELECT my_decimal, my_double FROM t1; +my_decimal my_double +0.000000000000000000000000000000 1.175494345e-32 +0.000000000000000000000000000000 1.175494345e-31 +0.000000000000000000000000000001 1.175494345e-30 +0.000000000000000000000000000012 1.175494345e-29 +0.000000000000000000000000000118 1.175494345e-28 +0.000000000000000000000000001175 1.175494345e-27 +0.000000000000000000000000011755 1.175494345e-26 +0.000000000000000000000000117549 1.175494345e-25 +0.000000000000000000000001175494 1.175494345e-24 +0.000000000000000000000011754943 1.175494345e-23 +0.000000000000000000000117549435 1.175494345e-22 +0.000000000000000000001175494345 1.175494345e-21 +0.000000000000000000011754943450 1.175494345e-20 +0.000000000000000000117549434500 1.175494345e-19 +0.000000000000000001175494345000 1.175494345e-18 +0.000000000000000011754943450000 1.175494345e-17 +0.000000000000000117549434500000 1.175494345e-16 +0.000000000000001175494345000000 1.175494345e-15 +0.000000000000011754943450000000 1.175494345e-14 +0.000000000000117549434500000000 1.175494345e-13 +0.000000000001175494345000000000 1.175494345e-12 +0.000000000011754943450000000000 1.175494345e-11 +0.000000000117549434500000000000 1.175494345e-10 +0.000000001175494345000000000000 1.175494345e-09 +0.000000011754943450000000000000 1.175494345e-08 +0.000000117549434500000000000000 1.175494345e-07 +0.000001175494345000000000000000 1.175494345e-06 +0.000011754943450000000000000000 1.175494345e-05 +0.000117549434500000000000000000 0.0001175494345 +0.001175494345000000000000000000 0.001175494345 +0.011754943450000000000000000000 0.01175494345 +0.117549434500000000000000000000 0.1175494345 +UPDATE t1 SET my_decimal = my_varchar; +Warnings: +Note 1265 Data truncated for column 'my_decimal' at row 1 +Note 1265 Data truncated for column 'my_decimal' at row 2 +Note 1265 Data truncated for column 'my_decimal' at row 3 +Note 1265 Data truncated for column 'my_decimal' at row 4 +Note 1265 Data truncated for column 'my_decimal' at row 5 +Note 1265 Data truncated for column 'my_decimal' at row 6 +Note 1265 Data truncated for column 'my_decimal' at row 7 +Note 1265 Data truncated for column 'my_decimal' at row 8 +Note 1265 Data truncated for column 'my_decimal' at row 9 +Note 1265 Data truncated for column 'my_decimal' at row 10 +Note 1265 Data truncated for column 'my_decimal' at row 11 +SELECT my_decimal, my_varchar FROM t1; +my_decimal my_varchar +0.000000000000000000000000000000 1.175494345e-32 +0.000000000000000000000000000000 1.175494345e-31 +0.000000000000000000000000000001 1.175494345e-30 +0.000000000000000000000000000012 1.175494345e-29 +0.000000000000000000000000000118 1.175494345e-28 +0.000000000000000000000000001175 1.175494345e-27 +0.000000000000000000000000011755 1.175494345e-26 +0.000000000000000000000000117549 1.175494345e-25 +0.000000000000000000000001175494 1.175494345e-24 +0.000000000000000000000011754943 1.175494345e-23 +0.000000000000000000000117549435 1.175494345e-22 +0.000000000000000000001175494345 1.175494345e-21 +0.000000000000000000011754943450 1.175494345e-20 +0.000000000000000000117549434500 1.175494345e-19 +0.000000000000000001175494345000 1.175494345e-18 +0.000000000000000011754943450000 1.175494345e-17 +0.000000000000000117549434500000 1.175494345e-16 +0.000000000000001175494345000000 1.175494345e-15 +0.000000000000011754943450000000 1.175494345e-14 +0.000000000000117549434500000000 1.175494345e-13 +0.000000000001175494345000000000 1.175494345e-12 +0.000000000011754943450000000000 1.175494345e-11 +0.000000000117549434500000000000 1.175494345e-10 +0.000000001175494345000000000000 1.175494345e-9 +0.000000011754943450000000000000 1.175494345e-8 +0.000000117549434500000000000000 1.175494345e-7 +0.000001175494345000000000000000 1.175494345e-6 +0.000011754943450000000000000000 1.175494345e-5 +0.000117549434500000000000000000 1.175494345e-4 +0.001175494345000000000000000000 1.175494345e-3 +0.011754943450000000000000000000 1.175494345e-2 +0.117549434500000000000000000000 1.175494345e-1 +DROP TABLE t1; +create table t1 (c1 decimal(64)); +insert into t1 values( +89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000); +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +insert into t1 values( +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 * +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +insert into t1 values(1e100); +Warnings: +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +select * from t1; +c1 +9999999999999999999999999999999999999999999999999999999999999999 +9999999999999999999999999999999999999999999999999999999999999999 +9999999999999999999999999999999999999999999999999999999999999999 +drop table t1; diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result index ff07dcca106..bcdba3dca76 100644 --- a/mysql-test/r/type_ranges.result +++ b/mysql-test/r/type_ranges.result @@ -215,7 +215,7 @@ Field Type Collation Null Key Default Extra Privileges Comment auto int(5) unsigned NULL NO MUL NULL auto_increment # string char(10) latin1_swedish_ci YES newdefault # tiny tinyint(4) NULL NO MUL 0 # -short smallint(6) NULL NO MUL 0 # +short smallint(6) NULL NO MUL # medium mediumint(8) NULL NO MUL 0 # long_int int(11) NULL NO 0 # longlong bigint(13) NULL NO MUL 0 # diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result index 442435b0459..deb60a95f21 100644 --- a/mysql-test/r/type_time.result +++ b/mysql-test/r/type_time.result @@ -85,3 +85,27 @@ sec_to_time(time_to_sec(t)) 13:00:00 09:00:00 drop table t1; +SELECT CAST(235959.123456 AS TIME); +CAST(235959.123456 AS TIME) +23:59:59.123456 +SELECT CAST(0.235959123456e+6 AS TIME); +CAST(0.235959123456e+6 AS TIME) +23:59:59.123456 +SELECT CAST(235959123456e-6 AS TIME); +CAST(235959123456e-6 AS TIME) +23:59:59.123456 +SELECT CAST(235959.1234567 AS TIME); +CAST(235959.1234567 AS TIME) +23:59:59.123456 +Warnings: +Warning 1292 Truncated incorrect time value: '235959.1234567' +SELECT CAST(0.2359591234567e6 AS TIME); +CAST(0.2359591234567e6 AS TIME) +23:59:59.123456 +Warnings: +Warning 1292 Truncated incorrect time value: '235959.1234567' +SELECT CAST(0.2359591234567e+30 AS TIME); +CAST(0.2359591234567e+30 AS TIME) +NULL +Warnings: +Warning 1292 Truncated incorrect time value: '2.359591234567e+29' diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 042dfb5ad8d..f2708a50c77 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1220,6 +1220,32 @@ show columns from t2; Field Type Null Key Default Extra a varchar(3) YES NULL drop table t2, t1; +create table t1 (f1 decimal(60,25), f2 decimal(60,25)); +insert into t1 values (0.0,0.0); +select f1 from t1 union all select f2 from t1; +f1 +0.0000000000000000000000000 +0.0000000000000000000000000 +select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 +union all +select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; +description f1 +XXXXXXXXXXXXXXXXXXXX 0.0000000000000000000000000 +YYYYYYYYYYYYYYYYYYYY 0.0000000000000000000000000 +drop table t1; +create table t1 (f1 decimal(60,24), f2 decimal(60,24)); +insert into t1 values (0.0,0.0); +select f1 from t1 union all select f2 from t1; +f1 +0.000000000000000000000000 +0.000000000000000000000000 +select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 +union all +select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; +description f1 +XXXXXXXXXXXXXXXXXXXX 0.000000000000000000000000 +YYYYYYYYYYYYYYYYYYYY 0.000000000000000000000000 +drop table t1; create table t1 (a varchar(5)); create table t2 select * from t1 union select 'abcdefghijkl'; show create table t2; diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index d2aa051c299..abeade5df0c 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -263,8 +263,8 @@ test delete from t1 where count(*)=1; ERROR HY000: Invalid use of group function drop table t1; -create table t1 ( a int, index (a) ); -insert into t1 values (0),(0),(0),(0),(0),(0),(0),(0); +create table t1 ( a int, b int default 0, index (a) ); +insert into t1 (a) values (0),(0),(0),(0),(0),(0),(0),(0); flush status; select a from t1 order by a limit 1; a @@ -278,15 +278,16 @@ Handler_read_prev 0 Handler_read_rnd 0 Handler_read_rnd_next 0 flush status; -update t1 set a=unix_timestamp() order by a limit 1; +update t1 set a=9999 order by a limit 1; +update t1 set b=9999 order by a limit 1; show status like 'handler_read%'; Variable_name Value Handler_read_first 1 Handler_read_key 0 Handler_read_next 0 Handler_read_prev 0 -Handler_read_rnd 1 -Handler_read_rnd_next 0 +Handler_read_rnd 2 +Handler_read_rnd_next 9 flush status; delete from t1 order by a limit 1; show status like 'handler_read%'; @@ -318,7 +319,42 @@ Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 1 Handler_read_rnd_next 9 -select count(*) from t1; -count(*) -5 +select * from t1; +a b +0 0 +0 0 +0 0 +0 0 +0 0 +update t1 set a=a+10,b=1 order by a limit 3; +update t1 set a=a+11,b=2 order by a limit 3; +update t1 set a=a+12,b=3 order by a limit 3; +select * from t1 order by a; +a b +11 2 +21 2 +22 3 +22 3 +23 3 +drop table t1; +create table t1 (f1 date not null); +insert into t1 values('2000-01-01'),('0000-00-00'); +update t1 set f1='2002-02-02' where f1 is null; +select * from t1; +f1 +2000-01-01 +2002-02-02 drop table t1; +create table t1 (f1 int); +create table t2 (f2 int); +insert into t1 values(1),(2); +insert into t2 values(1),(1); +update t1,t2 set f1=3,f2=3 where f1=f2 and f1=1; +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +update t2 set f2=1; +update t1 set f1=1 where f1=3; +update t2,t1 set f1=3,f2=3 where f1=f2 and f1=1; +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +drop table t1,t2; diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index acdc793fb69..75a680e504d 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -123,6 +123,17 @@ select @a+0, @a:=@a+0+count(*), count(*), @a+0 from t1 group by i; 0 1 1 0 1 3 2 0 3 6 3 0 +set @a=0; +select @a,@a:="hello",@a,@a:=3,@a,@a:="hello again" from t1 group by i; +@a @a:="hello" @a @a:=3 @a @a:="hello again" +0 hello 0 3 0 hello again +0 hello 0 3 0 hello again +0 hello 0 3 0 hello again +select @a,@a:="hello",@a,@a:=3,@a,@a:="hello again" from t1 group by i; +@a @a:="hello" @a @a:=3 @a @a:="hello again" +hello again hello hello again 3 hello again hello again +hello again hello hello again 3 hello again hello again +hello again hello hello again 3 hello again hello again drop table t1; set @a=_latin2'test'; select charset(@a),collation(@a),coercibility(@a); diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 3ecc48620b1..df180218a09 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -351,6 +351,14 @@ set global rpl_recovery_rank=100; set global server_id=100; set global slow_launch_time=100; set sort_buffer_size=100; +set @@max_sp_recursion_depth=10; +select @@max_sp_recursion_depth; +@@max_sp_recursion_depth +10 +set @@max_sp_recursion_depth=0; +select @@max_sp_recursion_depth; +@@max_sp_recursion_depth +0 set sql_auto_is_null=1; select @@sql_auto_is_null; @@sql_auto_is_null diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 4d224bf196d..b9380dcf033 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1,4 +1,4 @@ -drop table if exists t1,t2,t9,`t1a``b`,v1,v2,v3,v4,v5,v6; +drop table if exists t1,t2,t3,t4,t9,`t1a``b`,v1,v2,v3,v4,v5,v6; drop view if exists t1,t2,`t1a``b`,v1,v2,v3,v4,v5,v6; drop database if exists mysqltest; use test; @@ -204,6 +204,21 @@ create table t1 (a int); insert into t1 values (1), (2), (3); create view v1 (a) as select a+1 from t1; create view v2 (a) as select a-1 from t1; +select * from t1 natural left join v1; +a +1 +2 +3 +select * from v2 natural left join t1; +a +0 +1 +2 +select * from v2 natural left join v1; +a +0 +1 +2 drop view v1, v2; drop table t1; create table t1 (a int); @@ -574,10 +589,10 @@ create view v1 as select * from t1; drop table t1; create table t1 (col1 char(5),newcol2 char(5)); insert into v1 values('a','aa'); -ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them drop table t1; select * from v1; -ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them drop view v1; create view v1 (a,a) as select 'a','a'; ERROR 42S21: Duplicate column name 'a' @@ -809,11 +824,11 @@ create table t1 (s1 int); create view v1 as select x1() from t1; drop function x1; select * from v1; -ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment t1 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL -v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL View 'test.v1' references invalid table(s) or column(s) or function(s) +v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL View 'test.v1' references invalid table(s) or column(s) or function(s) or define drop view v1; drop table t1; create view v1 as select 99999999999999999999999999999999999999999999999999999 as col1; @@ -1360,7 +1375,7 @@ test.t1 check status OK drop table t1; check table v1; Table Op Msg_type Msg_text -test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) +test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them drop view v1; create table t1 (a int); create table t2 (a int); @@ -1884,11 +1899,11 @@ CREATE VIEW v6 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; DROP TABLE t1; CHECK TABLE v1, v2, v3, v4, v5, v6; Table Op Msg_type Msg_text -test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) +test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v2 check status OK -test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s) +test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v4 check status OK -test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s) +test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v6 check status OK drop view v1, v2, v3, v4, v5, v6; drop table t2; @@ -1908,21 +1923,21 @@ CREATE VIEW v6 AS SELECT f2() FROM t3; drop function f1; CHECK TABLE v1, v2, v3, v4, v5, v6; Table Op Msg_type Msg_text -test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) +test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v2 check status OK -test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s) +test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v4 check status OK -test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s) +test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v6 check status OK create function f1 () returns int return (select max(col1) from t1); DROP TABLE t1; CHECK TABLE v1, v2, v3, v4, v5, v6; Table Op Msg_type Msg_text -test.v1 check error Table 'test.t1' doesn't exist +test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v2 check status OK -test.v3 check error Table 'test.t1' doesn't exist +test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v4 check status OK -test.v5 check error Table 'test.t1' doesn't exist +test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v6 check status OK drop function f1; drop function f2; @@ -2154,7 +2169,7 @@ Field Type Null Key Default Extra f4 char(5) YES NULL ALTER TABLE t1 CHANGE COLUMN f4 f4x CHAR(5); DESCRIBE v1; -ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them DROP TABLE t1; DROP VIEW v1; create table t1 (f1 char); @@ -2198,11 +2213,11 @@ r_object_id users_names 120001a080000542 guser02 drop view v1, v2; drop table t1, t2; -create definer=some_user@__% sql security invoker view v1 as select 1; -ERROR HY000: View definer is not fully qualified +create definer=some_user@`` sql security invoker view v1 as select 1; +ERROR HY000: Definer is not fully qualified create definer=some_user@localhost sql security invoker view v1 as select 1; Warnings: -Note 1449 There is not some_user@localhost registered +Note 1449 There is no 'some_user'@'localhost' registered show create view v1; View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1` @@ -2323,3 +2338,140 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where DROP VIEW v1,v2; DROP TABLE t1,t2,t3; +create table t1 (f1 int); +create view v1 as select t1.f1 as '123 +456' from t1; +select * from v1; +123 +456 +drop view v1; +drop table t1; +create table t1 (f1 int, f2 int); +insert into t1 values(1,1),(1,2),(1,3); +create view v1 as select f1 ,group_concat(f2 order by f2 asc) from t1 group by f1; +create view v2 as select f1 ,group_concat(f2 order by f2 desc) from t1 group by f1; +select * from v1; +f1 group_concat(f2 order by f2 asc) +1 1,2,3 +select * from v2; +f1 group_concat(f2 order by f2 desc) +1 3,2,1 +drop view v1,v2; +drop table t1; +create table t1 (x int, y int); +create table t2 (x int, y int, z int); +create table t3 (x int, y int, z int); +create table t4 (x int, y int, z int); +create view v1 as +select t1.x +from ( +(t1 join t2 on ((t1.y = t2.y))) +join +(t3 left join t4 on (t3.y = t4.y) and (t3.z = t4.z)) +); +prepare stmt1 from "select count(*) from v1 where x = ?"; +set @parm1=1; +execute stmt1 using @parm1; +count(*) +0 +execute stmt1 using @parm1; +count(*) +0 +drop view v1; +drop table t1,t2,t3,t4; +CREATE TABLE t1(id INT); +CREATE VIEW v1 AS SELECT id FROM t1; +OPTIMIZE TABLE v1; +Table Op Msg_type Msg_text +test.v1 optimize error 'test.v1' is not BASE TABLE +Warnings: +Error 1347 'test.v1' is not BASE TABLE +ANALYZE TABLE v1; +Table Op Msg_type Msg_text +test.v1 analyze error 'test.v1' is not BASE TABLE +Warnings: +Error 1347 'test.v1' is not BASE TABLE +REPAIR TABLE v1; +Table Op Msg_type Msg_text +test.v1 repair error 'test.v1' is not BASE TABLE +Warnings: +Error 1347 'test.v1' is not BASE TABLE +DROP TABLE t1; +OPTIMIZE TABLE v1; +Table Op Msg_type Msg_text +test.v1 optimize error 'test.v1' is not BASE TABLE +Warnings: +Error 1347 'test.v1' is not BASE TABLE +DROP VIEW v1; +create definer = current_user() sql security invoker view v1 as select 1; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1` +drop view v1; +create definer = current_user sql security invoker view v1 as select 1; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1` +drop view v1; +create table t1 (id INT, primary key(id)); +insert into t1 values (1),(2); +create view v1 as select * from t1; +explain select id from v1 order by id; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index NULL PRIMARY 4 NULL 2 Using index +drop view v1; +drop table t1; +create table t1(f1 int, f2 int); +insert into t1 values (null, 10), (null,2); +select f1, sum(f2) from t1 group by f1; +f1 sum(f2) +NULL 12 +create view v1 as select * from t1; +select f1, sum(f2) from v1 group by f1; +f1 sum(f2) +NULL 12 +drop view v1; +drop table t1; +drop procedure if exists p1; +create procedure p1 () deterministic +begin +create view v1 as select 1; +end; +// +call p1(); +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` +drop view v1; +drop procedure p1; +CREATE VIEW v1 AS SELECT 42 AS Meaning; +DROP FUNCTION IF EXISTS f1; +CREATE FUNCTION f1() RETURNS INTEGER +BEGIN +DECLARE retn INTEGER; +SELECT Meaning FROM v1 INTO retn; +RETURN retn; +END +// +CREATE VIEW v2 AS SELECT f1(); +select * from v2; +f1() +42 +drop view v2,v1; +drop function f1; +create table t1 (id numeric, warehouse_id numeric); +create view v1 as select id from t1; +create view v2 as +select t1.warehouse_id, v1.id as receipt_id +from t1, v1 where t1.id = v1.id; +insert into t1 (id, warehouse_id) values(3, 2); +insert into t1 (id, warehouse_id) values(4, 2); +insert into t1 (id, warehouse_id) values(5, 1); +select v2.receipt_id as alias1, v2.receipt_id as alias2 from v2 +order by v2.receipt_id; +alias1 alias2 +3 3 +4 4 +5 5 +drop view v2, v1; +drop table t1; diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index bac6e691069..e2ee02351d7 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -13,7 +13,7 @@ create table mysqltest.t2 (a int, b int); grant select on mysqltest.t1 to mysqltest_1@localhost; grant create view,select on test.* to mysqltest_1@localhost; create definer=root@localhost view v1 as select * from mysqltest.t1; -ERROR HY000: You need the SUPER privilege for creation view with root@localhost definer +ERROR 42000: Access denied; you need the SUPER privilege for this operation create view v1 as select * from mysqltest.t1; alter view v1 as select * from mysqltest.t1; ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 'v1' @@ -305,5 +305,216 @@ create table mysqltest.t1 (a int); grant all privileges on mysqltest.* to mysqltest_1@localhost; use mysqltest; create view v1 as select * from t1; +use test; revoke all privileges on mysqltest.* from mysqltest_1@localhost; drop database mysqltest; +create database mysqltest; +create table mysqltest.t1 (a int, b int); +grant select on mysqltest.t1 to mysqltest_1@localhost; +grant create view,select on test.* to mysqltest_1@localhost; +create view v1 as select * from mysqltest.t1; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_1`@`localhost` SQL SECURITY DEFINER VIEW `test`.`v1` AS select `mysqltest`.`t1`.`a` AS `a`,`mysqltest`.`t1`.`b` AS `b` from `mysqltest`.`t1` +revoke select on mysqltest.t1 from mysqltest_1@localhost; +select * from v1; +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +grant select on mysqltest.t1 to mysqltest_1@localhost; +select * from v1; +a b +REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; +drop view v1; +drop database mysqltest; +create database mysqltest; +use mysqltest; +create table t1 (a int); +insert into t1 values (1); +create table t2 (s1 int); +drop function if exists f2; +create function f2 () returns int begin declare v int; select s1 from t2 +into v; return v; end// +create algorithm=TEMPTABLE view v1 as select f2() from t1; +create algorithm=MERGE view v2 as select f2() from t1; +create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select f2() from t1; +create algorithm=MERGE SQL SECURITY INVOKER view v4 as select f2() from t1; +create SQL SECURITY INVOKER view v5 as select * from v4; +grant select on v1 to mysqltest_1@localhost; +grant select on v2 to mysqltest_1@localhost; +grant select on v3 to mysqltest_1@localhost; +grant select on v4 to mysqltest_1@localhost; +grant select on v5 to mysqltest_1@localhost; +use mysqltest; +select * from v1; +f2() +NULL +Warnings: +Warning 1329 No data to FETCH +select * from v2; +f2() +NULL +Warnings: +Warning 1329 No data to FETCH +select * from v3; +ERROR HY000: View 'mysqltest.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v4; +ERROR HY000: View 'mysqltest.v4' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v5; +ERROR HY000: View 'mysqltest.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +use test; +drop view v1, v2, v3, v4, v5; +drop function f2; +drop table t1, t2; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; +drop database mysqltest; +create database mysqltest; +use mysqltest; +create table t1 (a int); +insert into t1 values (1); +create table t2 (s1 int); +drop function if exists f2; +create function f2 () returns int begin declare v int; select s1 from t2 +into v; return v; end// +grant select on t1 to mysqltest_1@localhost; +grant execute on function f2 to mysqltest_1@localhost; +grant create view on mysqltest.* to mysqltest_1@localhost; +use mysqltest; +create algorithm=TEMPTABLE view v1 as select f2() from t1; +create algorithm=MERGE view v2 as select f2() from t1; +create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select f2() from t1; +create algorithm=MERGE SQL SECURITY INVOKER view v4 as select f2() from t1; +use test; +create view v5 as select * from v1; +revoke execute on function f2 from mysqltest_1@localhost; +select * from v1; +ERROR HY000: View 'mysqltest.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v2; +ERROR HY000: View 'mysqltest.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v3; +f2() +NULL +Warnings: +Warning 1329 No data to FETCH +select * from v4; +f2() +NULL +Warnings: +Warning 1329 No data to FETCH +select * from v5; +ERROR HY000: View 'mysqltest.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +drop view v1, v2, v3, v4, v5; +drop function f2; +drop table t1, t2; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; +drop database mysqltest; +create database mysqltest; +use mysqltest; +create table t1 (a int); +create table v1 (a int); +insert into t1 values (1); +grant select on t1 to mysqltest_1@localhost; +grant select on v1 to mysqltest_1@localhost; +grant create view on mysqltest.* to mysqltest_1@localhost; +drop table v1; +use mysqltest; +create algorithm=TEMPTABLE view v1 as select *, a as b from t1; +create algorithm=MERGE view v2 as select *, a as b from t1; +create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select *, a as b from t1; +create algorithm=MERGE SQL SECURITY INVOKER view v4 as select *, a as b from t1; +create view v5 as select * from v1; +use test; +revoke select on t1 from mysqltest_1@localhost; +select * from v1; +ERROR HY000: View 'mysqltest.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v2; +ERROR HY000: View 'mysqltest.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v3; +a b +1 1 +select * from v4; +a b +1 1 +select * from v5; +ERROR HY000: View 'mysqltest.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +drop table t1; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; +drop database mysqltest; +create database mysqltest; +use mysqltest; +create table t1 (a int); +insert into t1 values (1); +create algorithm=TEMPTABLE view v1 as select *, a as b from t1; +create algorithm=MERGE view v2 as select *, a as b from t1; +create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select *, a as b from t1; +create algorithm=MERGE SQL SECURITY INVOKER view v4 as select *, a as b from t1; +create SQL SECURITY INVOKER view v5 as select * from v4; +grant select on v1 to mysqltest_1@localhost; +grant select on v2 to mysqltest_1@localhost; +grant select on v3 to mysqltest_1@localhost; +grant select on v4 to mysqltest_1@localhost; +grant select on v5 to mysqltest_1@localhost; +use mysqltest; +select * from v1; +a b +1 1 +select * from v2; +a b +1 1 +select * from v3; +ERROR HY000: View 'mysqltest.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v4; +ERROR HY000: View 'mysqltest.v4' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v5; +ERROR HY000: View 'mysqltest.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +use test; +drop view v1, v2, v3, v4, v5; +drop table t1; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; +drop database mysqltest; +drop view if exists v1; +create table t1 as select * from mysql.user where user=''; +delete from mysql.user where user=''; +flush privileges; +grant all on test.* to 'test14256'@'%'; +use test; +create view v1 as select 42; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`test14256`@`%` SQL SECURITY DEFINER VIEW `v1` AS select 42 AS `42` +select definer into @v1def1 from information_schema.views +where table_schema = 'test' and table_name='v1'; +drop view v1; +create definer=`test14256`@`%` view v1 as select 42; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`test14256`@`%` SQL SECURITY DEFINER VIEW `v1` AS select 42 AS `42` +select definer into @v1def2 from information_schema.views +where table_schema = 'test' and table_name='v1'; +drop view v1; +select @v1def1, @v1def2, @v1def1=@v1def2; +@v1def1 @v1def2 @v1def1=@v1def2 +test14256@% test14256@% 1 +drop user test14256; +insert into mysql.user select * from t1; +flush privileges; +drop table t1; +create database mysqltest; +use mysqltest; +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT * FROM t1; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` +GRANT SELECT, LOCK TABLES ON mysqltest.* TO mysqltest_1@localhost; +use mysqltest; +LOCK TABLES v1 READ; +SHOW CREATE TABLE v1; +ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1' +UNLOCK TABLES; +use test; +use test; +drop user mysqltest_1@localhost; +drop database mysqltest; diff --git a/mysql-test/r/view_query_cache.result b/mysql-test/r/view_query_cache.result index 944e1db34c9..03430bd504b 100644 --- a/mysql-test/r/view_query_cache.result +++ b/mysql-test/r/view_query_cache.result @@ -132,4 +132,65 @@ unlock tables; set query_cache_wlock_invalidate=default; drop view v1; drop table t1; +flush status; +create table t1 (a int, b int); +create algorithm=temptable view v1 as select * from t1; +select * from v1; +a b +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +select * from v1; +a b +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +insert into t1 values (1,1); +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +select * from v1; +a b +1 1 +select * from v1; +a b +1 1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 2 +drop view v1; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 2 +drop table t1; set GLOBAL query_cache_size=default; diff --git a/mysql-test/std_data/loaddata_dq.dat b/mysql-test/std_data/loaddata_dq.dat new file mode 100644 index 00000000000..5bdddfa977a --- /dev/null +++ b/mysql-test/std_data/loaddata_dq.dat @@ -0,0 +1,3 @@ +"field1","field2" +"a""b","cd""ef" +"a"b",c"d"e diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index bae94656125..f4245abfe86 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -340,7 +340,9 @@ drop table t1; # # BUG 12207 alter table ... discard table space on MyISAM table causes ERROR 2013 (HY000) # +# Some platforms (Mac OS X, Windows) will send the error message using small letters. CREATE TABLE T12207(a int) ENGINE=MYISAM; +--replace_result t12207 T12207 --error 1031 ALTER TABLE T12207 DISCARD TABLESPACE; DROP TABLE T12207; @@ -401,3 +403,12 @@ use test; drop table t1; # End of 4.1 tests + +# +# Bug #14693 (ALTER SET DEFAULT doesn't work) +# + +create table t1 (mycol int(10) not null); +alter table t1 alter column mycol set default 0; +desc t1; +drop table t1; diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test index 4060892c389..a248c671c18 100644 --- a/mysql-test/t/analyse.test +++ b/mysql-test/t/analyse.test @@ -65,5 +65,30 @@ insert into t1 values (100000); select * from t1 procedure analyse (1,1); drop table t1; +# +# Bug #14138 ROLLUP and PROCEDURE ANALYSE() hang server +# +create table t1 (product varchar(32), country_id int not null, year int, + profit int); +insert into t1 values ( 'Computer', 2,2000, 1200), + ( 'TV', 1, 1999, 150), + ( 'Calculator', 1, 1999,50), + ( 'Computer', 1, 1999,1500), + ( 'Computer', 1, 2000,1500), + ( 'TV', 1, 2000, 150), + ( 'TV', 2, 2000, 100), + ( 'TV', 2, 2000, 100), + ( 'Calculator', 1, 2000,75), + ( 'Calculator', 2, 2000,75), + ( 'TV', 1, 1999, 100), + ( 'Computer', 1, 1999,1200), + ( 'Computer', 2, 2000,1500), + ( 'Calculator', 2, 2000,75), + ( 'Phone', 3, 2003,10) + ; +create table t2 (country_id int primary key, country char(20) not null); +insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland'); +select product, sum(profit),avg(profit) from t1 group by product with rollup procedure analyse(); +drop table t1,t2; # End of 4.1 tests diff --git a/mysql-test/t/analyze.test b/mysql-test/t/analyze.test index 3c3b3933bc3..656ff752c9b 100644 --- a/mysql-test/t/analyze.test +++ b/mysql-test/t/analyze.test @@ -39,4 +39,27 @@ check table t1; drop table t1; +# Bug #14902 ANALYZE TABLE fails to recognize up-to-date tables +# minimal test case to get an error. +# The problem is happening when analysing table with FT index that +# contains stopwords only. The first execution of analyze table should +# mark index statistics as up to date so that next execution of this +# statement will end up with Table is up to date status. +create table t1 (a mediumtext, fulltext key key1(a)) charset utf8 collate utf8_general_ci engine myisam; +insert into t1 values ('hello'); + +analyze table t1; +analyze table t1; + +drop table t1; + +# +# procedure in PS BUG#13673 +# +CREATE TABLE t1 (a int); +prepare stmt1 from "SELECT * FROM t1 PROCEDURE ANALYSE()"; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; + # End of 4.1 tests diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index ac2061eeb0b..ba2ad3ed8aa 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -1347,6 +1347,11 @@ SELECT * FROM t2; # Just test syntax, we will never know if the output is right or wrong # Must be the last test INSERT DELAYED INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily',''); + +# Adding test for alter table +ALTER TABLE t2 DROP COLUMN fld6; +SHOW CREATE TABLE t2; +SELECT * from t2; # # Cleanup, test is over # diff --git a/mysql-test/t/archive_gis.test b/mysql-test/t/archive_gis.test new file mode 100644 index 00000000000..ffbad923173 --- /dev/null +++ b/mysql-test/t/archive_gis.test @@ -0,0 +1,3 @@ +--source include/have_archive.inc +SET storage_engine=archive; +--source include/gis_generic.inc diff --git a/mysql-test/t/backup.test b/mysql-test/t/backup.test index 3034129ad4b..40a9fa73b60 100644 --- a/mysql-test/t/backup.test +++ b/mysql-test/t/backup.test @@ -52,5 +52,6 @@ unlock tables; connection con1; reap; drop table t5; +--system rm $MYSQL_TEST_DIR/var/tmp/t?.* # End of 4.1 tests diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test index bf72a4555b8..d017d91bfb1 100644 --- a/mysql-test/t/bdb.test +++ b/mysql-test/t/bdb.test @@ -938,7 +938,25 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera"); SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd"); DROP TABLE t1; -# End of 4.1 tests +# +# Bug #15536: Crash when DELETE with subquery using BDB tables +# +create table t1 (a int, key(a)) engine=bdb; +create table t2 (b int, key(b)) engine=bdb; +insert into t1 values (1),(1),(2),(3),(4); +insert into t2 values (1),(5),(6),(7); +delete from t1 where (a in (select b from t2)); +select count(*) from t1; +# INSERT also blows up +--error 1242 +insert into t1 set a=(select b from t2); +select count(*) from t1; +# UPDATE also blows up +update t1 set a = a + 1 where (a in (select b from t2)); +select count(*) from t1; +drop table t1, t2; + +--echo End of 4.1 tests # # alter temp table @@ -962,6 +980,7 @@ source include/varchar.inc; # Some errors/warnings on create # +--replace_result 1024 MAX_KEY_LENGTH 3072 MAX_KEY_LENGTH create table t1 (v varchar(65530), key(v)); drop table if exists t1; create table t1 (v varchar(65536)); @@ -975,6 +994,23 @@ drop table t1; eval set storage_engine=$default; # +# Test that we can create a large key +# +create table t1 (a varchar(255) character set utf8, + b varchar(255) character set utf8, + c varchar(255) character set utf8, + d varchar(255) character set utf8, + key (a,b,c,d)) engine=bdb; +drop table t1; +--error ER_TOO_LONG_KEY +create table t1 (a varchar(255) character set utf8, + b varchar(255) character set utf8, + c varchar(255) character set utf8, + d varchar(255) character set utf8, + e varchar(255) character set utf8, + key (a,b,c,d,e)) engine=bdb; + +# # Bug #14212: Server crash after COMMIT + ALTER TABLE # set autocommit=0; @@ -983,4 +1019,4 @@ commit; alter table t1 add primary key(a); drop table t1; -# End of 5.0 tests +--echo End of 5.0 tests diff --git a/mysql-test/t/bdb_gis.test b/mysql-test/t/bdb_gis.test new file mode 100644 index 00000000000..88dcbb7cbe9 --- /dev/null +++ b/mysql-test/t/bdb_gis.test @@ -0,0 +1,3 @@ +-- source include/have_bdb.inc +SET storage_engine=bdb; +--source include/gis_generic.inc diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test index d9c1abd9ba9..7871b3647e3 100644 --- a/mysql-test/t/bigint.test +++ b/mysql-test/t/bigint.test @@ -2,7 +2,7 @@ # Initialize --disable_warnings -drop table if exists t1; +drop table if exists t1, t2; --enable_warnings # diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index 70eb87131df..dc7f695e38e 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -64,7 +64,7 @@ select cast(_latin1'a ' AS char) as c2, cast(_latin1'abc' AS char(2)) as c3, cast(_latin1'a ' AS char(2)) as c4, - cast(_latin1'a' AS char(2)) as c5; + hex(cast(_latin1'a' AS char(2))) as c5; select cast(1000 as CHAR(3)); create table t1 select @@ -73,7 +73,7 @@ create table t1 select cast(_latin1'abc' AS char(2)) as c3, cast(_latin1'a ' AS char(2)) as c4, cast(_latin1'a' AS char(2)) as c5; -select * from t1; +select c1,c2,c3,c4,hex(c5) from t1; show create table t1; drop table t1; diff --git a/mysql-test/t/compress.test b/mysql-test/t/compress.test new file mode 100644 index 00000000000..46244edd2a8 --- /dev/null +++ b/mysql-test/t/compress.test @@ -0,0 +1,15 @@ +# Turn on compression between the client and server +# and run a number of tests + +-- source include/have_compress.inc + +connect (comp_con,localhost,root,,,,,COMPRESS); + +# Check compression turned on +SHOW STATUS LIKE 'Compression'; + +# Source select test case +-- source include/common-tests.inc + +# Check compression turned on +SHOW STATUS LIKE 'Compression'; diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test index 60ac7b88bbe..fef9d4552e6 100644 --- a/mysql-test/t/connect.test +++ b/mysql-test/t/connect.test @@ -1,7 +1,6 @@ # This test is to check various cases of connections -# with right and wrong password, with and without database -# Unfortunately the check is incomplete as we can't handle errors on connect -# Also we can't connect without database +# with right and wrong password, with and without database +# Unfortunately the check is incomplete as we can't connect without database # This test makes no sense with the embedded server --source include/not_embedded.inc @@ -10,69 +9,72 @@ drop table if exists t1,t2; --enable_warnings + #connect (con1,localhost,root,,""); #show tables; connect (con1,localhost,root,,mysql); show tables; -connect (con1,localhost,root,,test); +connect (con2,localhost,root,,test); show tables; -# Re enable this one day if error handling on connect will take place - -#connect (con1,localhost,root,z,test2); -#--error 1045 -#connect (con1,localhost,root,z,); -#--error 1045 +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1045 +connect (fail_con,localhost,root,z,test2); +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1045 +connect (fail_con,localhost,root,z,); grant ALL on *.* to test@localhost identified by "gambling"; grant ALL on *.* to test@127.0.0.1 identified by "gambling"; # Now check this user with different databases - #connect (con1,localhost,test,gambling,""); #show tables; -connect (con1,localhost,test,gambling,mysql); +connect (con3,localhost,test,gambling,mysql); show tables; -connect (con1,localhost,test,gambling,test); +connect (con4,localhost,test,gambling,test); show tables; -# Re enable this one day if error handling on connect will take place - -#connect (con1,localhost,test,,test2); -#--error 1045 -#connect (con1,localhost,test,,""); -#--error 1045 -#connect (con1,localhost,test,zorro,test2); -#--error 1045 -#connect (con1,localhost,test,zorro,); -#--error 1045 +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1045 +connect (fail_con,localhost,test,,test2); +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1045 +connect (fail_con,localhost,test,,""); +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1045 +connect (fail_con,localhost,test,zorro,test2); +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1045 +connect (fail_con,localhost,test,zorro,); # check if old password version also works update mysql.user set password=old_password("gambling2") where user=_binary"test"; flush privileges; -#connect (con1,localhost,test,gambling2,""); -#show tables; -connect (con1,localhost,test,gambling2,mysql); +connect (con10,localhost,test,gambling2,); +connect (con5,localhost,test,gambling2,mysql); set password=""; --error 1372 set password='gambling3'; set password=old_password('gambling3'); show tables; -connect (con1,localhost,test,gambling3,test); +connect (con6,localhost,test,gambling3,test); show tables; -# Re enable this one day if error handling on connect will take place - -#connect (con1,localhost,test,,test2); -#--error 1045 -#connect (con1,localhost,test,,); -#--error 1045 -#connect (con1,localhost,test,zorro,test2); -#--error 1045 -#connect (con1,localhost,test,zorro,); -#--error 1045 +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1045 +connect (fail_con,localhost,test,,test2); +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1045 +connect (fail_con,localhost,test,,); +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1045 +connect (fail_con,localhost,test,zorro,test2); +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1045 +connect (fail_con,localhost,test,zorro,); # remove user 'test' so that other tests which may use 'test' @@ -84,13 +86,13 @@ flush privileges; # # Bug#12517: Clear user variables and replication events before # closing temp tables in thread cleanup. -connect (con2,localhost,root,,test); -connection con2; +connect (con7,localhost,root,,test); +connection con7; create table t1 (id integer not null auto_increment primary key); create temporary table t2(id integer not null auto_increment primary key); set @id := 1; delete from t1 where id like @id; -disconnect con2; +disconnect con7; --sleep 5 connection default; drop table t1; diff --git a/mysql-test/t/count_distinct3.test b/mysql-test/t/count_distinct3.test index 52a4f271dac..f817b2c635d 100644 --- a/mysql-test/t/count_distinct3.test +++ b/mysql-test/t/count_distinct3.test @@ -17,7 +17,7 @@ while ($1) SET @rnd= RAND(); SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); SET @id_rev= @rnd_max - @id; - SET @grp= CAST(128.0 * @rnd AS UNSIGNED); + SET @grp= CAST(127.0 * @rnd AS UNSIGNED); INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); dec $1; } diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index b72dc49e89a..162db3d0c0a 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -3,7 +3,7 @@ # --disable_warnings -drop table if exists t1,t2,t3; +drop table if exists t1,t2,t3,t4,t5; drop database if exists mysqltest; --enable_warnings @@ -218,13 +218,6 @@ create table if not exists t1 select 1,2,3,4; create table if not exists t1 select 1; select * from t1; drop table t1; -create table t1 select 1,2,3; -create table if not exists t1 select 1,2; ---error 1136 -create table if not exists t1 select 1,2,3,4; -create table if not exists t1 select 1; -select * from t1; -drop table t1; # # Test create table if not exists with duplicate key error @@ -545,4 +538,119 @@ create table t1 (a int); create table if not exists t1 (a int); drop table t1; +# BUG#14139 +create table t1 ( + a varchar(112) charset utf8 collate utf8_bin not null, + primary key (a) +) select 'test' as a ; +--warning 1364 +show create table t1; +drop table t1; + +# +# BUG#14480: assert failure in CREATE ... SELECT because of wrong +# calculation of number of NULLs. +# +CREATE TABLE t2 ( + a int(11) default NULL +); +insert into t2 values(111); + +--warning 1364 +create table t1 ( + a varchar(12) charset utf8 collate utf8_bin not null, + b int not null, primary key (a) +) select a, 1 as b from t2 ; +show create table t1; +drop table t1; + +--warning 1364 +create table t1 ( + a varchar(12) charset utf8 collate utf8_bin not null, + b int not null, primary key (a) +) select a, 1 as c from t2 ; +show create table t1; +drop table t1; + +--warning 1364 +create table t1 ( + a varchar(12) charset utf8 collate utf8_bin not null, + b int null, primary key (a) +) select a, 1 as c from t2 ; +show create table t1; +drop table t1; + +--warning 1364 +create table t1 ( + a varchar(12) charset utf8 collate utf8_bin not null, + b int not null, primary key (a) +) select 'a' as a , 1 as b from t2 ; +show create table t1; +drop table t1; + +--warning 1364 +create table t1 ( + a varchar(12) charset utf8 collate utf8_bin, + b int not null, primary key (a) +) select 'a' as a , 1 as b from t2 ; +show create table t1; +drop table t1, t2; + +create table t1 ( + a1 int not null, + a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int +); +insert into t1 values (1,1,1, 1,1,1, 1,1,1); + +--warning 1364 +create table t2 ( + a1 varchar(12) charset utf8 collate utf8_bin not null, + a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int, + primary key (a1) +) select a1,a2,a3,a4,a5,a6,a7,a8,a9 from t1 ; +drop table t2; + +--warning 1364 +create table t2 ( + a1 varchar(12) charset utf8 collate utf8_bin, + a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int +) select a1,a2,a3,a4,a5,a6,a7,a8,a9 from t1; + +drop table t1, t2; +--warning 1364 +create table t1 ( + a1 int, a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int +); +insert into t1 values (1,1,1, 1,1,1, 1,1,1); + +--warning 1364 +create table t2 ( + a1 varchar(12) charset utf8 collate utf8_bin not null, + a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int, + primary key (a1) +) select a1,a2,a3,a4,a5,a6,a7,a8,a9 from t1 ; + +# Test the default value +drop table t2; + +create table t2 ( a int default 3, b int default 3) + select a1,a2 from t1; +show create table t2; + +drop table t1, t2; + # End of 4.1 tests + +# +# Bug #14155: Maximum value of MAX_ROWS handled incorrectly on 64-bit +# platforms +# +create table t1 (i int) engine=myisam max_rows=100000000000; +show create table t1; +alter table t1 max_rows=100; +show create table t1; +alter table t1 max_rows=100000000000; +show create table t1; +drop table t1; + +# End of 5.0 tests diff --git a/mysql-test/t/csv.test b/mysql-test/t/csv.test index 2ac46d75f9a..a028f6ced6d 100644 --- a/mysql-test/t/csv.test +++ b/mysql-test/t/csv.test @@ -1314,4 +1314,73 @@ select period from t1; drop table if exists t1,t2,t3,t4; +# +# Bug #13894 Server crashes on update of CSV table +# + +--disable_warnings +DROP TABLE IF EXISTS bug13894; +--enable_warnings + +CREATE TABLE bug13894 ( val integer ) ENGINE = CSV; +INSERT INTO bug13894 VALUES (5); +INSERT INTO bug13894 VALUES (10); +INSERT INTO bug13894 VALUES (11); +INSERT INTO bug13894 VALUES (10); +SELECT * FROM bug13894; +UPDATE bug13894 SET val=6 WHERE val=10; +SELECT * FROM bug13894; +DROP TABLE bug13894; + +# +# Bug #14672 Bug in deletion +# + +--disable_warnings +DROP TABLE IF EXISTS bug14672; +--enable_warnings + +CREATE TABLE bug14672 (c1 integer) engine = CSV; +INSERT INTO bug14672 VALUES (1), (2), (3); +SELECT * FROM bug14672; +DELETE FROM bug14672 WHERE c1 = 2; +SELECT * FROM bug14672; +INSERT INTO bug14672 VALUES (4); +SELECT * FROM bug14672; +INSERT INTO bug14672 VALUES (5); +SELECT * FROM bug14672; +DROP TABLE bug14672; + # End of 4.1 tests + +# +# BUG#13406 - incorrect amount of "records deleted" +# + +create table t1 (a int) engine=csv; +insert t1 values (1); +--enable_info +delete from t1; -- delete_row +delete from t1; -- delete_all_rows +--disable_info +insert t1 values (1),(2); +--enable_info +delete from t1; -- delete_all_rows +--disable_info +insert t1 values (1),(2),(3); +flush tables; +--enable_info +delete from t1; -- delete_row +--disable_info +insert t1 values (1),(2),(3),(4); +flush tables; +select count(*) from t1; +--enable_info +delete from t1; -- delete_all_rows +--disable_info +insert t1 values (1),(2),(3),(4),(5); +--enable_info +truncate table t1; -- truncate +--disable_info +drop table t1; + diff --git a/mysql-test/t/ctype_cp1250_ch.test b/mysql-test/t/ctype_cp1250_ch.test index ea4b35a44a3..2d1e5f0bf9d 100644 --- a/mysql-test/t/ctype_cp1250_ch.test +++ b/mysql-test/t/ctype_cp1250_ch.test @@ -23,4 +23,25 @@ SELECT * FROM t1 WHERE popisek = '2005-01-1'; SELECT * FROM t1 WHERE popisek LIKE '2005-01-1'; drop table t1; +# +# Bug#13347: empty result from query with like and cp1250 charset +# +set names cp1250; +CREATE TABLE t1 +( + id INT AUTO_INCREMENT PRIMARY KEY, + str VARCHAR(32) CHARACTER SET cp1250 COLLATE cp1250_czech_cs NOT NULL default '', + UNIQUE KEY (str) +); + +INSERT INTO t1 VALUES (NULL, 'a'); +INSERT INTO t1 VALUES (NULL, 'aa'); +INSERT INTO t1 VALUES (NULL, 'aaa'); +INSERT INTO t1 VALUES (NULL, 'aaaa'); +INSERT INTO t1 VALUES (NULL, 'aaaaa'); +INSERT INTO t1 VALUES (NULL, 'aaaaaa'); +INSERT INTO t1 VALUES (NULL, 'aaaaaaa'); +select * from t1 where str like 'aa%'; +drop table t1; + # End of 4.1 tests diff --git a/mysql-test/t/ctype_cp932_binlog.test b/mysql-test/t/ctype_cp932_binlog.test new file mode 100644 index 00000000000..270e27cf27f --- /dev/null +++ b/mysql-test/t/ctype_cp932_binlog.test @@ -0,0 +1,34 @@ +-- source include/not_embedded.inc +-- source include/have_cp932.inc + +--character_set cp932 +--disable_warnings +drop table if exists t1; +--enable_warnings + +set names cp932; +set character_set_database = cp932; + +# Test prepared statement with 0x8300 sequence in parameter while +# running with cp932 client character set. +RESET MASTER; +CREATE TABLE t1(f1 blob); +PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)'; +SET @var1= x'8300'; +# TODO: Note that this doesn't actually test the code which was added for +# bug#11338 because this syntax for prepared statements causes the PS to +# be replicated differently than if we executed the PS from C or Java. +# Using this syntax, variable names are inserted into the binlog instead +# of values. The real goal of this test is to check the code that was +# added to Item_param::query_val_str() in order to do hex encoding of +# PS parameters when the client character set is cp932; +# Bug#11338 has an example java program which can be used to verify this +# code (and I have used it to test the fix) until there is some way to +# exercise this code from mysql-test-run. +EXECUTE stmt1 USING @var1; +SHOW BINLOG EVENTS FROM 98; +SELECT HEX(f1) FROM t1; +DROP table t1; +# end test for bug#11338 + +# End of 4.1 tests diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test index 9949ef88da4..5648cea7fd3 100644 --- a/mysql-test/t/ctype_recoding.test +++ b/mysql-test/t/ctype_recoding.test @@ -144,8 +144,7 @@ create table t1 (a char(10) character set cp1251); insert into t1 values (_koi8r'×ÁÓÑ'); # this is possible: select * from t1 where a=_koi8r'×ÁÓÑ'; -# this is not possible, because we have a function, not just a constant: ---error 1267 +# this is possible, because we have a function with constant arguments: select * from t1 where a=concat(_koi8r'×ÁÓÑ'); # this is not posible, cannot convert _latin1'×ÁÓÑ' into cp1251: --error 1267 @@ -154,6 +153,14 @@ drop table t1; set names latin1; # +# Bug#10446 Illegal mix of collations +# +create table t1 (a char(10) character set utf8 collate utf8_bin); +insert into t1 values (' xxx'); +select * from t1 where a=lpad('xxx',10,' '); +drop table t1; + +# # Check more automatic conversion # set names koi8r; diff --git a/mysql-test/t/ctype_uca.test b/mysql-test/t/ctype_uca.test index 6d8713f4910..3e49b9de883 100644 --- a/mysql-test/t/ctype_uca.test +++ b/mysql-test/t/ctype_uca.test @@ -212,6 +212,7 @@ select group_concat(c1 order by c1) from t1 group by c1 collate utf8_slovak_ci; select group_concat(c1 order by c1) from t1 group by c1 collate utf8_spanish2_ci; select group_concat(c1 order by c1) from t1 group by c1 collate utf8_roman_ci; select group_concat(c1 order by c1) from t1 group by c1 collate utf8_esperanto_ci; +select group_concat(c1 order by c1) from t1 group by c1 collate utf8_hungarian_ci; drop table t1; diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 626c7e0e1b6..04de13f8228 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -421,6 +421,14 @@ insert into t1 values (0x005b); select hex(a) from t1; drop table t1; +# +# Bug #14583 Bug on query using a LIKE on indexed field with ucs2_bin collation +# +create table t1(f1 varchar(5) CHARACTER SET ucs2 COLLATE ucs2_bin NOT NULL) engine=InnoDB; +insert into t1 values('a'); +create index t1f1 on t1(f1); +select f1 from t1 where f1 like 'a%'; +drop table t1; # End of 4.1 tests # diff --git a/mysql-test/t/ctype_ujis.test b/mysql-test/t/ctype_ujis.test index c1d6c67387b..77d250b5c45 100644 --- a/mysql-test/t/ctype_ujis.test +++ b/mysql-test/t/ctype_ujis.test @@ -1170,7 +1170,7 @@ INSERT INTO t1 VALUES(_ujis 0xA4A2); DELIMITER |; CREATE PROCEDURE sp1() BEGIN - DECLARE a CHAR(1); + DECLARE a CHAR(2) CHARSET ujis; DECLARE cur1 CURSOR FOR SELECT c1 FROM t1; OPEN cur1; FETCH cur1 INTO a; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 5670e9efbf9..a96564f4e76 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -884,7 +884,9 @@ SELECT DISTINCT id FROM t1 ORDER BY id; DROP TABLE t1; # -# Bugs#10504: Character set does not support traditional mode +# Bug#10504: Character set does not support traditional mode +# Bug#14146: CHAR(...USING ...) and CONVERT(CHAR(...) USING...) +# produce different results # set names utf8; # correct value @@ -894,12 +896,14 @@ select char(0xd18f using utf8); select char(53647 using utf8); # incorrect value: return with warning select char(0xff,0x8f using utf8); +select convert(char(0xff,0x8f) using utf8); # incorrect value in strict mode: return NULL with "Error" level warning set sql_mode=traditional; select char(0xff,0x8f using utf8); select char(195 using utf8); select char(196 using utf8); select char(2557 using utf8); +select convert(char(0xff,0x8f) using utf8); # # Check convert + char + using diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test index f76f51fd12d..c007c2f5205 100644 --- a/mysql-test/t/date_formats.test +++ b/mysql-test/t/date_formats.test @@ -261,4 +261,12 @@ select str_to_date("2003-04-05 g", "%Y-%m-%d") as f1, str_to_date("2003-04-05 10:11:12.101010234567", "%Y-%m-%d %H:%i:%S.%f") as f2; --enable_ps_protocol +# +# Bug #14016 +# +create table t1 (f1 datetime); +insert into t1 (f1) values ("2005-01-01"); +insert into t1 (f1) values ("2005-02-01"); +select date_format(f1, "%m") as d1, date_format(f1, "%M") as d2 from t1 order by date_format(f1, "%M"); +drop table t1; # End of 4.1 tests diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index bc81f716ec7..a209088f202 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -11,8 +11,5 @@ ############################################################################## sp-goto : GOTO is currently is disabled - will be fixed in the future -rpl_relayrotate : Unstable test case, bug#12429 -rpl_until : Unstable test case, bug#12429 -rpl_deadlock : Unstable test case, bug#12429 -kill : Unstable test case, bug#9712 -federated : Broken test case, bug#14272 +subselect : Bug#15706 +type_time : Bug#15805 diff --git a/mysql-test/t/drop_temp_table.test b/mysql-test/t/drop_temp_table.test index 38c13e3e5e4..bc06de4096c 100644 --- a/mysql-test/t/drop_temp_table.test +++ b/mysql-test/t/drop_temp_table.test @@ -1,6 +1,10 @@ # Embedded server doesn't support binlog -- source include/not_embedded.inc +--disable_warnings +drop database if exists `drop-temp+table-test`; +--enable_warnings + connect (con1,localhost,root,,); connect (con2,localhost,root,,); connection con1; diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index 9880cd78653..b6b3b90c083 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1188,5 +1188,40 @@ connection slave; DROP TABLE federated.normal_table; # END ALTER TEST +# +# Test BUG #14532 - bit columns broken in federated +# storage engine +# +--disable_warnings +DROP TABLE IF EXISTS federated.t1; +--enable_warnings +CREATE TABLE federated.t1 ( + `bitty` bit(3) +) DEFAULT CHARSET=latin1; + +connection master; + +--disable_warnings +DROP TABLE IF EXISTS federated.t1; +--enable_warnings + +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( + `bitty` bit(3) +) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 + CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; + +INSERT INTO federated.t1 VALUES (b'001'); +INSERT INTO federated.t1 VALUES (b'010'); +INSERT INTO federated.t1 VALUES (b'011'); +INSERT INTO federated.t1 VALUES (b'100'); +INSERT INTO federated.t1 VALUES (b'101'); +INSERT INTO federated.t1 VALUES (b'110'); +INSERT INTO federated.t1 VALUES (b'111'); +select * FROM federated.t1; +drop table federated.t1; + +connection slave; +drop table federated.t1; source include/federated_cleanup.inc; diff --git a/mysql-test/t/flush_read_lock_kill.test b/mysql-test/t/flush_read_lock_kill.test index de2576300dc..19a47b2893a 100644 --- a/mysql-test/t/flush_read_lock_kill.test +++ b/mysql-test/t/flush_read_lock_kill.test @@ -42,7 +42,7 @@ connection con1; # debug build running without our --debug=make_global..., will be # error 0 (no error). The only important thing to test is that on # debug builds with our --debug=make_global... we don't hang forever. ---error 0,1053 +--error 0,1053,2013 reap; connection con2; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 08648f4e0a6..ea92ec944ed 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -348,6 +348,13 @@ INSERT INTO t1 VALUES('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'); SET myisam_repair_threads=2; REPAIR TABLE t1; SET myisam_repair_threads=@@global.myisam_repair_threads; + +# +# BUG#5686 - #1034 - Incorrect key file for table - only utf8 +# +INSERT INTO t1 VALUES('testword\'\''); +SELECT a FROM t1 WHERE MATCH a AGAINST('testword' IN BOOLEAN MODE); +SELECT a FROM t1 WHERE MATCH a AGAINST('testword\'\'' IN BOOLEAN MODE); DROP TABLE t1; # End of 4.1 tests diff --git a/mysql-test/t/fulltext2.test b/mysql-test/t/fulltext2.test index bcd39b9ea04..7a7b572d58f 100644 --- a/mysql-test/t/fulltext2.test +++ b/mysql-test/t/fulltext2.test @@ -179,7 +179,37 @@ update t1 set a='aaaxxx' where a = 'aaayyy'; select count(*) from t1 where match a against ('aaaxxx' in boolean mode); select count(*) from t1 where match a against ('aaayyy' in boolean mode); select count(*) from t1 where match a against ('aaazzz' in boolean mode); +drop table t1; + +# +# BUG#11336 +# +# for uca collation isalnum and strnncollsp don't agree on whether +# 0xC2A0 is a space (strnncollsp is right, isalnum is wrong). +# +# they still don't, the bug was fixed by avoiding strnncollsp +# +set names utf8; +create table t1(a text,fulltext(a)) collate=utf8_swedish_ci; +insert into t1 values('test test '),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), +('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'); +delete from t1 limit 1; drop table t1; +set names latin1; # End of 4.1 tests diff --git a/mysql-test/t/func_equal.test b/mysql-test/t/func_equal.test index 4c88ed170a1..1c219af0254 100644 --- a/mysql-test/t/func_equal.test +++ b/mysql-test/t/func_equal.test @@ -34,4 +34,13 @@ select * from t1 where value <=> value; select * from t1 where id <=> value or value<=>id; drop table t1,t2; +# +# Bug #12612: quoted bigint unsigned value and the use of "in" in where clause +# +create table t1 (a bigint unsigned); +insert into t1 values (4828532208463511553); +select * from t1 where a = '4828532208463511553'; +select * from t1 where a in ('4828532208463511553'); +drop table t1; + # End of 4.1 tests diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index a519d51e0b5..058df9af56b 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -69,7 +69,7 @@ set group_concat_max_len = 1024; # Test errors --error 1111 -select group_concat(sum(a)) from t1 group by grp; +select group_concat(sum(c)) from t1 group by grp; --error 1054 select grp,group_concat(c order by 2) from t1 group by grp; @@ -390,3 +390,19 @@ SELECT GROUP_CONCAT(a ORDER BY a) FROM t1 GROUP BY id; DROP TABLE t1; # End of 4.1 tests + +# +# Bug#8568 "GROUP_CONCAT returns string, unless in a UNION in which case +# returns BLOB": add a test case, the bug can not be repeated any more. +# + +set names latin1; +create table t1 (a char, b char); +insert into t1 values ('a', 'a'), ('a', 'b'), ('b', 'a'), ('b', 'b'); +create table t2 select group_concat(b) as a from t1 where a = 'a'; +create table t3 (select group_concat(a) as a from t1 where a = 'a') union + (select group_concat(b) as a from t1 where a = 'b'); +select charset(a) from t2; +select charset(a) from t3; +drop table t1, t2, t3; +set names default; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 9237205eeb5..c667f90940c 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -2,8 +2,6 @@ # simple test of all group functions # ---source include/have_innodb.inc - --disable_warnings drop table if exists t1,t2; --enable_warnings @@ -545,10 +543,12 @@ DROP TABLE t1; # Bug #12882 min/max inconsistent on empty table # +--disable_warnings create table t1m (a int) engine=myisam; create table t1i (a int) engine=innodb; create table t2m (a int) engine=myisam; create table t2i (a int) engine=innodb; +--enable_warnings insert into t2m values (5); insert into t2i values (5); diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index 2935f24f2d7..24dd18daab1 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -116,6 +116,16 @@ insert into t1 values (1); select rand(i) from t1; drop table t1; +# +# Bug #14009: use of abs() on null value causes problems with filesort +# +# InnoDB is required to reproduce the fault, but it is okay if we default to +# MyISAM when testing. +create table t1 (a varchar(90), ts datetime not null, index (a)) engine=innodb default charset=utf8; +insert into t1 values ('http://www.foo.com/', now()); +select a from t1 where a='http://www.foo.com/' order by abs(timediff(ts, 0)); +drop table t1; + # End of 4.1 tests # diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 142bd29fa2d..bb3f621d194 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -372,6 +372,9 @@ insert into t1 values (pointfromtext('point(1,1)')); drop table t1; +select (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))); +select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))); + # End of 4.1 tests # diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 635c7a3f4e7..e806df5e91c 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -487,4 +487,16 @@ flush privileges; set @user123="non-existent"; select * from mysql.db where user=@user123; +set names koi8r; +create database ÂÄ; +grant select on ÂÄ.* to root@localhost; +select hex(Db) from mysql.db where Db='ÂÄ'; +show grants for root@localhost; +flush privileges; +show grants for root@localhost; +drop database ÂÄ; +revoke all privileges on ÂÄ.* from root@localhost; +show grants for root@localhost; +set names latin1; + # End of 4.1 tests diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index 2fa82ce5dce..c19bb1482d6 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -155,6 +155,38 @@ flush privileges; drop database mysqltest; use test; + +# +# Bug #15775: "drop user" command does not refresh acl_check_hosts +# + +# Create some test users +create user mysqltest_1@host1; +create user mysqltest_2@host2; +create user mysqltest_3@host3; +create user mysqltest_4@host4; +create user mysqltest_5@host5; +create user mysqltest_6@host6; +create user mysqltest_7@host7; +flush privileges; + +# Drop one user +drop user mysqltest_3@host3; + +# This connect failed before fix since the acl_check_hosts list was corrupted by the "drop user" +connect (con8,127.0.0.1,root,,test,$MASTER_MYPORT,); +disconnect con8; +connection default; + +# Clean up - Drop all of the remaining users at once +drop user mysqltest_1@host1, mysqltest_2@host2, mysqltest_4@host4, + mysqltest_5@host5, mysqltest_6@host6, mysqltest_7@host7; + +# Check that it's still possible to connect +connect (con9,127.0.0.1,root,,test,$MASTER_MYPORT,); +disconnect con9; +connection default; + # # Create and drop user # diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 3d751f4a571..e15ef92116c 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -693,3 +693,25 @@ create table t1(a int, key(a)) engine=innodb; insert into t1 values(1); select a, count(a) from t1 group by a with rollup; drop table t1; + +# +# Bug #13293 Wrongly used index results in endless loop. +# +create table t1 (f1 int, f2 char(1), primary key(f1,f2)) engine=innodb; +insert into t1 values ( 1,"e"),(2,"a"),( 3,"c"),(4,"d"); +alter table t1 drop primary key, add primary key (f2, f1); +explain select distinct f1 a, f1 b from t1; +explain select distinct f1, f2 from t1; +drop table t1; + +# +# Bug #14920 Ordering aggregated result sets with composite primary keys +# corrupts resultset +# +create table t1 (c1 int not null,c2 int not null, primary key(c1,c2)); +insert into t1 (c1,c2) values +(10,1),(10,2),(10,3),(20,4),(20,5),(20,6),(30,7),(30,8),(30,9); +select distinct c1, c2 from t1 order by c2; +select c1,min(c2) as c2 from t1 group by c1 order by c2; +select c1,c2 from t1 group by c1,c2 order by c2; +drop table t1; diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test index 1bb9b1d3504..3fb09df5f2f 100644 --- a/mysql-test/t/handler.test +++ b/mysql-test/t/handler.test @@ -3,7 +3,7 @@ # --disable_warnings -drop table if exists t1; +drop table if exists t1,t3,t4,t5; --enable_warnings create table t1 (a int, b char(10), key a(a), key b(a,b)); @@ -347,4 +347,79 @@ drop table t3; drop table t4; drop table t5; +# +# Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash +# +create table t1 (c1 int); +insert into t1 values (1); +# client 1 +handler t1 open; +handler t1 read first; +# client 2 +connect (con2,localhost,root,,); +connection con2; +--exec echo send the below to another connection, do not wait for the result +send optimize table t1; +--sleep 1 +# client 1 +--exec echo proceed with the normal connection +connection default; +handler t1 read next; +handler t1 close; +# client 2 +--exec echo read the result from the other connection +connection con2; +reap; +# client 1 +--exec echo proceed with the normal connection +connection default; +drop table t1; + # End of 4.1 tests + +# +# Addendum to Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash +# Show that DROP TABLE can no longer deadlock against +# FLUSH TABLES WITH READ LOCK. This is a 5.0 issue. +# +create table t1 (c1 int); +insert into t1 values (14397); +flush tables with read lock; +# The thread with the global read lock cannot drop the table itself: +--error 1223 +drop table t1; +# +# client 2 +# We need a second connection to try the drop. +# The drop waits for the global read lock to go away. +# Without the addendum fix it locked LOCK_open before entering the wait loop. +connection con2; +--exec echo send the below to another connection, do not wait for the result +send drop table t1; +--sleep 1 +# +# client 1 +# Now we need something that wants LOCK_open. A simple table access which +# opens the table does the trick. +--exec echo proceed with the normal connection +connection default; +# This would hang on LOCK_open without the 5.0 addendum fix. +select * from t1; +# Release the read lock. This should make the DROP go through. +unlock tables; +# +# client 2 +# Read the result of the drop command. +connection con2; +--exec echo read the result from the other connection +reap; +# +# client 1 +# Now back to normal operation. The table should not exist any more. +--exec echo proceed with the normal connection +connection default; +--error 1146 +select * from t1; +# Just to be sure and not confuse the next test case writer. +drop table if exists t1; + diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 9fb57fc187b..f835a7148a2 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -379,6 +379,8 @@ where table_schema='test'; select index_name from information_schema.statistics where table_schema='test'; select constraint_name from information_schema.table_constraints where table_schema='test'; +show create view v2; +show create table v3; drop view v2; drop view v3; drop table t4; @@ -499,8 +501,8 @@ drop table t1; # grant select on test.* to mysqltest_4@localhost; -connect (user4,localhost,mysqltest_4,,); -connection user4; +connect (user10261,localhost,mysqltest_4,,); +connection user10261; SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME='TABLE_NAME'; connection default; @@ -727,3 +729,64 @@ use information_schema; select 1 from (select 1 from test.t1) a; use test; drop table t1; + +# +# Bug #14290: character_maximum_length for text fields +# + +create table t1(a blob, b text charset utf8, c text charset ucs2); +select data_type, character_octet_length, character_maximum_length + from information_schema.columns where table_name='t1'; +drop table t1; + +# +# Bug#14476 `information_schema`.`TABLES`.`TABLE_TYPE` with empty value +# +create table t1 (f1 int(11)); +create view v1 as select * from t1; +drop table t1; +select table_type from information_schema.tables +where table_name="v1"; +drop view v1; + +# +# Bug #14387 SHOW COLUMNS doesn't work on temporary tables +# Bug #15224 SHOW INDEX from temporary table doesn't work +# Bug #12770 DESC cannot display the info. about temporary table +# +create temporary table t1(f1 int, index(f1)); +show columns from t1; +describe t1; +show indexes from t1; +drop table t1; + +# +# Bug#14271 I_S: columns has no size for (var)binary columns +# +create table t1(f1 binary(32), f2 varbinary(64)); +select character_maximum_length, character_octet_length +from information_schema.columns where table_name='t1'; +drop table t1; + +# +# Bug#15533 crash, information_schema, function, view +# +CREATE TABLE t1 (f1 BIGINT, f2 VARCHAR(20), f3 BIGINT); +INSERT INTO t1 SET f1 = 1, f2 = 'Schoenenbourg', f3 = 1; + +CREATE FUNCTION func2() RETURNS BIGINT RETURN 1; + +delimiter //; +CREATE FUNCTION func1() RETURNS BIGINT +BEGIN + RETURN ( SELECT COUNT(*) FROM INFORMATION_SCHEMA.VIEWS); +END// +delimiter ;// + +CREATE VIEW v1 AS SELECT 1 FROM t1 + WHERE f3 = (SELECT func2 ()); +SELECT func1(); +DROP TABLE t1; +DROP VIEW v1; +DROP FUNCTION func1; +DROP FUNCTION func2; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index cf0e08e2e66..887d8193157 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1356,8 +1356,8 @@ source include/varchar.inc; # Clean up filename -- embedded server reports whole path without .frm, # regular server reports relative path with .frm (argh!) --replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t1.frm t1 ---error 1005 create table t1 (v varchar(65530), key(v)); +drop table t1; create table t1 (v varchar(65536)); show create table t1; drop table t1; @@ -1485,7 +1485,7 @@ CREATE TEMPORARY TABLE t2 DROP TABLE t1; # -# Test that index column max sizes are checked (bug #13315) +# Test that index column max sizes are honored (bug #13315) # # prefix index @@ -1512,22 +1512,36 @@ create table t8 (col1 blob, index(col1(767))) create table t9 (col1 varchar(512), col2 varchar(512), index(col1, col2)) character set = latin1 engine = innodb; +show create table t9; + drop table t1, t2, t3, t4, t5, t6, t7, t8, t9; ---error 1005 -create table t1 (col1 varchar(768), index (col1)) +# these should have their index length trimmed +create table t1 (col1 varchar(768), index(col1)) character set = latin1 engine = innodb; ---error 1005 -create table t2 (col1 varchar(768) primary key) +create table t2 (col1 varbinary(768), index(col1)) character set = latin1 engine = innodb; ---error 1005 -create table t3 (col1 varbinary(768) primary key) +create table t3 (col1 text, index(col1(768))) character set = latin1 engine = innodb; ---error 1005 -create table t4 (col1 text, index(col1(768))) +create table t4 (col1 blob, index(col1(768))) character set = latin1 engine = innodb; ---error 1005 -create table t5 (col1 blob, index(col1(768))) + +show create table t1; + +drop table t1, t2, t3, t4; + +# these should be refused +--error 1071 +create table t1 (col1 varchar(768) primary key) + character set = latin1 engine = innodb; +--error 1071 +create table t2 (col1 varbinary(768) primary key) + character set = latin1 engine = innodb; +--error 1071 +create table t3 (col1 text, primary key(col1(768))) + character set = latin1 engine = innodb; +--error 1071 +create table t4 (col1 blob, primary key(col1(768))) character set = latin1 engine = innodb; # @@ -1751,3 +1765,106 @@ insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); drop table t1; drop table t2; commit; + +# tests for bugs #9802 and #13778 + +# test that FKs between invalid types are not accepted + +set foreign_key_checks=0; +create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; +-- error 1005 +create table t1(a char(10) primary key, b varchar(20)) engine = innodb; +set foreign_key_checks=1; +drop table t2; + +# test that FKs between different charsets are not accepted in CREATE even +# when f_k_c is 0 + +set foreign_key_checks=0; +create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +-- error 1005 +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8; +set foreign_key_checks=1; +drop table t1; + +# test that invalid datatype conversions with ALTER are not allowed + +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb; +create table t1(a varchar(10) primary key) engine = innodb; +-- error 1025,1025 +alter table t1 modify column a int; +set foreign_key_checks=1; +drop table t2,t1; + +# test that charset conversions with ALTER are allowed when f_k_c is 0 + +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; +create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +alter table t1 convert to character set utf8; +set foreign_key_checks=1; +drop table t2,t1; + +# test that RENAME does not allow invalid charsets when f_k_c is 0 + +set foreign_key_checks=0; +create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; +create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; +-- error 1025 +rename table t3 to t1; +set foreign_key_checks=1; +drop table t2,t3; + +# +# Test that we can create a large (>1K) key +# +create table t1 (a varchar(255) character set utf8, + b varchar(255) character set utf8, + c varchar(255) character set utf8, + d varchar(255) character set utf8, + key (a,b,c,d)) engine=innodb; +drop table t1; +--error ER_TOO_LONG_KEY +create table t1 (a varchar(255) character set utf8, + b varchar(255) character set utf8, + c varchar(255) character set utf8, + d varchar(255) character set utf8, + e varchar(255) character set utf8, + key (a,b,c,d,e)) engine=innodb; + +# test that foreign key errors are reported correctly (Bug #15550) + +create table t1(a int primary key) row_format=redundant engine=innodb; +create table t2(a int primary key,constraint foreign key(a)references t1(a)) row_format=compact engine=innodb; +create table t3(a int primary key) row_format=compact engine=innodb; +create table t4(a int primary key,constraint foreign key(a)references t3(a)) row_format=redundant engine=innodb; + +insert into t1 values(1); +insert into t3 values(1); +-- error 1452 +insert into t2 values(2); +-- error 1452 +insert into t4 values(2); +insert into t2 values(1); +insert into t4 values(1); +-- error 1451 +update t1 set a=2; +-- error 1452 +update t2 set a=2; +-- error 1451 +update t3 set a=2; +-- error 1452 +update t4 set a=2; +-- error 1451 +truncate t1; +-- error 1451 +truncate t3; +truncate t2; +truncate t4; +truncate t1; +truncate t3; + +drop table t4,t3,t2,t1; + +--echo End of 5.0 tests diff --git a/mysql-test/t/innodb_gis.test b/mysql-test/t/innodb_gis.test new file mode 100644 index 00000000000..142b526af92 --- /dev/null +++ b/mysql-test/t/innodb_gis.test @@ -0,0 +1,3 @@ +--source include/have_innodb.inc +SET storage_engine=innodb; +--source include/gis_generic.inc diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 7116a25ff39..5dd6f338865 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -202,4 +202,26 @@ insert into t1 select t2.a from t2 on duplicate key update t2.a= a + t2.b; insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b; drop table t1,t2,t3; +# +# Bug #12695 Item_func_isnull::update_used_tables() did not update +# const_item_cache +create table t1(f1 varchar(5) key); +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1; +select * from t1; +drop table t1; + +# +# Bug #13392 values() fails with 'ambiguous' or returns NULL +# with ON DUPLICATE and SELECT +create table t1(x int, y int); +create table t2(x int, z int); +insert into t1(x,y) select x,z from t2 on duplicate key update x=values(x); +--error 1054 +insert into t1(x,y) select x,z from t2 on duplicate key update x=values(z); +--error 1054 +insert into t1(x,y) select x,z from t2 on duplicate key update x=values(t2.x); +drop table t1,t2; + # End of 4.1 tests diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index bb82a93c6c4..553aaf987bb 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -334,3 +334,210 @@ select t1.i,t2.i,t3.i from t2 right join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i drop table t1,t2,t3; # End of 4.1 tests + +# +# Tests for WL#2486 Natural/using join according to SQL:2003. +# +# NOTICE: +# - The tests are designed so that all statements, except MySQL +# extensions run on any SQL server. Please do no change. +# - Tests marked with TODO will be submitted as bugs. +# + +create table t1 (c int, b int); +create table t2 (a int, b int); +create table t3 (b int, c int); +create table t4 (y int, c int); +create table t5 (y int, z int); +create table t6 (a int, c int); + +insert into t1 values (10,1); +insert into t1 values (3 ,1); +insert into t1 values (3 ,2); +insert into t2 values (2, 1); +insert into t3 values (1, 3); +insert into t3 values (1,10); +insert into t4 values (11,3); +insert into t4 values (2, 3); +insert into t5 values (11,4); +insert into t6 values (2, 3); + +-- Views with simple natural join. +create algorithm=merge view v1a as +select * from t1 natural join t2; +-- as above, but column names are cross-renamed: a->c, c->b, b->a +create algorithm=merge view v1b(a,b,c) as +select * from t1 natural join t2; +-- as above, but column names are aliased: a->c, c->b, b->a +create algorithm=merge view v1c as +select b as a, c as b, a as c from t1 natural join t2; +-- as above, but column names are cross-renamed, and aliased +-- a->c->b, c->b->a, b->a->c +create algorithm=merge view v1d(b, a, c) as +select a as c, c as b, b as a from t1 natural join t2; + +-- Views with JOIN ... ON +create algorithm=merge view v2a as +select t1.c, t1.b, t2.a from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; +create algorithm=merge view v2b as +select t1.c as b, t1.b as a, t2.a as c +from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; + +-- Views with bigger natural join +create algorithm=merge view v3a as +select * from t1 natural join t2 natural join t3; +create algorithm=merge view v3b as +select * from t1 natural join (t2 natural join t3); + +-- View over views with mixed natural join and join ... on +create algorithm=merge view v4 as +select * from v2a natural join v3a; + +-- Nested natural/using joins. +select * from (t1 natural join t2) natural join (t3 natural join t4); +select * from (t1 natural join t2) natural left join (t3 natural join t4); +select * from (t3 natural join t4) natural right join (t1 natural join t2); +select * from (t1 natural left join t2) natural left join (t3 natural left join t4); +select * from (t4 natural right join t3) natural right join (t2 natural right join t1); +select * from t1 natural join t2 natural join t3 natural join t4; +select * from ((t1 natural join t2) natural join t3) natural join t4; +select * from t1 natural join (t2 natural join (t3 natural join t4)); +-- BUG#15355: this query fails in 'prepared statements' mode +-- select * from ((t3 natural join (t1 natural join t2)) natural join t4) natural join t5; +-- select * from ((t3 natural left join (t1 natural left join t2)) natural left join t4) natural left join t5; +select * from t5 natural right join (t4 natural right join ((t2 natural right join t1) natural right join t3)); +select * from (t1 natural join t2), (t3 natural join t4); +-- MySQL extension - nested comma ',' operator instead of cross join. +-- BUG#15357 - natural join with nested cross-join results in incorrect columns +-- select * from t5 natural join ((t1 natural join t2), (t3 natural join t4)); +-- select * from ((t1 natural join t2), (t3 natural join t4)) natural join t5; +-- select * from t5 natural join ((t1 natural join t2) cross join (t3 natural join t4)); +-- select * from ((t1 natural join t2) cross join (t3 natural join t4)) natural join t5; + +select * from (t1 join t2 using (b)) join (t3 join t4 using (c)) using (c); +select * from (t1 join t2 using (b)) natural join (t3 join t4 using (c)); + + +-- Other clauses refer to NJ columns. +select a,b,c from (t1 natural join t2) natural join (t3 natural join t4) +where b + 1 = y or b + 10 = y group by b,c,a having min(b) < max(y) order by a; +select * from (t1 natural join t2) natural left join (t3 natural join t4) +where b + 1 = y or b + 10 = y group by b,c,a,y having min(b) < max(y) order by a, y; +select * from (t3 natural join t4) natural right join (t1 natural join t2) +where b + 1 = y or b + 10 = y group by b,c,a,y having min(b) < max(y) order by a, y; + +-- Qualified column references to NJ columns. +select * from t1 natural join t2 where t1.c > t2.a; +select * from t1 natural join t2 where t1.b > t2.b; +select * from t1 natural left join (t4 natural join t5) where t5.z is not NULL; + +-- Nested 'join ... on' - name resolution of ON conditions +select * from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; +select * from (t2 join t4 on b + 1 = y) join t1 on t1.c = t4.c; +select * from t1 natural join (t2 join t4 on b + 1 = y); +select * from (t1 cross join t2) join (t3 cross join t4) on (a < y and t2.b < t3.c); + +-- MySQL extension - 'join ... on' over nested comma operator +select * from (t1, t2) join (t3, t4) on (a < y and t2.b < t3.c); +select * from (t1 natural join t2) join (t3 natural join t4) on a = y; +select * from ((t3 join (t1 join t2 on c > a) on t3.b < t2.a) join t4 on y > t1.c) join t5 on z = t1.b + 3; + +-- MySQL extension - refererence qualified coalesced columns +select * from t1 natural join t2 where t1.b > 0; +select * from t1 natural join (t4 natural join t5) where t4.y > 7; +select * from (t4 natural join t5) natural join t1 where t4.y > 7; +select * from t1 natural left join (t4 natural join t5) where t4.y > 7; +select * from (t4 natural join t5) natural right join t1 where t4.y > 7; +select * from (t1 natural join t2) join (t3 natural join t4) on t1.b = t3.b; + +-- MySQL extension - select qualified columns of NJ columns +select t1.*, t2.* from t1 natural join t2; +select t1.*, t2.*, t3.*, t4.* from (t1 natural join t2) natural join (t3 natural join t4); + +-- Queries over subselects in the FROM clause +select * from (select * from t1 natural join t2) as t12 + natural join + (select * from t3 natural join t4) as t34; +select * from (select * from t1 natural join t2) as t12 + natural left join + (select * from t3 natural join t4) as t34; +select * from (select * from t3 natural join t4) as t34 + natural right join + (select * from t1 natural join t2) as t12; + +-- Queries over views +select * from v1a; +select * from v1b; +select * from v1c; +select * from v1d; +select * from v2a; +select * from v2b; +select * from v3a; +select * from v3b; +select * from v4; +select * from v1a natural join v2a; +select v2a.* from v1a natural join v2a; +select * from v1b join v2a on v1b.b = v2a.c; +select * from v1c join v2a on v1c.b = v2a.c; +select * from v1d join v2a on v1d.a = v2a.c; +select * from v1a join (t3 natural join t4) on a = y; + +-- TODO: add tests with correlated subqueries for natural join/join on. +-- related to BUG#15269 + + +---------------------------------------------------------------------- +-- Negative tests (tests for errors) +---------------------------------------------------------------------- +-- error 1052 +select * from t1 natural join (t3 cross join t4); -- works in Oracle - bug +-- error 1052 +select * from (t3 cross join t4) natural join t1; -- works in Oracle - bug +-- error 1052 +select * from t1 join (t2, t3) using (b); +-- error 1052 +select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; +-- error 1052 +select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; +-- error 1052 +-- BUG#15357: doesn't detect non-unique column 'c', as in the above query. +-- select * from t6 natural join ((t1 natural join t2), (t3 natural join t4)); +-- error 1052 +select * from (t1 join t2 on t1.b=t2.b) natural join (t3 natural join t4); +-- error 1052 +select * from (t3 natural join t4) natural join (t1 join t2 on t1.b=t2.b); +-- this one is OK, the next equivalent one is incorrect (bug in Oracle) +-- error 1052 +select * from (t3 join (t4 natural join t5) on (b < z)) + natural join + (t1 natural join t2); +-- error 1052 +-- BUG#15357: this query should return an ambiguous column error +-- Expected result: the query must return error with duplicate column 'c' +--select * from (t1 natural join t2) +-- natural join +-- (t3 join (t4 natural join t5) on (b < z)); + +-- error 1054 +select t1.b from v1a; +-- error 1054 +select * from v1a join v1b on t1.b = t2.b; + +drop table t1; +drop table t2; +drop table t3; +drop table t4; +drop table t5; +drop table t6; + +drop view v1a; +drop view v1b; +drop view v1c; +drop view v1d; +drop view v2a; +drop view v2b; +drop view v3a; +drop view v3b; +drop view v4; + +# End of tests for WL#2486 - natural/using join diff --git a/mysql-test/t/join_nested.test b/mysql-test/t/join_nested.test index 0592ec3152f..9f23e2d0e2f 100644 --- a/mysql-test/t/join_nested.test +++ b/mysql-test/t/join_nested.test @@ -832,3 +832,71 @@ SELECT v2.x FROM v2 JOIN t2 ON e=b JOIN t3 ON e=c JOIN t4 USING(d); DROP VIEW v1, v2; DROP TABLE t1, t2, t3, t4, t5, t6; + +# +# BUG#13126 -test case from bug report +# +create table t1 (id1 int(11) not null); +insert into t1 values (1),(2); + +create table t2 (id2 int(11) not null); +insert into t2 values (1),(2),(3),(4); + +create table t3 (id3 char(16) not null); +insert into t3 values ('100'); + +create table t4 (id2 int(11) not null, id3 char(16)); + +create table t5 (id1 int(11) not null, key (id1)); +insert into t5 values (1),(2),(1); + +create view v1 as + select t4.id3 from t4 join t2 on t4.id2 = t2.id2; + +select t1.id1 from t1 inner join (t3 left join v1 on t3.id3 = v1.id3); + +drop view v1; +drop table t1, t2, t3, t4, t5; + +create table t0 (a int); +insert into t0 values (0),(1),(2),(3); +create table t1(a int); +insert into t1 select A.a + 10*(B.a) from t0 A, t0 B; + +create table t2 (a int, b int); +insert into t2 values (1,1), (2,2), (3,3); + +create table t3(a int, b int, filler char(200), key(a)); +insert into t3 select a,a,'filler' from t1; +insert into t3 select a,a,'filler' from t1; + +create table t4 like t3; +insert into t4 select * from t3; +insert into t4 select * from t3; + +create table t5 like t4; +insert into t5 select * from t4; +insert into t5 select * from t4; + +create table t6 like t5; +insert into t6 select * from t5; +insert into t6 select * from t5; + +create table t7 like t6; +insert into t7 select * from t6; +insert into t7 select * from t6; + +--replace_column 9 X +explain select * from t4 join + t2 left join (t3 join t5 on t5.a=t3.b) on t3.a=t2.b where t4.a<=>t3.b; + +--replace_column 9 X +explain select * from (t4 join t6 on t6.a=t4.b) right join t3 on t4.a=t3.b + join t2 left join (t5 join t7 on t7.a=t5.b) on t5.a=t2.b where t3.a<=>t2.b; + +--replace_column 9 X +explain select * from t2 left join + (t3 left join (t4 join t6 on t6.a=t4.b) on t4.a=t3.b + join t5 on t5.a=t3.b) on t3.a=t2.b; + +drop table t0, t1, t2, t3, t4, t5, t6, t7; diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 7f3a9932d31..c50c35825fc 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -25,11 +25,18 @@ select ((@id := kill_id) - kill_id) from t1; kill @id; connection con1; ---sleep 1 +--sleep 2 -# this statement should fail ---error 2006,2013 +--disable_query_log +--disable_result_log +# One of the following statements should fail +--error 0,2006,2013 select 1; +--error 0,2006,2013 +select 1; +--enable_query_log +--enable_result_log + --enable_reconnect # this should work, and we should have a new connection_id() select ((@id := kill_id) - kill_id) from t1; diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index cd3a8f0fd92..09d97a42714 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -31,7 +31,6 @@ load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated select * from t1; drop table t1; - # # Bug #12053 LOAD DATA INFILE ignores NO_AUTO_VALUE_ON_ZERO setting # @@ -59,6 +58,15 @@ select * from t1; SET @@SQL_MODE=@OLD_SQL_MODE; drop table t1; +# +# Bug #11203: LOAD DATA does not accept same characters for ESCAPED and +# ENCLOSED +# +create table t1 (a varchar(20), b varchar(20)); +load data infile '../../std_data/loaddata_dq.dat' into table t1 fields terminated by ',' enclosed by '"' escaped by '"' (a,b); +select * from t1; +drop table t1; + # End of 4.1 tests # @@ -104,3 +112,5 @@ select * from t1; # cleanup drop table t1, t2; + +# End of 5.0 tests diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index ff05867b7c1..060f1ea167b 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -352,4 +352,30 @@ INSERT INTO t2 (b) VALUES (1) ON DUPLICATE KEY UPDATE b=3; SELECT b FROM t2; DROP TABLE t1, t2; + +# +# BUG#5390 - problems with merge tables +# Problem #1: INSERT...SELECT +# +#drop table if exists t1, t2, t3; +create table t1(a int); +create table t2(a int); +insert into t1 values (1); +insert into t2 values (2); +create table t3 (a int) engine=merge union=(t1, t2) insert_method=first; +select * from t3; +# +insert t2 select * from t2; +select * from t2; +# +insert t3 select * from t1; +select * from t3; +# +insert t1 select * from t3; +select * from t1; +select * from t2; +select * from t3; +check table t1, t2; +drop table t1, t2, t3; + # End of 4.1 tests diff --git a/mysql-test/t/mix_innodb_myisam_binlog.test b/mysql-test/t/mix_innodb_myisam_binlog.test index 2e804f4c986..658584b625e 100644 --- a/mysql-test/t/mix_innodb_myisam_binlog.test +++ b/mysql-test/t/mix_innodb_myisam_binlog.test @@ -227,7 +227,37 @@ select (@after:=unix_timestamp())*0; # always give repeatable output # the bug, the reap would return immediately after the insert into t2. select (@after-@before) >= 2; -# cleanup drop table t1,t2; +commit; + +# test for BUG#7947 - DO RELEASE_LOCK() not written to binlog on rollback in the middle +# of a transaction + +connection con2; +begin; +create temporary table ti (a int) engine=innodb; +rollback; +insert into ti values(1); +set autocommit=0; +create temporary table t1 (a int) engine=myisam; +commit; +insert t1 values (1); +rollback; +create table t0 (n int); +insert t0 select * from t1; +set autocommit=1; +insert into t0 select GET_LOCK("lock1",null); +set autocommit=0; +create table t2 (n int) engine=innodb; +insert into t2 values (3); +disconnect con2; +connection con3; +select get_lock("lock1",60); +--replace_column 5 # +--replace_result "xid=208" "xid=105" "xid=227" "xid=114" "xid=230" "xid=115" "xid=234" "xid=117" "xid=261" "xid=132" +show binlog events from 98; +do release_lock("lock1"); +drop table t0,t2; + # End of 4.1 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 73afcab5e27..fb90c16bb86 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -477,6 +477,18 @@ explain select distinct t1.a from t1,t2 order by t2.a; drop table t1,t2; # +# Bug#14616 - Freshly imported table returns error 124 when using LIMIT +# +create table t1 ( + c1 varchar(32), + key (c1) +) engine=myisam; +alter table t1 disable keys; +insert into t1 values ('a'), ('b'); +select c1 from t1 order by c1 limit 1; +drop table t1; + +# # Test RTREE index # --error 1235, 1289 @@ -629,6 +641,43 @@ show index from t1; drop table t1; +# WL#2609, CSC#XXXX: MyISAM +set myisam_stats_method=nulls_ignored; +show variables like 'myisam_stats_method'; + +create table t1 ( + a char(3), b char(4), c char(5), d char(6), + key(a,b,c,d) +); +insert into t1 values ('bcd','def1', NULL, 'zz'); +insert into t1 values ('bcd','def2', NULL, 'zz'); +insert into t1 values ('bce','def1', 'yuu', NULL); +insert into t1 values ('bce','def2', NULL, 'quux'); +analyze table t1; +show index from t1; +delete from t1; +analyze table t1; +show index from t1; + +set myisam_stats_method=DEFAULT; +drop table t1; + +# BUG#13814 - key value packed incorrectly for TINYBLOBs + +create table t1( + cip INT NOT NULL, + time TIME NOT NULL, + score INT NOT NULL DEFAULT 0, + bob TINYBLOB +); + +insert into t1 (cip, time) VALUES (1, '00:01'), (2, '00:02'), (3,'00:03'); +insert into t1 (cip, bob, time) VALUES (4, 'a', '00:04'), (5, 'b', '00:05'), + (6, 'c', '00:06'); +select * from t1 where bob is null and cip=1; +create index bug on t1 (bob(22), cip, time); +select * from t1 where bob is null and cip=1; +drop table t1; # End of 4.1 tests # @@ -703,6 +752,7 @@ insert into t1 values (10),(11),(12); select * from t1; check table t1; drop table t1; +disconnect con1; # Same test with dynamic record length create table t1 (a int, b varchar(30) default "hello"); @@ -727,8 +777,10 @@ insert into t1 (a) values (10),(11),(12); select a from t1; check table t1; drop table t1; +disconnect con1; set global concurrent_insert=@save_concurrent_insert; + # BUG#9622 - ANALYZE TABLE and ALTER TABLE .. ENABLE INDEX produce # different statistics on the same table with NULL values. create table t1 (a int, key(a)); diff --git a/mysql-test/t/mysql_client_test.test b/mysql-test/t/mysql_client_test.test index ccf5e0bf66a..66b57dd5fb7 100644 --- a/mysql-test/t/mysql_client_test.test +++ b/mysql-test/t/mysql_client_test.test @@ -6,7 +6,7 @@ # var/log/mysql_client_test.trace --disable_result_log ---exec echo $MYSQL_CLIENT_TEST ---exec $MYSQL_CLIENT_TEST +--exec echo $MYSQL_CLIENT_TEST --getopt-ll-test=25600M +--exec $MYSQL_CLIENT_TEST --getopt-ll-test=25600M # End of 4.1 tests diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 31957e0db0d..e54bf6386c5 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -605,6 +605,7 @@ select * from t2 order by a; drop table t1, t2; drop database db1; + # # Bug #9558 mysqldump --no-data db t1 t2 format still dumps data # @@ -644,7 +645,7 @@ select '------ Testing with illegal table names ------' as test_sequence ; --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\t1" 2>&1 - + --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\\\t1" 2>&1 @@ -658,19 +659,19 @@ select '------ Testing with illegal table names ------' as test_sequence ; --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t/1" 2>&1 --error 6 ---exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "T_1" 2>&1 --error 6 ---exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T%1" +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "T%1" 2>&1 --error 6 ---exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T'1" +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "T'1" 2>&1 --error 6 ---exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "T_1" 2>&1 --error 6 ---exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_" +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "T_" 2>&1 --disable_query_log select '------ Testing with illegal database names ------' as test_sequence ; @@ -685,6 +686,7 @@ drop table t1, t2, t3; drop database mysqldump_test_db; use test; + # # Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly # @@ -697,6 +699,18 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir --exec $MYSQL_DUMP --skip-comments --xml --no-create-info test drop table t1, t2; +# +# BUG #12123 +# +create table t1 (a text character set utf8, b text character set latin1); +insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); +select * from t1; +--exec $MYSQL_DUMP --tab=$MYSQL_TEST_DIR/var/tmp/ test +--exec $MYSQL test < $MYSQL_TEST_DIR/var/tmp/t1.sql +--exec $MYSQL_IMPORT test $MYSQL_TEST_DIR/var/tmp/t1.txt +select * from t1; + +drop table t1; # End of 4.1 tests # @@ -870,6 +884,7 @@ DROP FUNCTION IF EXISTS bug9056_func1; DROP FUNCTION IF EXISTS bug9056_func2; DROP PROCEDURE IF EXISTS bug9056_proc1; DROP PROCEDURE IF EXISTS bug9056_proc2; +DROP PROCEDURE IF EXISTS `a'b`; --enable_warnings CREATE TABLE t1 (id int); @@ -905,6 +920,7 @@ DROP FUNCTION bug9056_func1; DROP FUNCTION bug9056_func2; DROP PROCEDURE bug9056_proc1; DROP PROCEDURE bug9056_proc2; +DROP PROCEDURE `a'b`; drop table t1; # @@ -985,3 +1001,38 @@ drop view v2; drop view v0; drop view v1; drop table t1; + +# +# BUG#14554 - mysqldump does not separate words "ROW" and "BEGIN" +# for tables with trigger created in the IGNORE_SPACE sql mode. +# + +SET @old_sql_mode = @@SQL_MODE; +SET SQL_MODE = IGNORE_SPACE; + +CREATE TABLE t1 (a INT); +DELIMITER |; +CREATE TRIGGER tr1 BEFORE INSERT ON t1 + FOR EACH ROW + BEGIN + SET new.a = 0; + END| +DELIMITER ;| + +SET SQL_MODE = @old_sql_mode; + +--exec $MYSQL_DUMP --skip-comments --databases test + +DROP TRIGGER tr1; +DROP TABLE t1; + +# +# Bug #13318: Bad result with empty field and --hex-blob +# +create table t1 (a binary(1), b blob); +insert into t1 values ('',''); +--exec $MYSQL_DUMP --skip-comments --skip-extended-insert --hex-blob test t1 +--exec $MYSQL_DUMP --skip-comments --hex-blob test t1 +drop table t1; + +# End of 4.1 tests diff --git a/mysql-test/t/mysqlshow.test b/mysql-test/t/mysqlshow.test index 1e2e97a4e07..78c4ae2b531 100644 --- a/mysql-test/t/mysqlshow.test +++ b/mysql-test/t/mysqlshow.test @@ -2,7 +2,7 @@ -- source include/not_embedded.inc --disable_warnings -DROP TABLE IF EXISTS t1,t2; +DROP TABLE IF EXISTS t1,t2,test1,test2; --enable_warnings # diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 11fbb023963..440a7787985 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -358,11 +358,11 @@ select 3 from t1 ; # Missing delimiter # The comment will be "sucked into" the sleep command since # delimiter is missing until after "show status" ---system echo "sleep 4" > var/log/mysqltest.sql ---system echo "# A comment" >> var/log/mysqltest.sql ---system echo "show status;" >> var/log/mysqltest.sql +--system echo "sleep 4" > var/tmp/mysqltest.sql +--system echo "# A comment" >> var/tmp/mysqltest.sql +--system echo "show status;" >> var/tmp/mysqltest.sql --error 1 ---exec $MYSQL_TEST < var/log/mysqltest.sql 2>&1 +--exec $MYSQL_TEST < var/tmp/mysqltest.sql 2>&1 # # Extra delimiter @@ -806,6 +806,66 @@ select "a" as col1, "c" as col2; --error 1 --exec echo "save_master_pos; sync_with_master a;" | $MYSQL_TEST 2>&1 +# ---------------------------------------------------------------------------- +# Test connect +# ---------------------------------------------------------------------------- + +--error 1 +--exec echo "connect;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "connect ();" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "connect (con2);" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "connect (con2,);" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "connect (con2,localhost);" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "connect (con2, localhost, root);" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "connect (con2, localhost, root,);" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "connect (con2,localhost,root,,illegal_db);" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "connect (con1,localhost,root,,,illegal_port,);" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "connect (con1,localhost,root,,,,,SMTP POP);" | $MYSQL_TEST 2>&1 + +# Repeat connect/disconnect +--exec echo "let \$i=100;" > var/tmp/con.sql +--exec echo "while (\$i)" >> var/tmp/con.sql +--exec echo "{" >> var/tmp/con.sql +--exec echo " connect (test_con1,localhost,root,,); " >> var/tmp/con.sql +--exec echo " disconnect test_con1; " >> var/tmp/con.sql +--exec echo " dec \$i; " >> var/tmp/con.sql +--exec echo "}" >> var/tmp/con.sql +--exec echo "source var/tmp/con.sql;" | $MYSQL_TEST 2>&1 + +# Repeat connect/disconnect, exceed max number of connections +--exec echo "let \$i=200;" > var/tmp/con.sql +--exec echo "while (\$i)" >> var/tmp/con.sql +--exec echo "{" >> var/tmp/con.sql +--exec echo " connect (test_con1,localhost,root,,); " >> var/tmp/con.sql +--exec echo " disconnect test_con1; " >> var/tmp/con.sql +--exec echo " dec \$i; " >> var/tmp/con.sql +--exec echo "}" >> var/tmp/con.sql +--error 1 +--exec echo "source var/tmp/con.sql;" | $MYSQL_TEST 2>&1 + +# Select disconnected connection +--exec echo "connect (test_con1,localhost,root,,);" > var/tmp/con.sql +--exec echo "disconnect test_con1; " >> var/tmp/con.sql +--exec echo "connection test_con1;" >> var/tmp/con.sql +--error 1 +--exec echo "source var/tmp/con.sql;" | $MYSQL_TEST 2>&1 + +# Connection name already used +--exec echo "connect (test_con1,localhost,root,,);" > var/tmp/con.sql +--exec echo "connect (test_con1,localhost,root,,);" >> var/tmp/con.sql +--error 1 +--exec echo "source var/tmp/con.sql;" | $MYSQL_TEST 2>&1 + + # ---------------------------------------------------------------------------- # Test mysqltest arguments @@ -885,3 +945,53 @@ select "this will not be executed"; --enable_parsing select "this will be executed"; --enable_query_log + + +# +# Bug #11731 mysqltest in multi-statement queries ignores errors in +# non-1st queries +# + +# Failing multi statement query +# PS does not support multi statement +--exec echo "--disable_ps_protocol" > var/tmp/bug11731.sql +--exec echo "delimiter ||||;" >> var/tmp/bug11731.sql +--exec echo "create table t1 (a int primary key);" >> var/tmp/bug11731.sql +--exec echo "insert into t1 values (1);" >> var/tmp/bug11731.sql +--exec echo "select 'select-me';" >> var/tmp/bug11731.sql +--exec echo "insertz 'error query'||||" >> var/tmp/bug11731.sql +--exec echo "delimiter ;||||" >> var/tmp/bug11731.sql + +--error 1 +--exec $MYSQL_TEST -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql 2>&1 +drop table t1; + +--error 1 +--exec $MYSQL_TEST --record -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql -R $MYSQL_TEST_DIR/var/tmp/bug11731.out +# The .out file should be empty +--error 1 +--exec test -s $MYSQL_TEST_DIR/var/tmp/bug11731.out +drop table t1; + + +# Using expected error +# PS does not support multi statement +--exec echo "--disable_ps_protocol" > var/tmp/bug11731.sql +--exec echo "delimiter ||||;" >> var/tmp/bug11731.sql +--exec echo "--error 1064" >> var/tmp/bug11731.sql +--exec echo "create table t1 (a int primary key);" >> var/tmp/bug11731.sql +--exec echo "insert into t1 values (1);" >> var/tmp/bug11731.sql +--exec echo "select 'select-me';" >> var/tmp/bug11731.sql +--exec echo "insertz "error query"||||" >> var/tmp/bug11731.sql +--exec echo "delimiter ;||||" >> var/tmp/bug11731.sql + +# These two should work since the error is expected +--exec $MYSQL_TEST -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql 2>&1 +drop table t1; + +--exec $MYSQL_TEST --record -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql -R $MYSQL_TEST_DIR/var/tmp/bug11731.out +--exec cat $MYSQL_TEST_DIR/var/tmp/bug11731.out +drop table t1; + + + diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index 357f658a296..0a0211c8c83 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -142,6 +142,7 @@ INSERT INTO t1 VALUES (1,2,0),(18,19,4),(20,21,0); select c from t1 order by c; drop table t1; +--disable_ps_protocol create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) ) engine=ndb; insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three'); @@ -151,10 +152,13 @@ select * from t1 where b = 'two'; connection server1; alter table t1 drop index c; connection server2; +# This should fail since index information is not automatically refreshed +--error 1015 select * from t1 where b = 'two'; select * from t1 where b = 'two'; connection server1; drop table t1; +--enable_ps_protocol #--disable_warnings #DROP TABLE IF EXISTS t2; diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test index 1c78a4b8744..12aca73d82b 100644 --- a/mysql-test/t/ndb_basic.test +++ b/mysql-test/t/ndb_basic.test @@ -606,6 +606,14 @@ select * from t1 order by counter; drop table t1; +# +# BUG#14514 Creating table with packed key fails silently +# + +CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb; +select * from t1; +drop table t1; + # End of 4.1 tests # @@ -615,3 +623,14 @@ create table atablewithareallylongandirritatingname (a int); insert into atablewithareallylongandirritatingname values (2); select * from atablewithareallylongandirritatingname; drop table atablewithareallylongandirritatingname; + +# +# Bug#15682 +# +create table t1 (f1 varchar(50), f2 text,f3 int, primary key(f1)) engine=NDB; +insert into t1 (f1,f2,f3)VALUES("111111","aaaaaa",1); +insert into t1 (f1,f2,f3)VALUES("222222","bbbbbb",2); +select * from t1 order by f1; +select * from t1 order by f2; +select * from t1 order by f3; +drop table t1; diff --git a/mysql-test/t/ndb_charset.test b/mysql-test/t/ndb_charset.test index fb43e1831f3..5941e5750db 100644 --- a/mysql-test/t/ndb_charset.test +++ b/mysql-test/t/ndb_charset.test @@ -237,13 +237,18 @@ drop table t1; #select a,b,length(a),length(b) from t1 where a='c' and b='c'; #drop table t1; -# bug +# bug#14007 create table t1 ( a char(10) primary key -) engine=ndb; -insert into t1 values ('jonas % '); -replace into t1 values ('jonas % '); -replace into t1 values ('jonas % '); +) engine=ndbcluster default charset=latin1; + +insert into t1 values ('aaabb'); +select * from t1; +replace into t1 set a = 'AAABB'; +select * from t1; +replace into t1 set a = 'aAaBb'; +select * from t1; +replace into t1 set a = 'aaabb'; select * from t1; drop table t1; diff --git a/mysql-test/t/ndb_gis.test b/mysql-test/t/ndb_gis.test new file mode 100644 index 00000000000..e14f462c32d --- /dev/null +++ b/mysql-test/t/ndb_gis.test @@ -0,0 +1,5 @@ +--source include/have_ndb.inc +SET storage_engine=ndbcluster; +--source include/gis_generic.inc +set engine_condition_pushdown = on; +--source include/gis_generic.inc diff --git a/mysql-test/t/ndb_multi.test b/mysql-test/t/ndb_multi.test index 760150c6f6a..1183f2b283f 100644 --- a/mysql-test/t/ndb_multi.test +++ b/mysql-test/t/ndb_multi.test @@ -40,6 +40,7 @@ connection server1; # Currently a retry is required remotely --error 1296 select * from t1; +flush table t1; select * from t1; # Connect to server2 and use the tables from there diff --git a/mysql-test/t/ndb_read_multi_range.test b/mysql-test/t/ndb_read_multi_range.test index 9d1f918fef0..b1bf7fe4258 100644 --- a/mysql-test/t/ndb_read_multi_range.test +++ b/mysql-test/t/ndb_read_multi_range.test @@ -2,7 +2,7 @@ -- source include/not_embedded.inc --disable_warnings -DROP TABLE IF EXISTS t1, r1; +DROP TABLE IF EXISTS t1, t2, r1; --enable_warnings # diff --git a/mysql-test/t/not_embedded_server-master.opt b/mysql-test/t/not_embedded_server-master.opt new file mode 100644 index 00000000000..35fcc5f30c6 --- /dev/null +++ b/mysql-test/t/not_embedded_server-master.opt @@ -0,0 +1 @@ +--loose-to-force-a-restart diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test index e04c77ddf45..359b8b69a4d 100644 --- a/mysql-test/t/openssl_1.test +++ b/mysql-test/t/openssl_1.test @@ -1,6 +1,6 @@ # We test openssl. Result set is optimized to be compiled with --with-openssl. # Use mysql-test-run with --with-openssl option. --- source include/have_openssl_1.inc +-- source include/have_openssl.inc --disable_warnings drop table if exists t1; @@ -13,27 +13,36 @@ grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com"; grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com"; flush privileges; -connect (con1,localhost,ssl_user1,,); -connect (con2,localhost,ssl_user2,,); -connect (con3,localhost,ssl_user3,,); -connect (con4,localhost,ssl_user4,,); + +connect (con1,localhost,ssl_user1,,,,,SSL); +connect (con2,localhost,ssl_user2,,,,,SSL); +connect (con3,localhost,ssl_user3,,,,,SSL); +connect (con4,localhost,ssl_user4,,,,,SSL); connection con1; +# Check ssl turned on +SHOW STATUS LIKE 'Ssl_cipher'; select * from t1; --error 1142 delete from t1; connection con2; +# Check ssl turned on +SHOW STATUS LIKE 'Ssl_cipher'; select * from t1; --error 1142 delete from t1; connection con3; +# Check ssl turned on +SHOW STATUS LIKE 'Ssl_cipher'; select * from t1; --error 1142 delete from t1; connection con4; +# Check ssl turned on +SHOW STATUS LIKE 'Ssl_cipher'; select * from t1; --error 1142 delete from t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 94ee2b1ca39..22d0abf645e 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -842,4 +842,44 @@ set @@tx_isolation=default; execute stmt; deallocate prepare stmt; +# +# Bug#14410 "Crash in Enum or Set type in CREATE TABLE and PS/SP" +# +# Part I. Make sure the typelib for ENUM is created in the statement memory +# root. +prepare stmt from "create temporary table t1 (letter enum('','a','b','c') +not null)"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +# Part II. Make sure that when the default value is converted to UTF-8, +# the new item is # created in the statement memory root. +set names latin1; +prepare stmt from "create table t1 (a enum('test') default 'test') + character set utf8"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +# Cleanup +set names default; +deallocate prepare stmt; + # End of 4.1 tests + +# +# Bug #14956: ROW_COUNT() returns incorrect result after EXECUTE of prepared +# statement +# +create table t1 (id int); +prepare ins_call from "insert into t1 (id) values (1)"; +execute ins_call; +select row_count(); +drop table t1; + +# End of 5.0 tests diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 646151a5aae..a9f171ff5b5 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -743,6 +743,19 @@ show status like "Qcache_hits"; drop table t1; # +# BUG#14652: Queries with leading '(' characters. +# +create table t1 (a int); +flush status; +(select a from t1) union (select a from t1); +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +(select a from t1) union (select a from t1); +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +drop table t1; # SP cursors and selects with query cache (BUG#9715) # create table t1 (a int); diff --git a/mysql-test/t/read_only.test b/mysql-test/t/read_only.test new file mode 100644 index 00000000000..0861951a6a1 --- /dev/null +++ b/mysql-test/t/read_only.test @@ -0,0 +1,103 @@ +# Test of the READ_ONLY global variable: +# check that it blocks updates unless they are only on temporary tables. + +--disable_warnings +DROP TABLE IF EXISTS t1,t2,t3; +--enable_warnings + +# READ_ONLY does nothing to SUPER users +# so we use a non-SUPER one: + +grant CREATE, SELECT, DROP on *.* to test@localhost; + +connect (con1,localhost,test,,test); + +connection default; + +set global read_only=0; + +connection con1; + +create table t1 (a int); + +insert into t1 values(1); + +create table t2 select * from t1; + +connection default; + +set global read_only=1; + +# We check that SUPER can: + +create table t3 (a int); +drop table t3; + +connection con1; + +select @@global.read_only; + +--error 1290 +create table t3 (a int); + +--error 1290 +insert into t1 values(1); + +# if a statement, after parse stage, looks like it will update a +# non-temp table, it will be rejected, even if at execution it would +# have turned out that 0 rows would be updated +--error 1290 +update t1 set a=1 where 1=0; + +# multi-update is special (see sql_parse.cc) so we test it +--error 1290 +update t1,t2 set t1.a=t2.a+1 where t1.a=t2.a; + +# check multi-delete to be sure +--error 1290 +delete t1,t2 from t1,t2 where t1.a=t2.a; + +# With temp tables updates should be accepted: + +create temporary table t3 (a int); + +create temporary table t4 (a int) select * from t3; + +insert into t3 values(1); + +insert into t4 select * from t3; + +# a non-temp table updated: +--error 1290 +update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; + +# no non-temp table updated (just swapped): +update t1,t3 set t3.a=t1.a+1 where t1.a=t3.a; + +update t4,t3 set t4.a=t3.a+1 where t4.a=t3.a; + +--error 1290 +delete t1 from t1,t3 where t1.a=t3.a; + +delete t3 from t1,t3 where t1.a=t3.a; + +delete t4 from t3,t4 where t4.a=t3.a; + +# and even homonymous ones + +create temporary table t1 (a int); + +insert into t1 values(1); + +update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; + +delete t1 from t1,t3 where t1.a=t3.a; + +drop table t1; + +--error 1290 +insert into t1 values(1); + +connection default; +drop table t1,t2; +drop user test@localhost; diff --git a/mysql-test/t/rpl000001.test b/mysql-test/t/rpl000001.test index 3d03823d474..45d621b730f 100644 --- a/mysql-test/t/rpl000001.test +++ b/mysql-test/t/rpl000001.test @@ -92,7 +92,7 @@ kill @id; # We don't drop t3 as this is a temporary table drop table t2; connection master; ---error 1053 +--error 1053,2013 reap; connection slave; # The SQL slave thread should now have stopped because the query was killed on diff --git a/mysql-test/t/rpl_deadlock.test b/mysql-test/t/rpl_deadlock.test index d2a8fc0c844..c74ed989ece 100644 --- a/mysql-test/t/rpl_deadlock.test +++ b/mysql-test/t/rpl_deadlock.test @@ -58,7 +58,7 @@ while ($1) enable_query_log; select * from t1 for update; start slave; ---sleep 3 # hope that slave is blocked now +--real_sleep 3 # hope that slave is blocked now insert into t2 values(22); # provoke deadlock, slave should be victim commit; sync_with_master; @@ -76,7 +76,7 @@ change master to master_log_pos=532; # the BEGIN log event begin; select * from t2 for update; # hold lock start slave; ---sleep 10 # slave should have blocked, and be retrying +--real_sleep 10 # slave should have blocked, and be retrying commit; sync_with_master; select * from t1; # check that slave succeeded finally @@ -97,12 +97,12 @@ change master to master_log_pos=532; begin; select * from t2 for update; start slave; ---sleep 10 +--real_sleep 10 commit; sync_with_master; select * from t1; select * from t2; ---replace_column 1 # 8 # 9 # 23 # 33 # +--replace_column 1 # 8 # 9 # 11 # 23 # 33 # --replace_result $MASTER_MYPORT MASTER_MYPORT show slave status; diff --git a/mysql-test/t/rpl_drop_db.test b/mysql-test/t/rpl_drop_db.test index 61354198c83..98afc6e3d02 100644 --- a/mysql-test/t/rpl_drop_db.test +++ b/mysql-test/t/rpl_drop_db.test @@ -13,6 +13,7 @@ insert into mysqltest1.t1 values (1); select * from mysqltest1.t1 into outfile 'mysqltest1/f1.txt'; create table mysqltest1.t2 (n int); create table mysqltest1.t3 (n int); +--replace_result \\ / --error 1010 drop database mysqltest1; use mysqltest1; @@ -29,6 +30,7 @@ while ($1) } --enable_query_log +--replace_result \\ / --error 1010 drop database mysqltest1; use mysqltest1; diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test index cb4137c49e0..339d966dbb3 100644 --- a/mysql-test/t/rpl_error_ignored_table.test +++ b/mysql-test/t/rpl_error_ignored_table.test @@ -45,7 +45,7 @@ select (@id := id) - id from t3; kill @id; drop table t2,t3; connection master; ---error 0,1053 +--error 0,1053,2013 reap; connection master1; --replace_column 2 # 5 # diff --git a/mysql-test/t/rpl_openssl.test b/mysql-test/t/rpl_openssl.test index 3c151721d8e..e15eb9b179a 100644 --- a/mysql-test/t/rpl_openssl.test +++ b/mysql-test/t/rpl_openssl.test @@ -1,4 +1,4 @@ -source include/have_openssl_1.inc; +source include/have_openssl.inc; source include/master-slave.inc; # We don't test all types of ssl auth params here since it's a bit hard diff --git a/mysql-test/t/rpl_relayrotate.test b/mysql-test/t/rpl_relayrotate.test index b66cf7a6e0d..04f03367e20 100644 --- a/mysql-test/t/rpl_relayrotate.test +++ b/mysql-test/t/rpl_relayrotate.test @@ -52,13 +52,9 @@ start slave; # which proves that the transaction restarted at # the right place. # We must wait for the transaction to commit before -# reading, MASTER_POS_WAIT() will do it for sure -# (the only statement with position>=3000 is COMMIT). -select master_pos_wait('master-bin.001',3000)>=0; +# reading: +sync_with_master; select max(a) from t1; ---replace_column 1 # 8 # 9 # 23 # 33 # ---replace_result $MASTER_MYPORT MASTER_MYPORT -show slave status; connection master; # The following DROP is a very important cleaning task: diff --git a/mysql-test/t/rpl_sp-slave.opt b/mysql-test/t/rpl_sp-slave.opt index 709a224fd92..611ee1f33be 100644 --- a/mysql-test/t/rpl_sp-slave.opt +++ b/mysql-test/t/rpl_sp-slave.opt @@ -1 +1 @@ ---log_bin_trust_routine_creators=0 +--log_bin_trust_routine_creators=0 --slave-skip-errors=1062 diff --git a/mysql-test/t/rpl_sp.test b/mysql-test/t/rpl_sp.test index e62a6c73c0a..8fa330584e2 100644 --- a/mysql-test/t/rpl_sp.test +++ b/mysql-test/t/rpl_sp.test @@ -1,10 +1,18 @@ # Test of replication of stored procedures (WL#2146 for MySQL 5.0) +# Modified by WL#2971. + +# Note that in the .opt files we still use the old variable name +# log-bin-trust-routine-creators so that this test checks that it's +# still accepted (this test also checks that the new name is +# accepted). The old name could be removed in 5.1 or 6.0. source include/master-slave.inc; -# First let's test replication of current_user() (that's a related thing) # we need a db != test, where we don't have automatic grants -create database if not exists mysqltest1; +--disable_warnings +drop database if exists mysqltest1; +--enable_warnings +create database mysqltest1; use mysqltest1; create table t1 (a varchar(100)); sync_slave_with_master; @@ -16,30 +24,15 @@ use mysqltest1; # (same definer, same properties...) connection master; -# cleanup ---disable_warnings -drop procedure if exists foo; -drop procedure if exists foo2; -drop procedure if exists foo3; -drop procedure if exists foo4; -drop procedure if exists bar; -drop function if exists fn1; ---enable_warnings delimiter |; ---error 1418 # not deterministic -create procedure foo() -begin - declare b int; - set b = 8; - insert into t1 values (b); - insert into t1 values (unix_timestamp()); -end| ---replace_column 2 # 5 # -show binlog events from 98| # check that not there +# Stored procedures don't have the limitations that functions have +# regarding binlogging: it's ok to create a procedure as not +# deterministic and updating data, while it's not ok to create such a +# function. We test this. -create procedure foo() deterministic +create procedure foo() begin declare b int; set b = 8; @@ -54,38 +47,29 @@ delimiter ;| --replace_column 13 # 14 # select * from mysql.proc where name='foo' and db='mysqltest1'; sync_slave_with_master; +# You will notice in the result that the definer does not match what +# it is on master, it is a known bug on which Alik is working --replace_result localhost.localdomain localhost 127.0.0.1 localhost --replace_column 13 # 14 # select * from mysql.proc where name='foo' and db='mysqltest1'; -# Now when we call it, does the CALL() get into binlog, -# or the substatements? connection master; # see if timestamp used in SP on slave is same as on master set timestamp=1000000000; call foo(); ---replace_column 2 # 5 # -show binlog events from 308; select * from t1; sync_slave_with_master; select * from t1; -# Now a SP which is supposed to not update tables (CALL should not be -# binlogged) as it's "read sql data", so should not give error even if -# non-deterministic. +# Now a SP which is not updating tables connection master; delete from t1; create procedure foo2() - not deterministic - reads sql data select * from mysqltest1.t1; call foo2(); -# verify CALL is not in binlog ---replace_column 2 # 5 # -show binlog events from 518; ---error 1418 +# check that this is allowed (it's not for functions): alter procedure foo2 contains sql; # SP with definer's right @@ -103,18 +87,18 @@ grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1; -connect (con1,127.0.0.1,zedjzlcsjhd,,mysqltest1,$MASTER_MYPORT,); -connection con1; - ---error 1419 # only full-global-privs user can create a routine -create procedure foo4() - deterministic - insert into t1 values (10); +# ToDo: BUG#14931: There is a race between the last grant binlogging, and +# the binlogging in the new connection made below, causing sporadic test +# failures due to switched statement order in binlog. To fix this we do +# SELECT 1 in the first connection before starting the second, ensuring +# that binlogging is done in the expected order. +# Please remove this SELECT 1 when BUG#14931 is fixed. +SELECT 1; -connection master; -set global log_bin_trust_routine_creators=1; +connect (con1,127.0.0.1,zedjzlcsjhd,,mysqltest1,$MASTER_MYPORT,); connection con1; +# this routine will fail in the second INSERT because of privileges delimiter |; create procedure foo4() deterministic @@ -128,29 +112,22 @@ delimiter ;| # I add ,0 so that it does not print the error in the test output, # because this error is hostname-dependent --error 1142,0 -call foo4(); # invoker has no INSERT grant on table => failure -show warnings; +call foo4(); # invoker has no INSERT grant on table t1 => failure connection master; call foo3(); # success (definer == root) show warnings; ---replace_result localhost.localdomain localhost 127.0.0.1 localhost --error 1142,0 call foo4(); # definer's rights => failure -show warnings; # we test replication of ALTER PROCEDURE alter procedure foo4 sql security invoker; call foo4(); # invoker's rights => success show warnings; -# Check that only successful CALLs are in binlog ---replace_column 2 # 5 # -show binlog events from 990; - -# Note that half-failed CALLs are not in binlog, which is a known -# bug. If we compare t2 on master and slave we see they differ: +# Note that half-failed procedure calls are ok with binlogging; +# if we compare t2 on master and slave we see they are identical: select * from t1; select * from t2; @@ -158,6 +135,30 @@ sync_slave_with_master; select * from t1; select * from t2; +# Let's check another failing-in-the-middle procedure +connection master; +delete from t2; +alter table t2 add unique (a); + +drop procedure foo4; +delimiter |; +create procedure foo4() + deterministic + begin + insert into t2 values(20),(20); + end| + +delimiter ;| + +--error 1062 +call foo4(); +show warnings; + +select * from t2; +sync_slave_with_master; +# check that this failed-in-the-middle replicated right: +select * from t2; + # Test of DROP PROCEDURE --replace_result localhost.localdomain localhost 127.0.0.1 localhost @@ -177,6 +178,14 @@ drop procedure foo2; drop procedure foo3; delimiter |; +# check that needs "deterministic" +--error 1418 +create function fn1(x int) + returns int +begin + insert into t1 values (x); + return x+2; +end| create function fn1(x int) returns int deterministic @@ -202,15 +211,69 @@ drop function fn1; create function fn1() returns int - deterministic + no sql begin return unix_timestamp(); end| + delimiter ;| +# check that needs "deterministic" +--error 1418 +alter function fn1 contains sql; + delete from t1; set timestamp=1000000000; insert into t1 values(fn1()); +connection con1; + +delimiter |; +--error 1419 # only full-global-privs user can create a function +create function fn2() + returns int + no sql +begin + return unix_timestamp(); +end| +delimiter ;| +connection master; +# test old variable name: +set global log_bin_trust_routine_creators=1; +# now use new name: +set global log_bin_trust_function_creators=0; +set global log_bin_trust_function_creators=1; +# slave needs it too otherwise will not execute what master allowed: +connection slave; +set global log_bin_trust_function_creators=1; + +connection con1; + +delimiter |; +create function fn2() + returns int + no sql +begin + return unix_timestamp(); +end| +delimiter ;| + +connection master; + +# Now a function which is supposed to not update tables +# as it's "reads sql data", so should not give error even if +# non-deterministic. + +delimiter |; +create function fn3() + returns int + not deterministic + reads sql data +begin + return 0; +end| +delimiter ;| + +select fn3(); --replace_result localhost.localdomain localhost 127.0.0.1 localhost --replace_column 13 # 14 # select * from mysql.proc where db='mysqltest1'; @@ -223,18 +286,43 @@ select * from t1; --replace_column 13 # 14 # select * from mysql.proc where db='mysqltest1'; -# And now triggers +# Let's check a failing-in-the-middle function +connection master; +delete from t2; +alter table t2 add unique (a); + +drop function fn1; + +delimiter |; +create function fn1() + returns int +begin + insert into t2 values(20),(20); + return 10; +end| + +delimiter ;| + +# Because of BUG#14769 the following statement requires that we start +# slave with --slave-skip-errors=1062. When that bug is fixed, that +# option can be removed. + +--error 1062 +select fn1(); + +select * from t2; +sync_slave_with_master; + +# check that this failed-in-the-middle replicated right: +select * from t2; + +# ********************** PART 3 : TRIGGERS *************** connection con1; --error 1227 create trigger trg before insert on t1 for each row set new.a= 10; connection master; -# fn1() above uses timestamps, so in !ps-protocol, the timezone will be -# binlogged, but in --ps-protocol it will not be (BUG#9359) so -# the binlog offsets get shifted which spoils SHOW BINLOG EVENTS. -# To be immune, we take a new binlog. -flush logs; delete from t1; # TODO: when triggers can contain an update, test that this update # does not go into binlog. @@ -253,7 +341,7 @@ drop trigger trg; insert into t1 values (1); select * from t1; --replace_column 2 # 5 # -show binlog events in 'master-bin.000002' from 98; +show binlog events in 'master-bin.000001' from 98; sync_slave_with_master; select * from t1; @@ -280,4 +368,40 @@ connection master; drop function fn1; drop database mysqltest1; drop user "zedjzlcsjhd"@127.0.0.1; +use test; +sync_slave_with_master; +use test; + +# +# Bug#14077 "Failure to replicate a stored function with a cursor": +# verify that stored routines with cursors work on slave. +# +connection master; +--disable_warnings +drop function if exists f1; +--enable_warnings +delimiter |; +create function f1() returns int reads sql data +begin + declare var integer; + declare c cursor for select a from v1; + open c; + fetch c into var; + close c; + return var; +end| +delimiter ;| +create view v1 as select 1 as a; +create table t1 (a int); +insert into t1 (a) values (f1()); +select * from t1; +drop view v1; +drop function f1; sync_slave_with_master; +connection slave; +select * from t1; + +# cleanup +connection master; +drop table t1; +reset master; diff --git a/mysql-test/t/rpl_trigger.test b/mysql-test/t/rpl_trigger.test index 715222f0314..fa6054372c7 100644 --- a/mysql-test/t/rpl_trigger.test +++ b/mysql-test/t/rpl_trigger.test @@ -87,12 +87,35 @@ insert into t1 set a = now(); select a=b && a=c from t1; let $time=`select a from t1`; +# Check that definer attribute is replicated properly: +# - dump definers on the master; +# - wait for the slave to synchronize with the master; +# - dump definers on the slave; + +SELECT routine_name, definer +FROM information_schema.routines; + +SELECT trigger_name, definer +FROM information_schema.triggers; + save_master_pos; connection slave; sync_with_master; --disable_query_log select "--- On slave --" as ""; --enable_query_log + +# XXX: Definers of stored procedures and functions are not replicated. WL#2897 +# (Complete definer support in the stored routines) addresses this issue. So, +# the result file is expected to be changed after implementation of this WL +# item. + +SELECT routine_name, definer +FROM information_schema.routines; + +SELECT trigger_name, definer +FROM information_schema.triggers; + select a=b && a=c from t1; --disable_query_log eval select a='$time' as 'test' from t1; @@ -111,6 +134,35 @@ drop function bug12480; drop table t1; # +# #14614: Replication of tables with trigger generates error message if databases is changed +# Note. The error message is emitted by _myfree() using fprintf() to the stderr +# and because of that does not fall into the .result file. +# + +create table t1 (i int); +create table t2 (i int); + +delimiter |; +create trigger tr1 before insert on t1 for each row +begin + insert into t2 values (1); +end| +delimiter ;| + +create database other; +use other; +insert into test.t1 values (1); + +save_master_pos; +connection slave; +sync_with_master; + +connection master; +use test; +drop table t1,t2; +drop database other; + +# # End of test # save_master_pos; diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index 5bc7a040b1b..e0ecf981fea 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -30,7 +30,7 @@ wait_for_slave_to_stop; # here table should be still not deleted select * from t1; --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 1 # 9 # 23 # 33 # +--replace_column 1 # 9 # 11 # 23 # 33 # show slave status; # this should fail right after start @@ -40,7 +40,7 @@ select * from t1; sleep 2; wait_for_slave_to_stop; --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 1 # 9 # 23 # 33 # +--replace_column 1 # 9 # 11 # 23 # 33 # show slave status; # try replicate all until second insert to t2; @@ -49,7 +49,7 @@ sleep 2; wait_for_slave_to_stop; select * from t2; --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 1 # 9 # 23 # 33 # +--replace_column 1 # 9 # 11 # 23 # 33 # show slave status; # clean up diff --git a/mysql-test/t/schema.test b/mysql-test/t/schema.test index d9bd607b2db..a08d9b38935 100644 --- a/mysql-test/t/schema.test +++ b/mysql-test/t/schema.test @@ -1,6 +1,12 @@ # # Just a couple of tests to make sure that schema works. # +# Drop mysqltest1 database, as it can left from the previous tests. +# + +--disable_warnings +drop database if exists mysqltest1; +--enable_warnings create schema foo; show create schema foo; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index a3d83c531d2..a85b82a7767 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2244,6 +2244,26 @@ SELECT t2.a, t2.b, IF(t1.b IS NULL,'',e) AS c, COUNT(*) AS d FROM t2,t1 WHERE t2.a = t1.a AND t2.b = t1.b GROUP BY a, b, c; DROP TABLE IF EXISTS t1, t2; +# +# Bug #13855 select distinct with group by caused server crash +# +create table t1 (f1 int primary key, f2 int); +create table t2 (f3 int, f4 int, primary key(f3,f4)); +insert into t1 values (1,1); +insert into t2 values (1,1),(1,2); +select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1; +drop table t1,t2; + +# +# Bug #14482 Server crash when subselecting from the same table +# +create table t1 (f1 int,f2 int); +insert into t1 values(1,1); +create table t2 (f3 int, f4 int, primary key(f3,f4)); +insert into t2 values(1,1); +select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2)); +drop table t1,t2; + # End of 4.1 tests # @@ -2702,3 +2722,96 @@ select * from t1 join t2 left join t3 on (t1.a=t3.c); select * from t1 join t2 right join t3 on (t1.a=t3.c); select * from t1 join t2 straight_join t3 on (t1.a=t3.c); drop table t1, t2 ,t3; + +# +# Bug #14093 Query takes a lot of time when date format is not valid +# fix optimizes execution. so here we just check that returned set is +# correct. +create table t1(f1 int, f2 date); +insert into t1 values(1,'2005-01-01'),(2,'2005-09-01'),(3,'2005-09-30'), + (4,'2005-10-01'),(5,'2005-12-30'); +# should return all records +select * from t1 where f2 >= 0; +select * from t1 where f2 >= '0000-00-00'; +# should return 4,5 +select * from t1 where f2 >= '2005-09-31'; +select * from t1 where f2 >= '2005-09-3a'; +# should return 1,2,3 +select * from t1 where f2 <= '2005-09-31'; +select * from t1 where f2 <= '2005-09-3a'; +drop table t1; + +# +# Bug ##14662 ORDER BY on column of a view, with an alias of the same +# column causes ambiguous +# + +create table t1 (f1 int, f2 int); +insert into t1 values (1, 30), (2, 20), (3, 10); +create algorithm=merge view v1 as select f1, f2 from t1; +create algorithm=merge view v2 (f2, f1) as select f1, f2 from t1; +create algorithm=merge view v3 as select t1.f1 as f2, t1.f2 as f1 from t1; +select t1.f1 as x1, f1 from t1 order by t1.f1; +select v1.f1 as x1, f1 from v1 order by v1.f1; +select v2.f1 as x1, f1 from v2 order by v2.f1; +select v3.f1 as x1, f1 from v3 order by v3.f1; +select f1, f2, v1.f1 as x1 from v1 order by v1.f1; +select f1, f2, v2.f1 as x1 from v2 order by v2.f1; +select f1, f2, v3.f1 as x1 from v3 order by v3.f1; +drop table t1; +drop view v1, v2, v3; + +# +# Bug #15106: lost equality predicate of the form field=const in a join query +# + +CREATE TABLE t1(key_a int4 NOT NULL, optimus varchar(32), PRIMARY KEY(key_a)); +CREATE TABLE t2(key_a int4 NOT NULL, prime varchar(32), PRIMARY KEY(key_a)); +CREATE table t3(key_a int4 NOT NULL, key_b int4 NOT NULL, foo varchar(32), + PRIMARY KEY(key_a,key_b)); + +INSERT INTO t1 VALUES (0,''); +INSERT INTO t1 VALUES (1,'i'); +INSERT INTO t1 VALUES (2,'j'); +INSERT INTO t1 VALUES (3,'k'); + +INSERT INTO t2 VALUES (1,'r'); +INSERT INTO t2 VALUES (2,'s'); +INSERT INTO t2 VALUES (3,'t'); + +INSERT INTO t3 VALUES (1,5,'x'); +INSERT INTO t3 VALUES (1,6,'y'); +INSERT INTO t3 VALUES (2,5,'xx'); +INSERT INTO t3 VALUES (2,6,'yy'); +INSERT INTO t3 VALUES (2,7,'zz'); +INSERT INTO t3 VALUES (3,5,'xxx'); + +SELECT t2.key_a,foo + FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a + INNER JOIN t3 ON t1.key_a = t3.key_a + WHERE t2.key_a=2 and key_b=5; +EXPLAIN SELECT t2.key_a,foo + FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a + INNER JOIN t3 ON t1.key_a = t3.key_a + WHERE t2.key_a=2 and key_b=5; + +SELECT t2.key_a,foo + FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a + INNER JOIN t3 ON t1.key_a = t3.key_a + WHERE t2.key_a=2 and key_b=5; +EXPLAIN SELECT t2.key_a,foo + FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a + INNER JOIN t3 ON t1.key_a = t3.key_a + WHERE t2.key_a=2 and key_b=5; + +DROP TABLE t1,t2,t3; + +# +# Bug#15268 Unchecked null value caused server crash +# +create table t1(f1 char, f2 char not null); +insert into t1 values(null,'a'); +create table t2 (f2 char not null); +insert into t2 values('b'); +select * from t1 left join t2 on f1=t2.f2 where t1.f2='a'; +drop table t1,t2; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 89d281a2c58..4d418303e6d 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -10,6 +10,7 @@ drop table if exists t1,t2; drop table if exists t1aa,t2aa; drop database if exists mysqltest; +drop database if exists mysqltest1; delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; diff --git a/mysql-test/t/skip_grants.test b/mysql-test/t/skip_grants.test index 7a729f98661..16b0fbc4d25 100644 --- a/mysql-test/t/skip_grants.test +++ b/mysql-test/t/skip_grants.test @@ -9,7 +9,7 @@ use test; # test that we can create VIEW if privileges check switched off # create table t1 (field1 INT); --- error ER_NO_VIEW_USER +-- error ER_MALFORMED_DEFINER CREATE VIEW v1 AS SELECT field1 FROM t1; drop table t1; diff --git a/mysql-test/t/skip_name_resolve.test b/mysql-test/t/skip_name_resolve.test index b67869692d2..3f732c8912b 100644 --- a/mysql-test/t/skip_name_resolve.test +++ b/mysql-test/t/skip_name_resolve.test @@ -15,6 +15,6 @@ DROP USER mysqltest_1@'127.0.0.1/255.255.255.255'; connect (con1, 127.0.0.1, root, , test, $MASTER_MYPORT, ); --replace_column 1 # select user(); ---replace_column 1 # 6 # 3 # +--replace_column 1 <id> 3 <host> 5 <command> 6 <time> 7 <state> 8 <info> show processlist; connection default; diff --git a/mysql-test/t/sp-big.test b/mysql-test/t/sp-big.test index 389a6f04504..90a3a79dd53 100644 --- a/mysql-test/t/sp-big.test +++ b/mysql-test/t/sp-big.test @@ -52,6 +52,9 @@ while ($1) --enable_query_log select count(*) from t1; select count(*) from t2; +--disable_warnings +drop procedure if exists p1; +--enable_warnings delimiter |; create procedure p1() begin diff --git a/mysql-test/t/sp-code.test b/mysql-test/t/sp-code.test new file mode 100644 index 00000000000..6644bc3ab43 --- /dev/null +++ b/mysql-test/t/sp-code.test @@ -0,0 +1,49 @@ +# +# Test the debugging feature "show procedure/function code <name>" +# + +-- source include/is_debug_build.inc + +create procedure empty() +begin +end; +show procedure code empty; +drop procedure empty; + +create function almost_empty() + returns int + return 0; +show function code almost_empty; +drop function almost_empty; + +delimiter //; +create procedure code_sample(x int, out err int, out nulls int) +begin + declare count int default 0; + + set nulls = 0; + begin + declare c cursor for select name from t1; + declare exit handler for not found close c; + + open c; + loop + begin + declare n varchar(20); + declare continue handler for sqlexception set err=1; + + fetch c into n; + if isnull(n) then + set nulls = nulls + 1; + else + set count = count + 1; + update t2 set idx = count where name=n; + end if; + end; + end loop; + end; + select t.name, t.idx from t2 t order by idx asc; +end// +delimiter ;// +show procedure code code_sample; +drop procedure code_sample; diff --git a/mysql-test/t/sp-destruct.test b/mysql-test/t/sp-destruct.test new file mode 100644 index 00000000000..a2a66090866 --- /dev/null +++ b/mysql-test/t/sp-destruct.test @@ -0,0 +1,124 @@ +# +# Destructive stored procedure tests +# +# We do horrible things to the mysql.proc table here, so any unexpected +# failures here might leave it in an undetermined state. +# +# In the case of trouble you might want to skip this. +# + +# We're using --system things that probably doesn't work on Windows. +--source include/not_windows.inc + +# Backup proc table +--system rm -rf var/master-data/mysql/backup +--system mkdir var/master-data/mysql/backup +--system cp var/master-data/mysql/proc.* var/master-data/mysql/backup/ + +use test; + +--disable_warnings +drop procedure if exists bug14233; +drop function if exists bug14233; +drop table if exists t1; +drop view if exists v1; +--enable_warnings + +create procedure bug14233() + set @x = 42; + +create function bug14233_f() returns int + return 42; + +create table t1 (id int); +create trigger t1_ai after insert on t1 for each row call bug14233(); + +# Unsupported tampering with the mysql.proc definition +alter table mysql.proc drop type; +--error ER_SP_PROC_TABLE_CORRUPT +call bug14233(); +--error ER_SP_PROC_TABLE_CORRUPT +create view v1 as select bug14233_f(); +--error ER_SP_PROC_TABLE_CORRUPT +insert into t1 values (0); + +flush table mysql.proc; + +# Thrashing the .frm file +--system echo 'saljdlfa' > var/master-data/mysql/proc.frm +--error ER_NOT_FORM_FILE +call bug14233(); +--error ER_NOT_FORM_FILE +create view v1 as select bug14233_f(); +--error ER_NOT_FORM_FILE +insert into t1 values (0); + + +flush table mysql.proc; + +# Drop the mysql.proc table +--system rm var/master-data/mysql/proc.* +--error ER_NO_SUCH_TABLE +call bug14233(); +--error ER_NO_SUCH_TABLE +create view v1 as select bug14233_f(); +--error ER_NO_SUCH_TABLE +insert into t1 values (0); + +# Restore mysql.proc +--system mv var/master-data/mysql/backup/* var/master-data/mysql/ +--system rmdir var/master-data/mysql/backup + +flush table mysql.proc; +flush privileges; + +delete from mysql.proc where name like 'bug14233%'; + +# Unsupported editing of mysql.proc, circumventing checks in "create ..." +insert into mysql.proc +( + db, name, type, specific_name, language, sql_data_access, is_deterministic, + security_type, param_list, returns, body, definer, created, modified, + sql_mode, comment +) +values +( + 'test', 'bug14233_1', 'FUNCTION', 'bug14233_1', 'SQL', 'READS_SQL_DATA', 'NO', + 'DEFINER', '', 'int(10)', + 'select count(*) from mysql.user', + 'root@localhost', NOW() , '0000-00-00 00:00:00', '', '' +), +( + 'test', 'bug14233_2', 'FUNCTION', 'bug14233_2', 'SQL', 'READS_SQL_DATA', 'NO', + 'DEFINER', '', 'int(10)', + 'begin declare x int; select count(*) into x from mysql.user; end', + 'root@localhost', NOW() , '0000-00-00 00:00:00', '', '' +), +( + 'test', 'bug14233_3', 'PROCEDURE', 'bug14233_3', 'SQL', 'READS_SQL_DATA','NO', + 'DEFINER', '', '', + 'alksj wpsj sa ^#!@ ', + 'root@localhost', NOW() , '0000-00-00 00:00:00', '', '' +); + +--error ER_SP_PROC_TABLE_CORRUPT +select bug14233_1(); +--error ER_SP_PROC_TABLE_CORRUPT +create view v1 as select bug14233_1(); + +--error ER_SP_PROC_TABLE_CORRUPT +select bug14233_2(); +--error ER_SP_PROC_TABLE_CORRUPT +create view v1 as select bug14233_2(); + +--error ER_SP_PROC_TABLE_CORRUPT +call bug14233_3(); +drop trigger t1_ai; +create trigger t1_ai after insert on t1 for each row call bug14233_3(); +--error ER_SP_PROC_TABLE_CORRUPT +insert into t1 values (0); + +# Clean-up +delete from mysql.proc where name like 'bug14233%'; +drop trigger t1_ai; +drop table t1; diff --git a/mysql-test/t/sp-dynamic.test b/mysql-test/t/sp-dynamic.test index e9816ee3ef0..6546a5ab548 100644 --- a/mysql-test/t/sp-dynamic.test +++ b/mysql-test/t/sp-dynamic.test @@ -1,4 +1,10 @@ delimiter |; + +--disable_warnings +drop procedure if exists p1| +drop procedure if exists p2| +--enable_warnings + ###################################################################### # Test Dynamic SQL in stored procedures. ############################# ###################################################################### @@ -26,18 +32,29 @@ begin execute stmt; end| prepare stmt from "call p1()"| +# Allow SP resursion to be show that it has not influence here +set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth| +set @@max_sp_recursion_depth=100| --error ER_PS_NO_RECURSION execute stmt| --error ER_PS_NO_RECURSION execute stmt| --error ER_PS_NO_RECURSION execute stmt| ---error ER_SP_NO_RECURSION +--error ER_PS_NO_RECURSION call p1()| ---error ER_SP_NO_RECURSION +--error ER_PS_NO_RECURSION +call p1()| +--error ER_PS_NO_RECURSION call p1()| ---error ER_SP_NO_RECURSION +set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS| +--error ER_SP_RECURSION_LIMIT call p1()| +--error ER_SP_RECURSION_LIMIT +call p1()| +--error ER_SP_RECURSION_LIMIT +call p1()| + drop procedure p1| # # C. Create/drop a stored procedure in Dynamic SQL. diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index e2343cd905c..cf8f8dfc79c 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1044,10 +1044,11 @@ begin call bug11394(i - 1,(select 1)); end if; end| -# Again if we allow recursion for stored procedures (without -# additional efforts) the following statement will crash the server. ---error 1424 +--error ER_SP_RECURSION_LIMIT +call bug11394(2, 1)| +set @@max_sp_recursion_depth=10| call bug11394(2, 1)| +set @@max_sp_recursion_depth=default| drop procedure bug11394| delimiter ;| @@ -1094,7 +1095,7 @@ delimiter |; --disable_warnings DROP FUNCTION IF EXISTS bug12953| --enable_warnings ---error ER_SP_BADSTATEMENT +--error ER_SP_NO_RETSET CREATE FUNCTION bug12953() RETURNS INT BEGIN OPTIMIZE TABLE t1; @@ -1233,6 +1234,10 @@ begin select password; end| +# Check that an error message is sent +--error ER_PARSE_ERROR +set names='foo2'| + --error ER_SP_BAD_VAR_SHADOW create procedure bug13510_2() begin @@ -1263,8 +1268,167 @@ call bug13510_4()| drop procedure bug13510_3| drop procedure bug13510_4| + + +# +# Test that statements which implicitly commit transaction are prohibited +# in stored function and triggers. Attempt to create function or trigger +# containing such statement should produce error (includes test for +# bug #13627). +# +--disable_warnings +drop function if exists bug_13627_f| +--enable_warnings + +CREATE TABLE t1 (a int)| +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN DROP TRIGGER test1; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN DROP TRIGGER test1; return 1; END | + +-- error ER_SP_BADSTATEMENT +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN load table t1 from master; END | +-- error ER_SP_BADSTATEMENT +CREATE FUNCTION bug_13627_f() returns int BEGIN load table t1 from master; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create table t2 (a int); END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN create table t2 (a int); return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create index t1_i on t1 (a); END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN create index t1_i on t1 (a); return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN alter table t1 add column b int; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN alter table t1 add column b int; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN rename table t1 to t2; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN rename table t1 to t2; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN truncate table t1; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN truncate table t1; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop table t1; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN drop table t1; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop index t1_i on t1; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN drop index t1_i on t1; return 1; END | + +-- error ER_SP_BADSTATEMENT +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN unlock tables; END | +-- error ER_SP_BADSTATEMENT +CREATE FUNCTION bug_13627_f() returns int BEGIN unlock tables; return 1; END | + +-- error ER_SP_BADSTATEMENT +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN LOCK TABLE t1 READ; END | +-- error ER_SP_BADSTATEMENT +CREATE FUNCTION bug_13627_f() returns int BEGIN LOCK TABLE t1 READ; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create database mysqltest; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN create database mysqltest; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop database mysqltest; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN drop database mysqltest; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create user 'mysqltest_1'; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN create user 'mysqltest_1'; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop user 'mysqltest_1'; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN drop user 'mysqltest_1'; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN rename user 'mysqltest_2' to 'mysqltest_1'; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN rename user 'mysqltest_2' to 'mysqltest_1'; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create view v1 as select 1; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN create view v1 as select 1; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN alter view v1 as select 1; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN alter view v1 as select 1; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop view v1; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug_13627_f() returns int BEGIN drop view v1; return 1; END | + +-- error ER_SP_NO_RECURSIVE_CREATE +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create trigger tr2 before insert on t1 for each row do select 1; END | +-- error ER_SP_NO_RECURSIVE_CREATE +CREATE FUNCTION bug_13627_f() returns int BEGIN create trigger tr2 before insert on t1 for each row do select 1; return 1; END | + +-- error ER_SP_NO_DROP_SP +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop function bug_13627_f; END | +-- error ER_SP_NO_DROP_SP +CREATE FUNCTION bug_13627_f() returns int BEGIN drop function bug_13627_f; return 1; END | + +-- error ER_SP_NO_RECURSIVE_CREATE +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create function f2 () returns int return 1; END | +-- error ER_SP_NO_RECURSIVE_CREATE +CREATE FUNCTION bug_13627_f() returns int BEGIN create function f2 () returns int return 1; return 1; END | + +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW + BEGIN + CREATE TEMPORARY TABLE t2 (a int); + DROP TEMPORARY TABLE t2; + END | +CREATE FUNCTION bug_13627_f() returns int + BEGIN + CREATE TEMPORARY TABLE t2 (a int); + DROP TEMPORARY TABLE t2; + return 1; + END | + +drop table t1| +drop function bug_13627_f| + delimiter ;| +# BUG#12329: "Bogus error msg when executing PS with stored procedure after +# SP was re-created". See also test for related bug#13399 in trigger.test +drop function if exists bug12329; +--enable_warnings +create table t1 as select 1 a; +create table t2 as select 1 a; +create function bug12329() returns int return (select a from t1); +prepare stmt1 from 'select bug12329()'; +execute stmt1; +drop function bug12329; +create function bug12329() returns int return (select a+100 from t2); +select bug12329(); +# Until we implement proper mechanism for invalidation of PS/SP when table +# or SP's are changed the following statement will fail with 'Table ... was +# not locked' error (this mechanism should be based on the new TDC). +--error 1100 +execute stmt1; +deallocate prepare stmt1; +drop function bug12329; +drop table t1, t2; + # # Bug#13514 "server crash when create a stored procedure before choose a # database" and @@ -1337,6 +1501,121 @@ DROP PROCEDURE bug13037_p1; DROP PROCEDURE bug13037_p2; DROP PROCEDURE bug13037_p3; +# +# Bug#14569 "editing a stored procedure kills mysqld-nt" +# +create database mysqltest1; +create database mysqltest2; +use mysqltest1; +drop database mysqltest1; +create procedure mysqltest2.p1() select version(); +--error ER_NO_DB_ERROR +create procedure p2() select version(); +use mysqltest2; +--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' +show procedure status; +drop database mysqltest2; +use test; + +# +# Bug#13012 "SP: REPAIR/BACKUP/RESTORE TABLE crashes the server" +# +delimiter |; +--disable_warnings +DROP FUNCTION IF EXISTS bug13012| +--enable_warnings +--error ER_SP_NO_RETSET +CREATE FUNCTION bug13012() RETURNS INT +BEGIN + REPAIR TABLE t1; + RETURN 1; +END| +--error ER_SP_NO_RETSET +CREATE FUNCTION bug13012() RETURNS INT +BEGIN + BACKUP TABLE t1 TO '/tmp'; + RETURN 1; +END| +--error ER_SP_NO_RETSET +CREATE FUNCTION bug13012() RETURNS INT +BEGIN + RESTORE TABLE t1 FROM '/tmp'; + RETURN 1; +END| +create table t1 (a int)| +CREATE PROCEDURE bug13012_1() REPAIR TABLE t1| +CREATE FUNCTION bug13012_2() RETURNS INT +BEGIN + CALL bug13012_1(); + RETURN 1; +END| +--error ER_SP_NO_RETSET +SELECT bug13012_2()| +drop table t1| +drop procedure bug13012_1| +drop function bug13012_2| +delimiter ;| + +# BUG#11555 "Stored procedures: current SP tables locking make +# impossible view security". We should not expose names of tables +# which are implicitly used by view (via stored routines/triggers). +# +# Note that SQL standard assumes that you simply won't be able drop table +# and leave some objects (routines/views/triggers) which were depending on +# it. Such objects should be dropped in advance (by default) or will be +# dropped simultaneously with table (DROP TABLE with CASCADE clause). +# So these tests probably should go away once we will implement standard +# behavior. +--disable_warnings +drop function if exists bug11555_1; +drop function if exists bug11555_2; +drop view if exists v1, v2, v3, v4; +--enable_warnings +create function bug11555_1() returns int return (select max(i) from t1); +create function bug11555_2() returns int return bug11555_1(); +# It is OK to report name of implicitly used table which is missing +# when we create view. +--error ER_NO_SUCH_TABLE +create view v1 as select bug11555_1(); +--error ER_NO_SUCH_TABLE +create view v2 as select bug11555_2(); +# But we should hide name of missing implicitly used table when we use view +create table t1 (i int); +create view v1 as select bug11555_1(); +create view v2 as select bug11555_2(); +create view v3 as select * from v1; +drop table t1; +--error ER_VIEW_INVALID +select * from v1; +--error ER_VIEW_INVALID +select * from v2; +--error ER_VIEW_INVALID +select * from v3; +# Note that creation of view which depends on broken view is yet +# another form of view usage. +--error ER_VIEW_INVALID +create view v4 as select * from v1; +drop view v1, v2, v3; +# We also should hide details about broken triggers which are +# invoked for view. +drop function bug11555_1; +drop function bug11555_2; +create table t1 (i int); +create table t2 (i int); +create trigger t1_ai after insert on t1 for each row insert into t2 values (new.i); +create view v1 as select * from t1; +drop table t2; +--error ER_VIEW_INVALID +insert into v1 values (1); +drop trigger t1_ai; +create function bug11555_1() returns int return (select max(i) from t2); +create trigger t1_ai after insert on t1 for each row set @a:=bug11555_1(); +--error ER_VIEW_INVALID +insert into v1 values (2); +drop function bug11555_1; +drop table t1; +drop view v1; + # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index afbc383a17a..8d4f99abd71 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -336,6 +336,7 @@ connection user1; do 1; use test; +disconnect user1; connection root; REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost; drop function bug_9503; diff --git a/mysql-test/t/sp-vars.test b/mysql-test/t/sp-vars.test new file mode 100644 index 00000000000..81504904797 --- /dev/null +++ b/mysql-test/t/sp-vars.test @@ -0,0 +1,1273 @@ +########################################################################### +# +# Cleanup. +# +########################################################################### + +--disable_warnings + +# Drop stored routines (if any) for general SP-vars test cases. These routines +# are created in include/sp-vars.inc file. + +DROP PROCEDURE IF EXISTS sp_vars_check_dflt; +DROP PROCEDURE IF EXISTS sp_vars_check_assignment; +DROP FUNCTION IF EXISTS sp_vars_check_ret1; +DROP FUNCTION IF EXISTS sp_vars_check_ret2; +DROP FUNCTION IF EXISTS sp_vars_check_ret3; +DROP FUNCTION IF EXISTS sp_vars_check_ret4; + +--enable_warnings + +########################################################################### +# +# Some general tests for SP-vars functionality. +# +########################################################################### + +# Create the procedure in ANSI mode. Check that all necessary warnings are +# emitted properly. + +SET @@sql_mode = 'ansi'; + +--source include/sp-vars.inc + +--echo +--echo --------------------------------------------------------------- +--echo Calling the routines, created in ANSI mode. +--echo --------------------------------------------------------------- +--echo + +CALL sp_vars_check_dflt(); + +CALL sp_vars_check_assignment(); + +SELECT sp_vars_check_ret1(); + +SELECT sp_vars_check_ret2(); + +SELECT sp_vars_check_ret3(); + +SELECT sp_vars_check_ret4(); + +# Check that changing sql_mode after creating a store procedure does not +# matter. + +SET @@sql_mode = 'traditional'; + +--echo +--echo --------------------------------------------------------------- +--echo Calling in TRADITIONAL mode the routines, created in ANSI mode. +--echo --------------------------------------------------------------- +--echo + +CALL sp_vars_check_dflt(); + +CALL sp_vars_check_assignment(); + +SELECT sp_vars_check_ret1(); + +SELECT sp_vars_check_ret2(); + +SELECT sp_vars_check_ret3(); + +SELECT sp_vars_check_ret4(); + +# Create the procedure in TRADITIONAL mode. Check that error will be thrown on +# execution. + +DROP PROCEDURE sp_vars_check_dflt; +DROP PROCEDURE sp_vars_check_assignment; +DROP FUNCTION sp_vars_check_ret1; +DROP FUNCTION sp_vars_check_ret2; +DROP FUNCTION sp_vars_check_ret3; +DROP FUNCTION sp_vars_check_ret4; + +--source include/sp-vars.inc + +--echo +--echo --------------------------------------------------------------- +--echo Calling the routines, created in TRADITIONAL mode. +--echo --------------------------------------------------------------- +--echo + +--error ER_WARN_DATA_OUT_OF_RANGE +CALL sp_vars_check_dflt(); + +--error ER_WARN_DATA_OUT_OF_RANGE +CALL sp_vars_check_assignment(); + +--error ER_WARN_DATA_OUT_OF_RANGE +SELECT sp_vars_check_ret1(); + +--error ER_WARN_DATA_OUT_OF_RANGE +SELECT sp_vars_check_ret2(); + +--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD +SELECT sp_vars_check_ret3(); + +# TODO: Is it an error, that only a warning is emitted here? Check the same +# behaviour with tables. + +SELECT sp_vars_check_ret4(); + +SET @@sql_mode = 'ansi'; + +# +# Cleanup. +# + +DROP PROCEDURE sp_vars_check_dflt; +DROP PROCEDURE sp_vars_check_assignment; +DROP FUNCTION sp_vars_check_ret1; +DROP FUNCTION sp_vars_check_ret2; +DROP FUNCTION sp_vars_check_ret3; +DROP FUNCTION sp_vars_check_ret4; + +########################################################################### +# +# Tests for BIT data type. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BIT data type tests +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +--enable_warnings + +# +# Test case. +# + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + DECLARE v1 BIT; + DECLARE v2 BIT(1); + DECLARE v3 BIT(3) DEFAULT b'101'; + DECLARE v4 BIT(64) DEFAULT 0x5555555555555555; + DECLARE v5 BIT(3); + DECLARE v6 BIT(64); + DECLARE v7 BIT(8) DEFAULT 128; + DECLARE v8 BIT(8) DEFAULT '128'; + DECLARE v9 BIT(8) DEFAULT ' 128'; + DECLARE v10 BIT(8) DEFAULT 'x 128'; + + SET v1 = v4; + SET v2 = 0; + SET v5 = v4; # check overflow + SET v6 = v3; # check padding + + SELECT HEX(v1); + SELECT HEX(v2); + SELECT HEX(v3); + SELECT HEX(v4); + SELECT HEX(v5); + SELECT HEX(v6); + SELECT HEX(v7); + SELECT HEX(v8); + SELECT HEX(v9); + SELECT HEX(v10); +END| +delimiter ;| + +CALL p1(); + +# +# Cleanup. +# + +DROP PROCEDURE p1; + +########################################################################### +# +# Tests for CASE statements functionality: +# - test for general functionality (scopes, nested cases, CASE in loops); +# - test that if type of the CASE expression is changed on each iteration, +# the execution will be correct. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo CASE expression tests. +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP TABLE IF EXISTS t1; + +# +# Test case. +# + +CREATE TABLE t1(log_msg VARCHAR(1024)); + +delimiter |; + +CREATE PROCEDURE p1(arg VARCHAR(255)) +BEGIN + INSERT INTO t1 VALUES('p1: step1'); + + CASE arg * 10 + WHEN 10 * 10 THEN + INSERT INTO t1 VALUES('p1: case1: on 10'); + WHEN 10 * 10 + 10 * 10 THEN + BEGIN + CASE arg / 10 + WHEN 1 THEN + INSERT INTO t1 VALUES('p1: case1: case2: on 1'); + WHEN 2 THEN + BEGIN + DECLARE i TINYINT DEFAULT 10; + + WHILE i > 0 DO + INSERT INTO t1 VALUES(CONCAT('p1: case1: case2: loop: i: ', i)); + + CASE MOD(i, 2) + WHEN 0 THEN + INSERT INTO t1 VALUES('p1: case1: case2: loop: i is even'); + WHEN 1 THEN + INSERT INTO t1 VALUES('p1: case1: case2: loop: i is odd'); + ELSE + INSERT INTO t1 VALUES('p1: case1: case2: loop: ERROR'); + END CASE; + + SET i = i - 1; + END WHILE; + END; + ELSE + INSERT INTO t1 VALUES('p1: case1: case2: ERROR'); + END CASE; + + CASE arg + WHEN 10 THEN + INSERT INTO t1 VALUES('p1: case1: case3: on 10'); + WHEN 20 THEN + INSERT INTO t1 VALUES('p1: case1: case3: on 20'); + ELSE + INSERT INTO t1 VALUES('p1: case1: case3: ERROR'); + END CASE; + END; + ELSE + INSERT INTO t1 VALUES('p1: case1: ERROR'); + END CASE; + + CASE arg * 10 + WHEN 10 * 10 THEN + INSERT INTO t1 VALUES('p1: case4: on 10'); + WHEN 10 * 10 + 10 * 10 THEN + BEGIN + CASE arg / 10 + WHEN 1 THEN + INSERT INTO t1 VALUES('p1: case4: case5: on 1'); + WHEN 2 THEN + BEGIN + DECLARE i TINYINT DEFAULT 10; + + WHILE i > 0 DO + INSERT INTO t1 VALUES(CONCAT('p1: case4: case5: loop: i: ', i)); + + CASE MOD(i, 2) + WHEN 0 THEN + INSERT INTO t1 VALUES('p1: case4: case5: loop: i is even'); + WHEN 1 THEN + INSERT INTO t1 VALUES('p1: case4: case5: loop: i is odd'); + ELSE + INSERT INTO t1 VALUES('p1: case4: case5: loop: ERROR'); + END CASE; + + SET i = i - 1; + END WHILE; + END; + ELSE + INSERT INTO t1 VALUES('p1: case4: case5: ERROR'); + END CASE; + + CASE arg + WHEN 10 THEN + INSERT INTO t1 VALUES('p1: case4: case6: on 10'); + WHEN 20 THEN + INSERT INTO t1 VALUES('p1: case4: case6: on 20'); + ELSE + INSERT INTO t1 VALUES('p1: case4: case6: ERROR'); + END CASE; + END; + ELSE + INSERT INTO t1 VALUES('p1: case4: ERROR'); + END CASE; +END| + +CREATE PROCEDURE p2() +BEGIN + DECLARE i TINYINT DEFAULT 3; + + WHILE i > 0 DO + IF MOD(i, 2) = 0 THEN + SET @_test_session_var = 10; + ELSE + SET @_test_session_var = 'test'; + END IF; + + CASE @_test_session_var + WHEN 10 THEN + INSERT INTO t1 VALUES('p2: case: numerical type'); + WHEN 'test' THEN + INSERT INTO t1 VALUES('p2: case: string type'); + ELSE + INSERT INTO t1 VALUES('p2: case: ERROR'); + END CASE; + + SET i = i - 1; + END WHILE; +END| + +delimiter ;| + +CALL p1(10); +CALL p1(20); + +CALL p2(); + +SELECT * FROM t1; + +# +# Cleanup. +# + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP TABLE t1; + +########################################################################### +# +# Test case for BUG#14161: Stored procedure cannot retrieve bigint unsigned. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#14161 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; +--enable_warnings + +# +# Test case. +# + +CREATE TABLE t1(col BIGINT UNSIGNED); + +INSERT INTO t1 VALUE(18446744073709551614); + +delimiter |; +CREATE PROCEDURE p1(IN arg BIGINT UNSIGNED) +BEGIN + SELECT arg; + SELECT * FROM t1; + SELECT * FROM t1 WHERE col = arg; +END| +delimiter ;| + +CALL p1(18446744073709551614); + +# +# Cleanup. +# + +DROP TABLE t1; +DROP PROCEDURE p1; + +########################################################################### +# +# Test case for BUG#13705: parameters to stored procedures are not verified. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#13705 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +--enable_warnings + +# +# Test case. +# + +delimiter |; +CREATE PROCEDURE p1(x VARCHAR(10), y CHAR(3)) READS SQL DATA +BEGIN + SELECT x, y; +END| +delimiter ;| + +CALL p1('alpha', 'abc'); +CALL p1('alpha', 'abcdef'); + +# +# Cleanup. +# + +DROP PROCEDURE p1; + +########################################################################### +# +# Test case for BUG#13675: DATETIME/DATE type in store proc param seems to be +# converted as varbinary. +# +# TODO: test case failed. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#13675 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1; +--enable_warnings + +# +# Test case. +# + +delimiter |; +CREATE PROCEDURE p1(x DATETIME) +BEGIN + CREATE TABLE t1 SELECT x; + SHOW CREATE TABLE t1; + DROP TABLE t1; +END| +delimiter ;| + +CALL p1(NOW()); + +CALL p1('test'); + +# +# Cleanup. +# + +DROP PROCEDURE p1; + +########################################################################### +# +# Test case for BUG#12976: Boolean values reversed in stored procedures? +# +# TODO: test case failed. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#12976 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +--enable_warnings + +# +# Test case. +# + +CREATE TABLE t1(b BIT(1)); + +INSERT INTO t1(b) VALUES(b'0'), (b'1'); + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + SELECT HEX(b), + b = 0, + b = FALSE, + b IS FALSE, + b = 1, + b = TRUE, + b IS TRUE + FROM t1; +END| + +CREATE PROCEDURE p2() +BEGIN + DECLARE vb BIT(1); + SELECT b INTO vb FROM t1 WHERE b = 0; + + SELECT HEX(vb), + vb = 0, + vb = FALSE, + vb IS FALSE, + vb = 1, + vb = TRUE, + vb IS TRUE; + + SELECT b INTO vb FROM t1 WHERE b = 1; + + SELECT HEX(vb), + vb = 0, + vb = FALSE, + vb IS FALSE, + vb = 1, + vb = TRUE, + vb IS TRUE; +END| +delimiter ;| + +# The expected and correct result. + +call p1(); + +# The wrong result. Note that only hex(vb) works, but is printed with two +# digits for some reason in this case. + +call p2(); + +# +# Cleanup. +# + +DROP TABLE t1; +DROP PROCEDURE p1; +DROP PROCEDURE p2; + +########################################################################### +# +# Test case for BUG#9572: Stored procedures: variable type declarations +# ignored. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#9572 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; + +DROP PROCEDURE IF EXISTS p4; +DROP PROCEDURE IF EXISTS p5; +DROP PROCEDURE IF EXISTS p6; +--enable_warnings + +# +# Test case. +# + +SET @@sql_mode = 'traditional'; + +delimiter |; + +CREATE PROCEDURE p1() +BEGIN + DECLARE v TINYINT DEFAULT 1e200; + SELECT v; +END| + +CREATE PROCEDURE p2() +BEGIN + DECLARE v DECIMAL(5) DEFAULT 1e200; + SELECT v; +END| + +CREATE PROCEDURE p3() +BEGIN + DECLARE v CHAR(5) DEFAULT 'abcdef'; + SELECT v LIKE 'abc___'; +END| + +CREATE PROCEDURE p4(arg VARCHAR(2)) +BEGIN + DECLARE var VARCHAR(1); + SET var := arg; + SELECT arg, var; +END| + +CREATE PROCEDURE p5(arg CHAR(2)) +BEGIN + DECLARE var CHAR(1); + SET var := arg; + SELECT arg, var; +END| + +CREATE PROCEDURE p6(arg DECIMAL(2)) +BEGIN + DECLARE var DECIMAL(1); + SET var := arg; + SELECT arg, var; +END| + +delimiter ;| + +--error ER_WARN_DATA_OUT_OF_RANGE +CALL p1(); +--error ER_WARN_DATA_OUT_OF_RANGE +CALL p2(); +--error ER_DATA_TOO_LONG +CALL p3(); + +--error ER_DATA_TOO_LONG +CALL p4('aaa'); +--error ER_DATA_TOO_LONG +CALL p5('aa'); +--error ER_WARN_DATA_OUT_OF_RANGE +CALL p6(10); + +# +# Cleanup. +# + +SET @@sql_mode = 'ansi'; + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; + +DROP PROCEDURE p4; +DROP PROCEDURE p5; +DROP PROCEDURE p6; + +########################################################################### +# +# Test case for BUG#9078: STORED PROCDURE: Decimal digits are not displayed +# when we use DECIMAL datatype. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#9078 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +--enable_warnings + +# +# Test case. +# + +delimiter |; +CREATE PROCEDURE p1 (arg DECIMAL(64,2)) +BEGIN + DECLARE var DECIMAL(64,2); + + SET var = arg; + SELECT var; +END| +delimiter ;| + +CALL p1(1929); +CALL p1(1929.00); +CALL p1(1929.003); + +# +# Cleanup. +# + +DROP PROCEDURE p1; + +########################################################################### +# +# Test case for BUG#8768: Functions: For any unsigned data type, -ve values can +# be passed and returned. +# +# TODO: there is a bug here -- the function created in ANSI mode should not +# throw errors instead of warnings if called in TRADITIONAL mode. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#8768 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +# +# Test case. +# + +# Create a function in ANSI mode. + +delimiter |; +CREATE FUNCTION f1(arg TINYINT UNSIGNED) RETURNS TINYINT +BEGIN + RETURN arg; +END| +delimiter ;| + +SELECT f1(-2500); + +# Call in TRADITIONAL mode the function created in ANSI mode. + +SET @@sql_mode = 'traditional'; + +# TODO: a warning should be emitted here. +--error ER_WARN_DATA_OUT_OF_RANGE +SELECT f1(-2500); + +# Recreate the function in TRADITIONAL mode. + +DROP FUNCTION f1; + +delimiter |; +CREATE FUNCTION f1(arg TINYINT UNSIGNED) RETURNS TINYINT +BEGIN + RETURN arg; +END| +delimiter ;| + +--error ER_WARN_DATA_OUT_OF_RANGE +SELECT f1(-2500); + +# +# Cleanup. +# + +SET @@sql_mode = 'ansi'; + +DROP FUNCTION f1; + +########################################################################### +# +# Test case for BUG#8769: Functions: For Int datatypes, out of range values can +# be passed and returned. +# +# TODO: there is a bug here -- the function created in ANSI mode should not +# throw errors instead of warnings if called in TRADITIONAL mode. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#8769 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +# +# Test case. +# + +# Create a function in ANSI mode. + +delimiter |; +CREATE FUNCTION f1(arg MEDIUMINT) RETURNS MEDIUMINT +BEGIN + RETURN arg; +END| +delimiter ;| + +SELECT f1(8388699); + +# Call in TRADITIONAL mode the function created in ANSI mode. + +SET @@sql_mode = 'traditional'; + +# TODO: a warning should be emitted here. +--error ER_WARN_DATA_OUT_OF_RANGE +SELECT f1(8388699); + +# Recreate the function in TRADITIONAL mode. + +DROP FUNCTION f1; + +delimiter |; +CREATE FUNCTION f1(arg MEDIUMINT) RETURNS MEDIUMINT +BEGIN + RETURN arg; +END| +delimiter ;| + +--error ER_WARN_DATA_OUT_OF_RANGE +SELECT f1(8388699); + +# +# Cleanup. +# + +SET @@sql_mode = 'ansi'; + +DROP FUNCTION f1; + +########################################################################### +# +# Test case for BUG#8702: Stored Procedures: No Error/Warning shown for +# inappropriate data type matching. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#8702 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1; +--enable_warnings + +# +# Test case. +# + +CREATE TABLE t1(col VARCHAR(255)); + +INSERT INTO t1(col) VALUES('Hello, world!'); + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + DECLARE sp_var INTEGER; + + SELECT col INTO sp_var FROM t1 LIMIT 1; + SET @user_var = sp_var; + + SELECT sp_var; + SELECT @user_var; +END| +delimiter ;| + +CALL p1(); + +# +# Cleanup. +# + +DROP PROCEDURE p1; +DROP TABLE t1; + +########################################################################### +# +# Test case for BUG#12903: upper function does not work inside a function. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#12903 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP FUNCTION IF EXISTS f1; +DROP TABLE IF EXISTS t1; +--enable_warnings + +# +# Test case. +# + +CREATE TABLE t1(txt VARCHAR(255)); + +delimiter |; +CREATE FUNCTION f1(arg VARCHAR(255)) RETURNS VARCHAR(255) +BEGIN + DECLARE v1 VARCHAR(255); + DECLARE v2 VARCHAR(255); + + SET v1 = CONCAT(LOWER(arg), UPPER(arg)); + SET v2 = CONCAT(LOWER(v1), UPPER(v1)); + + INSERT INTO t1 VALUES(v1), (v2); + + RETURN CONCAT(LOWER(arg), UPPER(arg)); +END| +delimiter ;| + +SELECT f1('_aBcDe_'); + +SELECT * FROM t1; + +# +# Cleanup. +# + +DROP FUNCTION f1; +DROP TABLE t1; + +########################################################################### +# +# Test case for BUG#13808: ENUM type stored procedure parameter accepts +# non-enumerated data. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#13808 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +# +# Test case. +# + +delimiter |; + +CREATE PROCEDURE p1(arg ENUM('a', 'b')) +BEGIN + SELECT arg; +END| + +CREATE PROCEDURE p2(arg ENUM('a', 'b')) +BEGIN + DECLARE var ENUM('c', 'd') DEFAULT arg; + + SELECT arg, var; +END| + +CREATE FUNCTION f1(arg ENUM('a', 'b')) RETURNS ENUM('c', 'd') +BEGIN + RETURN arg; +END| + +delimiter ;| + +CALL p1('c'); + +CALL p2('a'); + +SELECT f1('a'); + +# +# Cleanup. +# + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP FUNCTION f1; + +########################################################################### +# +# Test case for BUG#13909: Varchar Stored Procedure Parameter always BINARY +# string (ignores CHARACTER SET). +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#13909 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +--enable_warnings + +# +# Test case. +# + +delimiter |; + +CREATE PROCEDURE p1(arg VARCHAR(255)) +BEGIN + SELECT CHARSET(arg); +END| + +CREATE PROCEDURE p2(arg VARCHAR(255) CHARACTER SET UTF8) +BEGIN + SELECT CHARSET(arg); +END| + +delimiter ;| + +CALL p1('t'); +CALL p1(_UTF8 't'); + + +CALL p2('t'); +CALL p2(_LATIN1 't'); + +# +# Cleanup. +# + +DROP PROCEDURE p1; +DROP PROCEDURE p2; + +########################################################################### +# +# Test case for BUG#14188: BINARY variables have no 0x00 padding. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#14188 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +--enable_warnings + +# +# Test case. +# + +delimiter |; +CREATE PROCEDURE p1(arg1 BINARY(2), arg2 VARBINARY(2)) +BEGIN + DECLARE var1 BINARY(2) DEFAULT 0x41; + DECLARE var2 VARBINARY(2) DEFAULT 0x42; + + SELECT HEX(arg1), HEX(arg2); + SELECT HEX(var1), HEX(var2); +END| +delimiter ;| + +CALL p1(0x41, 0x42); + +# +# Cleanup. +# + +DROP PROCEDURE p1; + +########################################################################### +# +# Test case for BUG#15148: Stored procedure variables accept non-scalar values. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#15148 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1; +--enable_warnings + +# +# Test case. +# + +CREATE TABLE t1(col1 TINYINT, col2 TINYINT); + +INSERT INTO t1 VALUES(1, 2), (11, 12); + +delimiter |; +CREATE PROCEDURE p1(arg TINYINT) +BEGIN + SELECT arg; +END| +delimiter ;| + +--error ER_OPERAND_COLUMNS +CALL p1((1, 2)); + +--error ER_OPERAND_COLUMNS +CALL p1((SELECT * FROM t1 LIMIT 1)); + +--error ER_OPERAND_COLUMNS +CALL p1((SELECT col1, col2 FROM t1 LIMIT 1)); + +# +# Cleanup. +# + +DROP PROCEDURE p1; +DROP TABLE t1; + +########################################################################### +# +# Test case for BUG#13613: substring function in stored procedure. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#13613 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +# +# Test case. +# + +delimiter |; + +CREATE PROCEDURE p1(x VARCHAR(50)) +BEGIN + SET x = SUBSTRING(x, 1, 3); + SELECT x; +END| + +CREATE FUNCTION f1(x VARCHAR(50)) RETURNS VARCHAR(50) +BEGIN + RETURN SUBSTRING(x, 1, 3); +END| + +delimiter ;| + +CALL p1('abcdef'); + +SELECT f1('ABCDEF'); + +# +# Cleanup. +# + +DROP PROCEDURE p1; +DROP FUNCTION f1; + +########################################################################### +# +# Test case for BUG#13665: concat with '' produce incorrect results in SP. +# +########################################################################### + +--echo +--echo --------------------------------------------------------------- +--echo BUG#13665 +--echo --------------------------------------------------------------- +--echo + +# +# Prepare. +# + +--disable_warnings +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +# +# Test case. +# + +delimiter |; +CREATE FUNCTION f1() RETURNS VARCHAR(20000) +BEGIN + DECLARE var VARCHAR(2000); + + SET var = ''; + SET var = CONCAT(var, 'abc'); + SET var = CONCAT(var, ''); + + RETURN var; +END| +delimiter ;| + +SELECT f1(); + +# +# Cleanup. +# + +DROP FUNCTION f1; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index ab57139bb77..f73288f04ba 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -13,6 +13,8 @@ # Tests that require multiple connections, except security/privilege tests, # go to sp-thread. # Tests that uses 'goto' to into sp-goto.test (currently disabled) +# Tests that destroys system tables (e.g. mysql.proc) for error testing +# go to sp-destruct. use test; @@ -365,6 +367,7 @@ create function sub3(i int) returns int call sub1("sub1a", (select 7))| call sub1("sub1b", (select max(i) from t2))| +--error ER_OPERAND_COLUMNS call sub1("sub1c", (select i,d from t2 limit 1))| call sub1("sub1d", (select 1 from (select 1) a))| call sub2("sub2")| @@ -1211,15 +1214,13 @@ begin end if; end| select f5(1)| -# This should generate an error about insuficient number of tables locked -# Now this crash server ---disable_parsing # until bug#11394 fix ---error 1100 +# Since currently recursive functions are disallowed ER_SP_NO_RECURSION +# error will be returned, once we will allow them error about +# insufficient number of locked tables will be returned instead. +--error ER_SP_NO_RECURSION select f5(2)| -# But now it simply miserably fails because we are trying to use the same -# lex on the next iteration :/ It should generate some error too... +--error ER_SP_NO_RECURSION select f5(3)| ---enable_parsing # OTOH this should work create function f6() returns int @@ -1265,13 +1266,12 @@ select * from v1| # views and functions ? create function f1() returns int return (select sum(data) from t1) + (select sum(data) from v1)| -# This queries will crash server because we can't use LEX in -# reenterable fashion yet. Patch disabling recursion will heal this. ---disable_parsing +--error ER_SP_NO_RECURSION select f1()| +--error ER_SP_NO_RECURSION select * from v1| +--error ER_SP_NO_RECURSION select * from v2| ---enable_parsing # Back to the normal cases drop function f1| create function f1() returns int @@ -1289,9 +1289,7 @@ select *, f0() from v0| # # Let us test how well prelocking works with explicit LOCK TABLES. # -# Nowdays we have to lock mysql.proc to be able to read SP definitions. -# But Monty was going to fix this. -lock tables t1 read, t1 as t11 read, mysql.proc read| +lock tables t1 read, t1 as t11 read| # These should work well select f3()| select id, f3() from t1 as t11| @@ -1481,9 +1479,6 @@ show procedure status like '%p%'| # Fibonacci, for recursion test. (Yet Another Numerical series :) # -# This part of test is disabled until we implement support for -# recursive stored procedures. ---disable_parsing --disable_warnings drop table if exists fib| --enable_warnings @@ -1512,6 +1507,9 @@ begin end if; end| +# Enable recursion +set @@max_sp_recursion_depth= 20| + # Minimum test: recursion of 3 levels insert into fib values (0), (1)| @@ -1531,7 +1529,7 @@ call fib(20)| select * from fib order by f asc| drop table fib| drop procedure fib| ---enable_parsing +set @@max_sp_recursion_depth= 0| # # Comment & suid @@ -1800,16 +1798,8 @@ select @x2| drop procedure bug2260| # -# BUG#2267 +# BUG#2267 "Lost connect if stored procedure has SHOW FUNCTION STATUS" # -# NOTE: This test case will be fixed as soon as Monty -# will allow to open mysql.proc table under LOCK TABLES -# without mentioning in lock list. -# -# FIXME: Other solution would be to use preopened proc table -# instead of opening it anew. -# ---disable_parsing --disable_warnings drop procedure if exists bug2267_1| --enable_warnings @@ -1836,11 +1826,13 @@ end| --disable_warnings drop procedure if exists bug2267_4| +drop function if exists bug2267_4| --enable_warnings create procedure bug2267_4() begin - show create function fac; + show create function bug2267_4; end| +create function bug2267_4() returns int return 100| --replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' call bug2267_1()| @@ -1853,7 +1845,7 @@ drop procedure bug2267_1| drop procedure bug2267_2| drop procedure bug2267_3| drop procedure bug2267_4| ---enable_parsing +drop function bug2267_4| # # BUG#2227 @@ -1873,23 +1865,16 @@ call bug2227(9)| drop procedure bug2227| # -# BUG#2614 +# BUG#2614 "Stored procedure with INSERT ... SELECT that does not +# contain any tables crashes server" # -# QQ The second insert doesn't work with temporary tables (it was an -# QQ ordinary table before we changed the locking scheme). It results -# QQ in an error: 1137: Can't reopen table: 't3' -# QQ which is a known limit with temporary tables. -# QQ For this reason we can't run this test any more (i.e., if we modify -# QQ it, it's no longer a test case for the bug), but we keep it here -# QQ anyway, for tracability. ---disable_parsing --disable_warnings drop procedure if exists bug2614| --enable_warnings create procedure bug2614() begin - drop temporary table if exists t3; - create temporary table t3 (id int default '0' not null); + drop table if exists t3; + create table t3 (id int default '0' not null); insert into t3 select 12; insert into t3 select * from t3; end| @@ -1898,9 +1883,8 @@ end| call bug2614()| --enable_warnings call bug2614()| -drop temporary table t3| +drop table t3| drop procedure bug2614| ---enable_parsing # # BUG#2674 @@ -4291,6 +4275,9 @@ call bug12589_1()| # No warnings here call bug12589_2()| call bug12589_3()| +drop procedure bug12589_1| +drop procedure bug12589_2| +drop procedure bug12589_3| # # BUG#7049: Stored procedure CALL errors are ignored @@ -4488,6 +4475,608 @@ DROP TABLE IF EXISTS bug13095_t1; delimiter |; +# +# BUG#14210: "Simple query with > operator on large table gives server +# crash" +# Check that cursors work in case when HEAP tables are converted to +# MyISAM +# +--disable_warnings +drop procedure if exists bug14210| +--enable_warnings +set @@session.max_heap_table_size=16384| +select @@session.max_heap_table_size| +# To trigger the memory corruption the original table must be InnoDB. +# No harm if it's not, so don't warn if the suite is run with --skip-innodb +--disable_warnings +create table t3 (a char(255)) engine=InnoDB| +--enable_warnings +create procedure bug14210_fill_table() +begin + declare table_size, max_table_size int default 0; + select @@session.max_heap_table_size into max_table_size; + delete from t3; + insert into t3 (a) values (repeat('a', 255)); + repeat + insert into t3 select a from t3; + select count(*)*255 from t3 into table_size; + until table_size > max_table_size*2 end repeat; +end| +call bug14210_fill_table()| +drop procedure bug14210_fill_table| +create table t4 like t3| + +create procedure bug14210() +begin + declare a char(255); + declare done int default 0; + declare c cursor for select * from t3; + declare continue handler for sqlstate '02000' set done = 1; + open c; + repeat + fetch c into a; + if not done then + insert into t4 values (upper(a)); + end if; + until done end repeat; + close c; +end| +call bug14210()| +select count(*) from t4| + +drop table t3, t4| +drop procedure bug14210| +set @@session.max_heap_table_size=default| + + +# +# BUG#1473: Dumping of stored functions seems to cause corruption in +# the function body +# +--disable_warnings +drop function if exists bug14723| +drop procedure if exists bug14723| +--enable_warnings + +delimiter ;;| +/*!50003 create function bug14723() + returns bigint(20) +main_loop: begin + return 42; +end */;; +show create function bug14723;; +select bug14723();; + +/*!50003 create procedure bug14723() +main_loop: begin + select 42; +end */;; +show create procedure bug14723;; +call bug14723();; + +delimiter |;; + +drop function bug14723| +drop procedure bug14723| + +# +# Bug#14845 "mysql_stmt_fetch returns MYSQL_NO_DATA when COUNT(*) is 0" +# Check that when fetching from a cursor, COUNT(*) works properly. +# +create procedure bug14845() +begin + declare a char(255); + declare done int default 0; + declare c cursor for select count(*) from t1 where 1 = 0; + declare continue handler for sqlstate '02000' set done = 1; + open c; + repeat + fetch c into a; + if not done then + select a; + end if; + until done end repeat; + close c; +end| +call bug14845()| +drop procedure bug14845| + +# +# BUG#13549 "Server crash with nested stored procedures". +# Server should not crash when during execution of stored procedure +# we have to parse trigger/function definition and this new trigger/ +# function has more local variables declared than invoking stored +# procedure and last of these variables is used in argument of NOT +# operator. +# +--disable_warnings +drop procedure if exists bug13549_1| +drop procedure if exists bug13549_2| +--enable_warnings +CREATE PROCEDURE `bug13549_2`() +begin + call bug13549_1(); +end| +CREATE PROCEDURE `bug13549_1`() +begin + declare done int default 0; + set done= not done; +end| +CALL bug13549_2()| +drop procedure bug13549_2| +drop procedure bug13549_1| + +# +# BUG#10100: function (and stored procedure?) recursivity problem +# +--disable_warnings +drop function if exists bug10100f| +drop procedure if exists bug10100p| +drop procedure if exists bug10100t| +drop procedure if exists bug10100pt| +drop procedure if exists bug10100pv| +drop procedure if exists bug10100pd| +drop procedure if exists bug10100pc| +--enable_warnings +# routines with simple recursion +create function bug10100f(prm int) returns int +begin + if prm > 1 then + return prm * bug10100f(prm - 1); + end if; + return 1; +end| +create procedure bug10100p(prm int, inout res int) +begin + set res = res * prm; + if prm > 1 then + call bug10100p(prm - 1, res); + end if; +end| +create procedure bug10100t(prm int) +begin + declare res int; + set res = 1; + call bug10100p(prm, res); + select res; +end| + +# a procedure which use tables and recursion +create table t3 (a int)| +insert into t3 values (0)| +create view v1 as select a from t3; +create procedure bug10100pt(level int, lim int) +begin + if level < lim then + update t3 set a=level; + FLUSH TABLES; + call bug10100pt(level+1, lim); + else + select * from t3; + end if; +end| +# view & recursion +create procedure bug10100pv(level int, lim int) +begin + if level < lim then + update v1 set a=level; + FLUSH TABLES; + call bug10100pv(level+1, lim); + else + select * from v1; + end if; +end| +# dynamic sql & recursion +prepare stmt2 from "select * from t3;"; +create procedure bug10100pd(level int, lim int) +begin + if level < lim then + select level; + prepare stmt1 from "update t3 set a=a+2"; + execute stmt1; + FLUSH TABLES; + execute stmt1; + FLUSH TABLES; + execute stmt1; + FLUSH TABLES; + deallocate prepare stmt1; + execute stmt2; + select * from t3; + call bug10100pd(level+1, lim); + else + execute stmt2; + end if; +end| +# cursor & recursion +create procedure bug10100pc(level int, lim int) +begin + declare lv int; + declare c cursor for select a from t3; + open c; + if level < lim then + select level; + fetch c into lv; + select lv; + update t3 set a=level+lv; + FLUSH TABLES; + call bug10100pc(level+1, lim); + else + select * from t3; + end if; + close c; +end| + +set @@max_sp_recursion_depth=4| +select @@max_sp_recursion_depth| +-- error ER_SP_NO_RECURSION +select bug10100f(3)| +-- error ER_SP_NO_RECURSION +select bug10100f(6)| +call bug10100t(5)| +call bug10100pt(1,5)| +call bug10100pv(1,5)| +update t3 set a=1| +call bug10100pd(1,5)| +select * from t3| +update t3 set a=1| +call bug10100pc(1,5)| +select * from t3| +set @@max_sp_recursion_depth=0| +select @@max_sp_recursion_depth| +-- error ER_SP_NO_RECURSION +select bug10100f(5)| +-- error ER_SP_RECURSION_LIMIT +call bug10100t(5)| + +#end of the stack checking +set @@max_sp_recursion_depth=255| +set @var=1| +#disable log because error about stack overrun contains numbers which +#depend on a system +-- disable_result_log +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100p(255, @var)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pt(1,255)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pv(1,255)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pd(1,255)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pc(1,255)| +-- enable_result_log +set @@max_sp_recursion_depth=0| + +deallocate prepare stmt2| + +drop function bug10100f| +drop procedure bug10100p| +drop procedure bug10100t| +drop procedure bug10100pt| +drop procedure bug10100pv| +drop procedure bug10100pd| +drop procedure bug10100pc| +drop view v1| + +# +# BUG#13729: Stored procedures: packet error after exception handled +# +--disable_warnings +drop procedure if exists bug13729| +drop table if exists t3| +--enable_warnings + +create table t3 (s1 int, primary key (s1))| + +insert into t3 values (1),(2)| + +create procedure bug13729() +begin + declare continue handler for sqlexception select 55; + + update t3 set s1 = 1; +end| + +call bug13729()| +# Used to cause Packets out of order +select * from t3| + +drop procedure bug13729| +drop table t3| + +# +# BUG#14643: Stored Procedure: Continuing after failed var. initialization +# crashes server. +# +--disable_warnings +drop procedure if exists bug14643_1| +drop procedure if exists bug14643_2| +--enable_warnings + +create procedure bug14643_1() +begin + declare continue handler for sqlexception select 'boo' as 'Handler'; + + begin + declare v int default undefined_var; + + if v = 1 then + select 1; + else + select v, isnull(v); + end if; + end; +end| + +create procedure bug14643_2() +begin + declare continue handler for sqlexception select 'boo' as 'Handler'; + + case undefined_var + when 1 then + select 1; + else + select 2; + end case; + + select undefined_var; +end| + +call bug14643_1()| +call bug14643_2()| + +drop procedure bug14643_1| +drop procedure bug14643_2| + +# +# BUG#14304: auto_increment field incorrect set in SP +# +--disable_warnings +drop procedure if exists bug14304| +drop table if exists t3, t4| +--enable_warnings + +create table t3(a int primary key auto_increment)| +create table t4(a int primary key auto_increment)| + +create procedure bug14304() +begin + insert into t3 set a=null; + insert into t4 set a=null; + insert into t4 set a=null; + insert into t4 set a=null; + insert into t4 set a=null; + insert into t4 set a=null; + insert into t4 select null as a; + + insert into t3 set a=null; + insert into t3 set a=null; + + select * from t3; +end| + +call bug14304()| + +drop procedure bug14304| +drop table t3, t4| + +# +# BUG#14376: MySQL crash on scoped variable (re)initialization +# +--disable_warnings +drop procedure if exists bug14376| +--enable_warnings + +create procedure bug14376() +begin + declare x int default x; +end| + +# Not the error we want, but that's what we got for now... +--error ER_BAD_FIELD_ERROR +call bug14376()| +drop procedure bug14376| + +create procedure bug14376() +begin + declare x int default 42; + + begin + declare x int default x; + + select x; + end; +end| + +call bug14376()| + +drop procedure bug14376| + +create procedure bug14376(x int) +begin + declare x int default x; + + select x; +end| + +call bug14376(4711)| + +drop procedure bug14376| + +# +# Bug#5967 "Stored procedure declared variable used instead of column" +# The bug should be fixed later. +# Test precedence of names of parameters, variable declarations, +# variable declarations in nested compound statements, table columns, +# table columns in cursor declarations. +# According to the standard, table columns take precedence over +# variable declarations. In MySQL 5.0 it's vice versa. +# + +--disable_warnings +drop procedure if exists bug5967| +drop table if exists t3| +--enable_warnings +create table t3 (a varchar(255))| +insert into t3 (a) values ("a - table column")| +create procedure bug5967(a varchar(255)) +begin + declare i varchar(255); + declare c cursor for select a from t3; + select a; + select a from t3 into i; + select i as 'Parameter takes precedence over table column'; open c; + fetch c into i; + close c; + select i as 'Parameter takes precedence over table column in cursors'; + begin + declare a varchar(255) default 'a - local variable'; + declare c1 cursor for select a from t3; + select a as 'A local variable takes precedence over parameter'; + open c1; + fetch c1 into i; + close c1; + select i as 'A local variable takes precedence over parameter in cursors'; + begin + declare a varchar(255) default 'a - local variable in a nested compound statement'; + declare c2 cursor for select a from t3; + select a as 'A local variable in a nested compound statement takes precedence over a local variable in the outer statement'; + select a from t3 into i; + select i as 'A local variable in a nested compound statement takes precedence over table column'; + open c2; + fetch c2 into i; + close c2; + select i as 'A local variable in a nested compound statement takes precedence over table column in cursors'; + end; + end; +end| +call bug5967("a - stored procedure parameter")| +drop procedure bug5967| + +# +# Bug#13012 "SP: REPAIR/BACKUP/RESTORE TABLE crashes the server" +# +--disable_warnings +drop procedure if exists bug13012| +--enable_warnings +create procedure bug13012() +BEGIN + REPAIR TABLE t1; + BACKUP TABLE t1 to '../tmp'; + DROP TABLE t1; + RESTORE TABLE t1 FROM '../tmp'; +END| +call bug13012()| +drop procedure bug13012| +create view v1 as select * from t1| +create procedure bug13012() +BEGIN + REPAIR TABLE t1,t2,t3,v1; + OPTIMIZE TABLE t1,t2,t3,v1; + ANALYZE TABLE t1,t2,t3,v1; +END| +call bug13012()| +call bug13012()| +call bug13012()| +drop procedure bug13012| +drop view v1; +select * from t1| + +# +# A test case for Bug#15392 "Server crashes during prepared statement +# execute": make sure that stored procedure check for error conditions +# properly and do not continue execution if an error has been set. +# +# It's necessary to use several DBs because in the original code +# the successful return of mysql_change_db overrode the error from +# execution. +drop schema if exists mysqltest1| +drop schema if exists mysqltest2| +drop schema if exists mysqltest3| +create schema mysqltest1| +create schema mysqltest2| +create schema mysqltest3| +use mysqltest3| + +create procedure mysqltest1.p1 (out prequestid varchar(100)) +begin + call mysqltest2.p2('call mysqltest3.p3(1, 2)'); +end| + +create procedure mysqltest2.p2(in psql text) +begin + declare lsql text; + set @lsql= psql; + prepare lstatement from @lsql; + execute lstatement; + deallocate prepare lstatement; +end| + +create procedure mysqltest3.p3(in p1 int) +begin + select p1; +end| + +--error ER_SP_WRONG_NO_OF_ARGS +call mysqltest1.p1(@rs)| +--error ER_SP_WRONG_NO_OF_ARGS +call mysqltest1.p1(@rs)| +--error ER_SP_WRONG_NO_OF_ARGS +call mysqltest1.p1(@rs)| +drop schema if exists mysqltest1| +drop schema if exists mysqltest2| +drop schema if exists mysqltest3| +use test| + +# +# Bug#15441 "Running SP causes Server to Crash": check that an SP variable +# can not be used in VALUES() function. +# +--disable_warnings +drop table if exists t3| +drop procedure if exists bug15441| +--enable_warnings +create table t3 (id int not null primary key, county varchar(25))| +insert into t3 (id, county) values (1, 'York')| + +# First check that a stored procedure that refers to a parameter in VALUES() +# function won't parse. + +create procedure bug15441(c varchar(25)) +begin + update t3 set id=2, county=values(c); +end| +--error ER_BAD_FIELD_ERROR +call bug15441('county')| +drop procedure bug15441| + +# Now check the case when there is an ambiguity between column names +# and stored procedure parameters: the parser shall resolve the argument +# of VALUES() function to the column name. + +# It's hard to deduce what county refers to in every case (INSERT statement): +# 1st county refers to the column +# 2nd county refers to the procedure parameter +# 3d and 4th county refers to the column, again, but +# for 4th county it has the value of SP parameter + +# In UPDATE statement, just check that values() function returns NULL for +# non- INSERT...UPDATE statements, as stated in the manual. + +create procedure bug15441(county varchar(25)) +begin + declare c varchar(25) default "hello"; + + insert into t3 (id, county) values (1, county) + on duplicate key update county= values(county); + select * from t3; + + update t3 set id=2, county=values(id); + select * from t3; +end| +call bug15441('Yale')| +drop table t3| +drop procedure bug15441| # # BUG#NNNN: New bug synopsis diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test index 82e1cd2f1c9..308d4ad5c33 100644 --- a/mysql-test/t/sp_trans.test +++ b/mysql-test/t/sp_trans.test @@ -176,6 +176,250 @@ drop table t1, t2| # +# BUG#13825 "Triggers: crash if release savepoint". +# Also general test for handling of savepoints in stored routines. +# +# According to SQL standard we should establish new savepoint +# level before executing stored function/trigger and destroy +# this savepoint level after execution. Stored procedures by +# default should be executed using the same savepoint level +# as their caller (to execute stored procedure using new +# savepoint level one should explicitly specify NEW SAVEPOINT +# LEVEL clause in procedure creation statement which MySQL +# does not support yet). +--disable_warnings +drop function if exists bug13825_0| +drop function if exists bug13825_1| +drop function if exists bug13825_2| +drop function if exists bug13825_3| +drop function if exists bug13825_4| +drop function if exists bug13825_5| +drop procedure if exists bug13825_0| +drop procedure if exists bug13825_1| +drop procedure if exists bug13825_2| +drop table if exists t1| +--enable_warnings +create table t1 (i int) engine=innodb| +create table t2 (i int) engine=innodb| +create function bug13825_0() returns int +begin + rollback to savepoint x; + return 1; +end| +create function bug13825_1() returns int +begin + release savepoint x; + return 1; +end| +create function bug13825_2() returns int +begin + insert into t1 values (2); + savepoint x; + insert into t1 values (3); + rollback to savepoint x; + insert into t1 values (4); + return 1; +end| +create procedure bug13825_0() +begin + rollback to savepoint x; +end| +create procedure bug13825_1() +begin + release savepoint x; +end| +create procedure bug13825_2() +begin + savepoint x; +end| +insert into t2 values (1)| +create trigger t2_bi before insert on t2 for each row + rollback to savepoint x| +create trigger t2_bu before update on t2 for each row + release savepoint x| +create trigger t2_bd before delete on t2 for each row +begin + insert into t1 values (2); + savepoint x; + insert into t1 values (3); + rollback to savepoint x; + insert into t1 values (4); +end| +create function bug13825_3(rb int) returns int +begin + insert into t1 values(1); + savepoint x; + insert into t1 values(2); + if rb then + rollback to savepoint x; + end if; + insert into t1 values(3); + return rb; +end| +create function bug13825_4() returns int +begin + savepoint x; + insert into t1 values(2); + rollback to savepoint x; + return 0; +end| +create function bug13825_5(p int) returns int +begin + savepoint x; + insert into t2 values(p); + rollback to savepoint x; + insert into t2 values(p+1); + return p; +end| +set autocommit= 0| +# Test of savepoint level handling for stored functions and triggers +begin | +insert into t1 values (1)| +savepoint x| +--error ER_SP_DOES_NOT_EXIST +set @a:= bug13825_0()| +--error ER_SP_DOES_NOT_EXIST +insert into t2 values (2)| +--error ER_SP_DOES_NOT_EXIST +set @a:= bug13825_1()| +--error ER_SP_DOES_NOT_EXIST +update t2 set i = 2| +set @a:= bug13825_2()| +select * from t1| +rollback to savepoint x| +select * from t1| +delete from t2| +select * from t1| +rollback to savepoint x| +select * from t1| +# Of course savepoints set in function should not be visible from its caller +release savepoint x| +set @a:= bug13825_2()| +select * from t1| +--error ER_SP_DOES_NOT_EXIST +rollback to savepoint x| +delete from t1| +commit| +# Test of savepoint level handling for stored procedures +begin| +insert into t1 values (5)| +savepoint x| +insert into t1 values (6)| +call bug13825_0()| +select * from t1| +call bug13825_1()| +--error ER_SP_DOES_NOT_EXIST +rollback to savepoint x| +savepoint x| +insert into t1 values (7)| +call bug13825_2()| +rollback to savepoint x| +select * from t1| +delete from t1| +commit| +set autocommit= 1| +# Let us test that savepoints work inside of functions +# even in auto-commit mode +select bug13825_3(0)| +select * from t1| +delete from t1| +select bug13825_3(1)| +select * from t1| +delete from t1| +# Curious case: rolling back to savepoint which is set by first +# statement in function should not rollback whole transaction. +set autocommit= 0| +begin| +insert into t1 values (1)| +set @a:= bug13825_4()| +select * from t1| +delete from t1| +commit| +set autocommit= 1| +# Other curious case: savepoint in the middle of statement +drop table t2| +create table t2 (i int) engine=innodb| +insert into t1 values (1), (bug13825_5(2)), (3)| +select * from t1| +select * from t2| +# Cleanup +drop function bug13825_0| +drop function bug13825_1| +drop function bug13825_2| +drop function bug13825_3| +drop function bug13825_4| +drop function bug13825_5| +drop procedure bug13825_0| +drop procedure bug13825_1| +drop procedure bug13825_2| +drop table t1, t2| + + +# +# BUG#14840: CONTINUE handler problem +# +--disable_warnings +drop table if exists t3| +drop procedure if exists bug14840_1| +drop procedure if exists bug14840_2| +--enable_warnings + +create table t3 +( + x int, + y int, + primary key (x) +) engine=InnoDB| + +# This used to hang the client since the insert returned with an +# error status (left over from the update) even though it succeeded, +# which caused the execution to end at that point. +create procedure bug14840_1() +begin + declare err int default 0; + declare continue handler for sqlexception + set err = err + 1; + + start transaction; + update t3 set x = 1, y = 42 where x = 2; + insert into t3 values (3, 4711); + if err > 0 then + rollback; + else + commit; + end if; + select * from t3; +end| + +# A simpler (non-transactional) case: insert at select should be done +create procedure bug14840_2() +begin + declare err int default 0; + declare continue handler for sqlexception + begin + set err = err + 1; + select err as 'Ping'; + end; + + update t3 set x = 1, y = 42 where x = 2; + update t3 set x = 1, y = 42 where x = 2; + insert into t3 values (3, 4711); + select * from t3; +end| + +insert into t3 values (1, 3), (2, 5)| +call bug14840_1()| + +delete from t3| +insert into t3 values (1, 3), (2, 5)| +call bug14840_2()| + +drop procedure bug14840_1| +drop procedure bug14840_2| +drop table t3| + + +# # BUG#NNNN: New bug synopsis # #--disable_warnings diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test index b11afe9e59d..8ae9ced6c68 100644 --- a/mysql-test/t/sql_mode.test +++ b/mysql-test/t/sql_mode.test @@ -1,5 +1,6 @@ --disable_warnings -drop table if exists t1; +drop table if exists t1,t2,v1,v2; +drop view if exists t1,t2,v1,v2; --enable_warnings CREATE TABLE `t1` ( diff --git a/mysql-test/t/ssl.test b/mysql-test/t/ssl.test new file mode 100644 index 00000000000..de88569d74a --- /dev/null +++ b/mysql-test/t/ssl.test @@ -0,0 +1,17 @@ +# Turn on ssl between the client and server +# and run a number of tests + +-- source include/have_openssl.inc + +connect (ssl_con,localhost,root,,,,,SSL); + +# Check ssl turned on +SHOW STATUS LIKE 'Ssl_cipher'; + +# Source select test case +-- source include/common-tests.inc + +# Check ssl turned on +SHOW STATUS LIKE 'Ssl_cipher'; + + diff --git a/mysql-test/t/ssl_compress.test b/mysql-test/t/ssl_compress.test new file mode 100644 index 00000000000..f5fe86e9a81 --- /dev/null +++ b/mysql-test/t/ssl_compress.test @@ -0,0 +1,22 @@ +# Turn on compression between the client and server +# and run a number of tests + +-- source include/have_openssl.inc +-- source include/have_compress.inc + +connect (ssl_compress_con,localhost,root,,,,,SSL COMPRESS); + +# Check ssl turned on +SHOW STATUS LIKE 'Ssl_cipher'; + +# Check compression turned on +SHOW STATUS LIKE 'Compression'; + +# Source select test case +-- source include/common-tests.inc + +# Check ssl turned on +SHOW STATUS LIKE 'Ssl_cipher'; + +# Check compression turned on +SHOW STATUS LIKE 'Compression'; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index cc621fb5835..762ff36ba63 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1968,3 +1968,86 @@ drop table t1; purge master logs before (select adddate(current_timestamp(), interval -4 day)); +# +# Test for bug #11762: subquery with an aggregate function in HAVING +# + +CREATE TABLE t1 (a int, b int); +CREATE TABLE t2 (c int, d int); +CREATE TABLE t3 (e int); + +INSERT INTO t1 VALUES + (1,10), (2,10), (1,20), (2,20), (3,20), (2,30), (4,40); +INSERT INTO t2 VALUES + (2,10), (2,20), (4,10), (5,10), (3,20), (2,40); +INSERT INTO t3 VALUES (10), (30), (10), (20) ; + +SELECT a, MAX(b), MIN(b) FROM t1 GROUP BY a; +SELECT * FROM t2; +SELECT * FROM t3; + +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 WHERE MAX(b)>20); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 WHERE MAX(b)<d); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 WHERE MAX(b)>d); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 + WHERE d >= SOME(SELECT e FROM t3 WHERE MAX(b)=e)); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 + WHERE EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e <= d)); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 + WHERE d > SOME(SELECT e FROM t3 WHERE MAX(b)=e)); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 + WHERE EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e < d)); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 + WHERE MIN(b) < d AND + EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e <= d)); + +SELECT a, SUM(a) FROM t1 GROUP BY a; + +SELECT a FROM t1 + WHERE EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) = c) GROUP BY a; +SELECT a FROM t1 GROUP BY a + HAVING EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) = c); + +SELECT a FROM t1 + WHERE a < 3 AND + EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) != c) GROUP BY a; +SELECT a FROM t1 + WHERE a < 3 AND + EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) != c); + +SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a < ALL(SELECT t2.c FROM t2 GROUP BY t2.c + HAVING EXISTS(SELECT t3.e FROM t3 GROUP BY t3.e + HAVING SUM(t1.a+t2.c) < t3.e/4)); +SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.c FROM t2 + WHERE EXISTS(SELECT t3.e FROM t3 GROUP BY t3.e + HAVING SUM(t1.a+t2.c) < t3.e/4)); +-- error 1111 +SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.c FROM t2 + WHERE EXISTS(SELECT t3.e FROM t3 + WHERE SUM(t1.a+t2.c) < t3.e/4)); +-- error 1111 +SELECT t1.a from t1 GROUP BY t1.a HAVING AVG(SUM(t1.b)) > 20; + +SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c + HAVING AVG(t2.c+SUM(t1.b)) > 20); +SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c + HAVING AVG(SUM(t1.b)) > 20); + +SELECT t1.a, SUM(b) AS sum FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c + HAVING t2.c+sum > 20); + +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test index a07cc93ad68..4bfc4d17588 100644 --- a/mysql-test/t/subselect_innodb.test +++ b/mysql-test/t/subselect_innodb.test @@ -183,3 +183,57 @@ group by country; drop table t1; +# +# BUG#14342: wrong placement of subquery internals in complex queries +# +CREATE TABLE `t1` ( + `t3_id` int NOT NULL, + `t1_id` int NOT NULL, + PRIMARY KEY (`t1_id`) +); +CREATE TABLE `t2` ( + `t2_id` int NOT NULL, + `t1_id` int NOT NULL, + `b` int NOT NULL, + PRIMARY KEY (`t2_id`), + UNIQUE KEY `idx_t2_t1_b` (`t1_id`,`b`) +) ENGINE=InnoDB; +CREATE TABLE `t3` ( + `t3_id` int NOT NULL +); +INSERT INTO `t3` VALUES (3); +select + (SELECT rs.t2_id + FROM t2 rs + WHERE rs.t1_id= + (SELECT lt.t1_id + FROM t1 lt + WHERE lt.t3_id=a.t3_id) + ORDER BY b DESC LIMIT 1) +from t3 AS a; +# repeat above query in SP +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +--enable_warnings +delimiter //; +create procedure p1() +begin + declare done int default 3; + repeat + select + (SELECT rs.t2_id + FROM t2 rs + WHERE rs.t1_id= + (SELECT lt.t1_id + FROM t1 lt + WHERE lt.t3_id=a.t3_id) + ORDER BY b DESC LIMIT 1) as x + from t3 AS a; + set done= done-1; + until done <= 0 end repeat; +end// +delimiter ;// +call p1(); +call p1(); +call p1(); +drop tables t1,t2,t3; diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index b7a7e83d569..6a6dd305006 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -3,6 +3,8 @@ disable_query_log; show variables like "have_symlink"; enable_query_log; +--source include/not_windows.inc + --disable_warnings drop table if exists t1,t2,t7,t8,t9; drop database if exists mysqltest; diff --git a/mysql-test/t/trigger-compat.test b/mysql-test/t/trigger-compat.test new file mode 100644 index 00000000000..c2acc235135 --- /dev/null +++ b/mysql-test/t/trigger-compat.test @@ -0,0 +1,83 @@ +# Test case(s) in this file contain(s) GRANT/REVOKE statements, which are not +# supported in embedded server. So, this test should not be run on embedded +# server. + +-- source include/not_embedded.inc + +########################################################################### +# +# Tests for WL#2818: +# - Check that triggers created w/o DEFINER information work well: +# - create the first trigger; +# - manually remove definer information from corresponding TRG file; +# - create the second trigger (the first trigger will be reloaded; check +# that we receive a warning); +# - check that the triggers loaded correctly; +# +########################################################################### + +# +# Prepare environment. +# + +DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.columns_priv WHERE User LIKE 'mysqltest_%'; +FLUSH PRIVILEGES; + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest_db1; +--enable_warnings + +CREATE DATABASE mysqltest_db1; + +CREATE USER mysqltest_dfn@localhost; +CREATE USER mysqltest_inv@localhost; + +GRANT SUPER ON *.* TO mysqltest_dfn@localhost; +GRANT CREATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; + +# +# Create a table and the first trigger. +# + +--connect (wl2818_definer_con,localhost,mysqltest_dfn,,mysqltest_db1) +--connection wl2818_definer_con +--echo +--echo ---> connection: wl2818_definer_con + +CREATE TABLE t1(num_value INT); +CREATE TABLE t2(user_str TEXT); + +CREATE TRIGGER wl2818_trg1 BEFORE INSERT ON t1 + FOR EACH ROW + INSERT INTO t2 VALUES(CURRENT_USER()); + +# +# Remove definers from TRG file. +# + +--echo +--echo ---> patching t1.TRG... + +--exec grep -v 'definers=' $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG > $MYSQL_TEST_DIR/var/tmp/t1.TRG +--exec mv $MYSQL_TEST_DIR/var/tmp/t1.TRG $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG + +# +# Create a new trigger. +# + +--echo + +CREATE TRIGGER wl2818_trg2 AFTER INSERT ON t1 + FOR EACH ROW + INSERT INTO t2 VALUES(CURRENT_USER()); + +--echo + +SELECT trigger_name, definer FROM INFORMATION_SCHEMA.TRIGGERS ORDER BY trigger_name; + +--echo + +SELECT * FROM INFORMATION_SCHEMA.TRIGGERS ORDER BY trigger_name; diff --git a/mysql-test/t/trigger-grant.test b/mysql-test/t/trigger-grant.test new file mode 100644 index 00000000000..deeaeacbccc --- /dev/null +++ b/mysql-test/t/trigger-grant.test @@ -0,0 +1,475 @@ +# Test case(s) in this file contain(s) GRANT/REVOKE statements, which are not +# supported in embedded server. So, this test should not be run on embedded +# server. + +-- source include/not_embedded.inc + +########################################################################### +# +# Tests for WL#2818: +# - Check that triggers are executed under the authorization of the definer. +# - Check that if trigger contains NEW/OLD variables, the definer must have +# SELECT privilege on the subject table. +# - Check DEFINER clause of CREATE TRIGGER statement; +# - Check that SUPER privilege required to create a trigger with different +# definer. +# - Check that if the user specified as DEFINER does not exist, a warning +# is emitted. +# - Check that the definer of a trigger does not exist, the trigger will +# not be activated. +# - Check that SHOW TRIGGERS statement provides "Definer" column. +# +# Let's also check that user name part of definer can contain '@' symbol (to +# check that triggers are not affected by BUG#13310 "incorrect user parsing +# by SP"). +# +########################################################################### + +# +# Prepare environment. +# + +DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.columns_priv WHERE User LIKE 'mysqltest_%'; +FLUSH PRIVILEGES; + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest_db1; +--enable_warnings + +CREATE DATABASE mysqltest_db1; + +CREATE USER mysqltest_dfn@localhost; +CREATE USER mysqltest_inv@localhost; + +GRANT SUPER ON *.* TO mysqltest_dfn@localhost; +GRANT CREATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; + +# +# Check that triggers are executed under the authorization of the definer: +# - create two tables under "definer"; +# - grant all privileges on the test db to "definer"; +# - grant all privileges on the first table to "invoker"; +# - grant only select privilege on the second table to "invoker"; +# - create a trigger, which inserts a row into the second table after +# inserting into the first table. +# - insert a row into the first table under "invoker". A row also should be +# inserted into the second table. +# + +--connect (wl2818_definer_con,localhost,mysqltest_dfn,,mysqltest_db1) +--connection wl2818_definer_con +--echo +--echo ---> connection: wl2818_definer_con + +CREATE TABLE t1(num_value INT); +CREATE TABLE t2(user_str TEXT); + +CREATE TRIGGER trg1 AFTER INSERT ON t1 + FOR EACH ROW + INSERT INTO t2 VALUES(CURRENT_USER()); + +--connection default +--echo +--echo ---> connection: default + +# Setup definer's privileges. + +GRANT ALL PRIVILEGES ON mysqltest_db1.t1 TO mysqltest_dfn@localhost; +GRANT ALL PRIVILEGES ON mysqltest_db1.t2 TO mysqltest_dfn@localhost; + +# Setup invoker's privileges. + +GRANT ALL PRIVILEGES ON mysqltest_db1.t1 + TO 'mysqltest_inv'@localhost; + +GRANT SELECT ON mysqltest_db1.t2 + TO 'mysqltest_inv'@localhost; + +--connection wl2818_definer_con +--echo +--echo ---> connection: wl2818_definer_con + +use mysqltest_db1; + +INSERT INTO t1 VALUES(1); + +SELECT * FROM t1; +SELECT * FROM t2; + +--connect (wl2818_invoker_con,localhost,mysqltest_inv,,mysqltest_db1) +--connection wl2818_invoker_con +--echo +--echo ---> connection: wl2818_invoker_con + +use mysqltest_db1; + +INSERT INTO t1 VALUES(2); + +SELECT * FROM t1; +SELECT * FROM t2; + +# +# Check that if definer lost some privilege required to execute (activate) a +# trigger, the trigger will not be activated: +# - create a trigger on insert into the first table, which will insert a row +# into the second table; +# - revoke INSERT privilege on the second table from the definer; +# - insert a row into the first table; +# - check that an error has been risen; +# - check that no row has been inserted into the second table; +# + +--connection default +--echo +--echo ---> connection: default + +use mysqltest_db1; + +REVOKE INSERT ON mysqltest_db1.t2 FROM mysqltest_dfn@localhost; + +--connection wl2818_invoker_con +--echo +--echo ---> connection: wl2818_invoker_con + +use mysqltest_db1; + +--error ER_TABLEACCESS_DENIED_ERROR +INSERT INTO t1 VALUES(3); + +SELECT * FROM t1; +SELECT * FROM t2; + +# +# Check that if trigger contains NEW/OLD variables, the definer must have +# SELECT/UPDATE privilege on the subject table: +# - drop the trigger; +# - create a new trigger, which will use NEW variable; +# - create another new trigger, which will use OLD variable; +# - revoke SELECT/UPDATE privilege on the first table from "definer"; +# - insert a row into the first table; +# - analyze error code; +# + +# +# SELECT privilege. +# + +--connection default +--echo +--echo ---> connection: default + +use mysqltest_db1; + +REVOKE SELECT ON mysqltest_db1.t1 FROM mysqltest_dfn@localhost; + +--connection wl2818_definer_con +--echo +--echo ---> connection: wl2818_definer_con + +use mysqltest_db1; + +DROP TRIGGER trg1; + +SET @new_sum = 0; +SET @old_sum = 0; + +# INSERT INTO statement; BEFORE timing + +--echo ---> INSERT INTO statement; BEFORE timing + +CREATE TRIGGER trg1 BEFORE INSERT ON t1 + FOR EACH ROW + SET @new_sum = @new_sum + NEW.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +INSERT INTO t1 VALUES(4); + +# INSERT INTO statement; AFTER timing + +--echo ---> INSERT INTO statement; AFTER timing + +DROP TRIGGER trg1; + +CREATE TRIGGER trg1 AFTER INSERT ON t1 + FOR EACH ROW + SET @new_sum = @new_sum + NEW.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +INSERT INTO t1 VALUES(5); + +# UPDATE statement; BEFORE timing + +--echo ---> UPDATE statement; BEFORE timing + +DROP TRIGGER trg1; + +CREATE TRIGGER trg1 BEFORE UPDATE ON t1 + FOR EACH ROW + SET @old_sum = @old_sum + OLD.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +UPDATE t1 SET num_value = 10; + +# UPDATE statement; AFTER timing + +--echo ---> UPDATE statement; AFTER timing + +DROP TRIGGER trg1; + +CREATE TRIGGER trg1 AFTER UPDATE ON t1 + FOR EACH ROW + SET @new_sum = @new_sum + NEW.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +UPDATE t1 SET num_value = 20; + +# DELETE statement; BEFORE timing + +--echo ---> DELETE statement; BEFORE timing + +DROP TRIGGER trg1; + +CREATE TRIGGER trg1 BEFORE DELETE ON t1 + FOR EACH ROW + SET @old_sum = @old_sum + OLD.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +DELETE FROM t1; + +# DELETE statement; AFTER timing + +--echo ---> DELETE statement; AFTER timing + +DROP TRIGGER trg1; + +CREATE TRIGGER trg1 AFTER DELETE ON t1 + FOR EACH ROW + SET @old_sum = @old_sum + OLD.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +DELETE FROM t1; + +# +# UPDATE privilege +# +# NOTE: At the moment, UPDATE privilege is required if the trigger contains +# NEW/OLD variables, whenever the trigger modifies them or not. Moreover, +# UPDATE privilege is checked for whole table, not for individual columns. +# +# The following test cases should be changed when full support of UPDATE +# privilege will be done. +# + +--connection default +--echo +--echo ---> connection: default + +use mysqltest_db1; + +GRANT SELECT ON mysqltest_db1.t1 TO mysqltest_dfn@localhost; +REVOKE UPDATE ON mysqltest_db1.t1 FROM mysqltest_dfn@localhost; + +--connection wl2818_definer_con +--echo +--echo ---> connection: wl2818_definer_con + +use mysqltest_db1; + +DROP TRIGGER trg1; + +SET @new_sum = 0; +SET @old_sum = 0; + +# INSERT INTO statement; BEFORE timing + +--echo ---> INSERT INTO statement; BEFORE timing + +CREATE TRIGGER trg1 BEFORE INSERT ON t1 + FOR EACH ROW + SET @new_sum = @new_sum + NEW.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +INSERT INTO t1 VALUES(4); + +# INSERT INTO statement; AFTER timing + +--echo ---> INSERT INTO statement; AFTER timing + +DROP TRIGGER trg1; + +CREATE TRIGGER trg1 AFTER INSERT ON t1 + FOR EACH ROW + SET @new_sum = @new_sum + NEW.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +INSERT INTO t1 VALUES(5); + +# UPDATE statement; BEFORE timing + +--echo ---> UPDATE statement; BEFORE timing + +DROP TRIGGER trg1; + +CREATE TRIGGER trg1 BEFORE UPDATE ON t1 + FOR EACH ROW + SET @old_sum = @old_sum + OLD.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +UPDATE t1 SET num_value = 10; + +# UPDATE statement; AFTER timing + +--echo ---> UPDATE statement; AFTER timing + +DROP TRIGGER trg1; + +CREATE TRIGGER trg1 AFTER UPDATE ON t1 + FOR EACH ROW + SET @new_sum = @new_sum + NEW.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +UPDATE t1 SET num_value = 20; + +# DELETE statement; BEFORE timing + +--echo ---> DELETE statement; BEFORE timing + +DROP TRIGGER trg1; + +CREATE TRIGGER trg1 BEFORE DELETE ON t1 + FOR EACH ROW + SET @old_sum = @old_sum + OLD.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +DELETE FROM t1; + +# DELETE statement; AFTER timing + +--echo ---> DELETE statement; AFTER timing + +DROP TRIGGER trg1; + +CREATE TRIGGER trg1 AFTER DELETE ON t1 + FOR EACH ROW + SET @old_sum = @old_sum + OLD.num_value; + +--error ER_TABLEACCESS_DENIED_ERROR +DELETE FROM t1; + +# +# Check DEFINER clause of CREATE TRIGGER statement. +# +# NOTE: there is no dedicated TRIGGER privilege for CREATE TRIGGER statement. +# SUPER privilege is used instead. I.e., if one invokes CREATE TRIGGER, it should +# have SUPER privilege, so this test is meaningless right now. +# +# - Check that SUPER privilege required to create a trigger with different +# definer: +# - try to create a trigger with DEFINER="definer@localhost" under +# "invoker"; +# - analyze error code; +# - Check that if the user specified as DEFINER does not exist, a warning is +# emitted: +# - create a trigger with DEFINER="non_existent_user@localhost" from +# "definer"; +# - check that a warning emitted; +# - Check that the definer of a trigger does not exist, the trigger will not +# be activated: +# - activate just created trigger; +# - check error code; +# + +--connection wl2818_definer_con +--echo +--echo ---> connection: wl2818_definer_con + +use mysqltest_db1; + +DROP TRIGGER trg1; + +# Check that SUPER is required to specify different DEFINER. +# NOTE: meaningless at the moment + +CREATE DEFINER='mysqltest_inv'@'localhost' + TRIGGER trg1 BEFORE INSERT ON t1 + FOR EACH ROW + SET @new_sum = 0; + +# Create with non-existent user. + +CREATE DEFINER='mysqltest_nonexs'@'localhost' + TRIGGER trg2 AFTER INSERT ON t1 + FOR EACH ROW + SET @new_sum = 0; + +# Check that trg2 will not be activated. + +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +INSERT INTO t1 VALUES(6); + +# +# Check that SHOW TRIGGERS statement provides "Definer" column. +# + +SHOW TRIGGERS; + +# +# Check that weird definer values do not break functionality. I.e. check the +# following definer values: +# - ''; +# - '@'; +# - '@abc@def@@'; +# - '@hostname'; +# - '@abc@def@@@hostname'; +# + +DROP TRIGGER trg1; +DROP TRIGGER trg2; + +CREATE TRIGGER trg1 BEFORE INSERT ON t1 + FOR EACH ROW + SET @a = 1; + +CREATE TRIGGER trg2 AFTER INSERT ON t1 + FOR EACH ROW + SET @a = 2; + +CREATE TRIGGER trg3 BEFORE UPDATE ON t1 + FOR EACH ROW + SET @a = 3; + +CREATE TRIGGER trg4 AFTER UPDATE ON t1 + FOR EACH ROW + SET @a = 4; + +CREATE TRIGGER trg5 BEFORE DELETE ON t1 + FOR EACH ROW + SET @a = 5; + +--exec egrep -v '^definers=' $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG > $MYSQL_TEST_DIR/var/tmp/t1.TRG +--exec echo "definers='' '@' '@abc@def@@' '@hostname' '@abcdef@@@hostname'" >> $MYSQL_TEST_DIR/var/tmp/t1.TRG +--exec mv $MYSQL_TEST_DIR/var/tmp/t1.TRG $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG + +--echo + +SELECT trigger_name, definer FROM INFORMATION_SCHEMA.TRIGGERS ORDER BY trigger_name; + +--echo + +SELECT * FROM INFORMATION_SCHEMA.TRIGGERS ORDER BY trigger_name; + +# +# Cleanup +# + +--connection default +--echo +--echo ---> connection: default + +DROP USER mysqltest_dfn@localhost; +DROP USER mysqltest_inv@localhost; + +DROP DATABASE mysqltest_db1; diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index cd79eb82ace..f2d9bb6c856 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -13,6 +13,8 @@ drop procedure if exists p1; # Create additional connections used through test connect (addconroot1, localhost, root,,); connect (addconroot2, localhost, root,,); +# Connection without current database set +connect (addconwithoutdb, localhost, root,,*NO-ONE*); connection default; create table t1 (i int); @@ -743,8 +745,12 @@ create trigger t1_ai after insert on t1 for each row insert into t2 values (new.f1+1); create trigger t2_ai after insert on t2 for each row insert into t1 values (new.f2+1); +# Allow SP resursion to be show that it has not influence here +set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth; +set @@max_sp_recursion_depth=100; --error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG insert into t1 values (1); +set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS; select * from t1; select * from t2; drop trigger t1_ai; @@ -875,3 +881,80 @@ drop function f1; drop view v1; drop table t1, t2, t3; --enable_parsing + +# +# Test for bug #13399 "Crash when executing PS/SP which should activate +# trigger which is now dropped". See also test for similar bug for stored +# routines in sp-error.test (#12329). +create table t1 (id int); +create table t2 (id int); +create trigger t1_bi before insert on t1 for each row insert into t2 values (new.id); +prepare stmt1 from "insert into t1 values (10)"; +create procedure p1() insert into t1 values (10); +call p1(); +# Actually it is enough to do FLUSH TABLES instead of DROP TRIGGER +drop trigger t1_bi; +# Server should not crash on these two statements +execute stmt1; +call p1(); +deallocate prepare stmt1; +drop procedure p1; + +# Let us test more complex situation when we alter trigger in such way that +# it uses different set of tables (or simply add new trigger). +create table t3 (id int); +create trigger t1_bi after insert on t1 for each row insert into t2 values (new.id); +prepare stmt1 from "insert into t1 values (10)"; +create procedure p1() insert into t1 values (10); +call p1(); +# Altering trigger forcing it use different set of tables +drop trigger t1_bi; +create trigger t1_bi after insert on t1 for each row insert into t3 values (new.id); +# Until we implement proper mechanism for invalidation of PS/SP when table +# or SP's are changed these two statements will fail with 'Table ... was +# not locked' error (this mechanism should be based on the new TDC). +--error 1100 +execute stmt1; +--error 1100 +call p1(); +deallocate prepare stmt1; +drop procedure p1; +drop table t1, t2, t3; + +# +# BUG#13549 "Server crash with nested stored procedures". +# Server should not crash when during execution of stored procedure +# we have to parse trigger/function definition and this new trigger/ +# function has more local variables declared than invoking stored +# procedure and last of these variables is used in argument of NOT +# operator. +# +create table t1 (a int); +DELIMITER //; +CREATE PROCEDURE `p1`() +begin + insert into t1 values (1); +end// +create trigger trg before insert on t1 for each row +begin + declare done int default 0; + set done= not done; +end// +DELIMITER ;// +CALL p1(); +drop procedure p1; +drop table t1; + +# +# Test for bug #14863 "Triggers: crash if create and there is no current +# database". We should not crash and give proper error when database for +# trigger or its table is not specified and there is no current database. +# +connection addconwithoutdb; +--error ER_NO_DB_ERROR +create trigger t1_bi before insert on test.t1 for each row set @a:=0; +--error ER_NO_DB_ERROR +create trigger test.t1_bi before insert on t1 for each row set @a:=0; +--error ER_NO_DB_ERROR +drop trigger t1_bi; +connection default; diff --git a/mysql-test/t/type_binary.test b/mysql-test/t/type_binary.test index b5928cb14c4..1639aff4711 100644 --- a/mysql-test/t/type_binary.test +++ b/mysql-test/t/type_binary.test @@ -65,3 +65,30 @@ select hex(s1) from t1 where s1=0x0120; select hex(s1) from t1 where s1=0x0100; select count(distinct s1) from t1; drop table t1; + +# check that cast appends trailing zeros +select hex(cast(0x10 as binary(2))); + +# +# Bug #14299: BINARY space truncation should cause warning or error +# +create table t1 (b binary(2), vb varbinary(2)); +insert into t1 values(0x4120, 0x4120); +insert into t1 values(0x412020, 0x412020); +drop table t1; +create table t1 (c char(2), vc varchar(2)); +insert into t1 values(0x4120, 0x4120); +insert into t1 values(0x412020, 0x412020); +drop table t1; + +set @old_sql_mode= @@sql_mode, sql_mode= 'traditional'; +create table t1 (b binary(2), vb varbinary(2)); +insert into t1 values(0x4120, 0x4120); +--error ER_DATA_TOO_LONG +insert into t1 values(0x412020, NULL); +--error ER_DATA_TOO_LONG +insert into t1 values(NULL, 0x412020); +drop table t1; +set @@sql_mode= @old_sql_mode; + +--echo End of 5.0 tests diff --git a/mysql-test/t/type_newdecimal-big.test b/mysql-test/t/type_newdecimal-big.test new file mode 100644 index 00000000000..9a1104e4fe6 --- /dev/null +++ b/mysql-test/t/type_newdecimal-big.test @@ -0,0 +1,50 @@ +--source include/big_test.inc + +--disable_warnings +drop procedure if exists sp1; +--enable_warnings + +# +#-- 2. Adding (one millionth) one million times should be the same as +#-- adding 1. So a stored procedure with many iterations will show if +#-- small errors accumulate. +# + +delimiter //; +# +CREATE PROCEDURE sp1() +BEGIN + DECLARE v1, v2, v3, v4 DECIMAL(28,12); + DECLARE v3_2, v4_2 DECIMAL(28, 12); + DECLARE counter INT; + + SET v1 = 1; + SET v2 = 2; + SET v3 = 1000000000000; + SET v4 = 2000000000000; + SET counter = 0; + + WHILE counter < 100000 DO + SET v1 = v1 + 0.000000000001; + SET v2 = v2 - 0.000000000001; + SET v3 = v3 + 1; + SET v4 = v4 - 1; + SET counter = counter + 1; + END WHILE; + + SET v3_2 = v3 * 0.000000000001; + SET v4_2 = v4 * 0.000000000001; + + SELECT v1, v2, v3, v3_2, v4, v4_2; +END// +# +call sp1()// +#-- should return +# -- v1=1.0000001 +# -- v2=1.999999900000 +# -- v3=1.0000001 +# -- v4=1.999999900000 +# +delimiter ;// +# +drop procedure sp1; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index a7087d46dca..e2fe9767432 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -473,7 +473,7 @@ drop table wl1612_4; # #-- Additional tests for WL#1612 Precision math # -#-- 1. Comparisons should show that a number is +#-- Comparisons should show that a number is #-- exactly equal to its value as displayed. # set sql_mode=''; @@ -487,34 +487,9 @@ select 18.3=18.3; select -18.3=18.3; # select 0.8 = 0.7 + 0.1; + # -#-- 2. Adding (one millionth) one million times should be the same as -#-- adding 1. So a stored procedure with many iterations will show if -#-- small errors accumulate. -# -#drop procedure p1; -# -delimiter //; -# -create procedure p1 () begin - declare v1, v2, v3, v4 decimal(16,12); declare v5 int; - set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; - while v5 < 100000 do - set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; - end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;// -# -call p1()// -#-- should return -# -- v1=1.0000001 -# -- v2=1.999999900000 -# -- v3=1.0000001 -# -- v4=1.999999900000 -# -delimiter ;// -# -drop procedure p1; -# -#-- 3. It should be possible to define a column +#-- It should be possible to define a column #-- with up to 38 digits precision either before #-- or after the decimal point. Any number which #-- is inserted, if it's within the range, should @@ -565,7 +540,7 @@ select * from t1; # drop table t1; # -#-- 4. The usual arithmetic operators / * + - should work. +#-- The usual arithmetic operators / * + - should work. # #select 77777777777777777777777777777777777777 / 7777777777777777777777777777777777777 = 10; #-- should return 0 (false). @@ -668,7 +643,7 @@ select truncate(99999999999999999999999999999999999999,-31); #drop procedure p1; #drop table t1; # -#-- 7. When I say DECIMAL(x) I should be able to store x digits. +#-- When I say DECIMAL(x) I should be able to store x digits. #-- If I can't, there should be an error at CREATE time. # #drop table if exists t1; @@ -676,7 +651,8 @@ select truncate(99999999999999999999999999999999999999,-31); #create table t1 (col1 decimal(254)); #-- should return SQLSTATE 22003 numeric value out of range # -#-- 8. When I say DECIMAL(x,y) there should be no silent change of precision or scale. +#-- When I say DECIMAL(x,y) there should be no silent change of precision or +#-- scale. # #drop table if exists t1; # @@ -694,7 +670,7 @@ select truncate(99999999999999999999999999999999999999,-31); # #drop table t1; # -#-- 9. From WL#1612 "The future" point 2.: +#-- From WL#1612 "The future" point 2.: #-- The standard requires that we treat numbers like "0.5" as #-- DECIMAL or NUMERIC, not as floating-point. # @@ -715,7 +691,7 @@ show create table t1; # drop table t1; # -#-- 10. From WL#1612, "The future", point 3.: We have to start rounding correctly. +#-- From WL#1612, "The future", point 3.: We have to start rounding correctly. # select round(1.5),round(2.5); #-- should return: @@ -725,13 +701,13 @@ select round(1.5),round(2.5); #| 2 | 3 | #+------------+------------+ # -#-- 11. From WL#1612, "The future", point 4.: "select 0.07 * 0.07;" should return 0.0049, not 0.00. +#-- From WL#1612, "The future", point 4.: "select 0.07 * 0.07;" should return 0.0049, not 0.00. #-- If operand#1 has scale X and operand#2 has scale Y, then result should have scale (X+Y). # select 0.07 * 0.07; #-- should return 0.0049 # -#-- 12. From WL#1612, "The future", point 5.: Division by zero is an error. +#-- From WL#1612, "The future", point 5.: Division by zero is an error. # set sql_mode='traditional'; # @@ -752,7 +728,7 @@ select 1 / 0; #+-------+ #1 row in set, 1 warning (0.00 sec) # -#-- 13. From WL#1612 "The future" point 6.: Overflow is an error. +#-- From WL#1612 "The future" point 6.: Overflow is an error. # #set sql_mode=''; # @@ -793,7 +769,8 @@ select 1 / 0; #drop table t2; #drop table t1; # -#-- 15. From WL#1612 "The future" point 8.: Stop storing leading "+" signs and leading "0"s. +#-- From WL#1612 "The future" point 8.: Stop storing leading "+" signs and +# leading "0"s. # #drop table if exists t1; # @@ -805,7 +782,7 @@ select 1 / 0; # #drop table t1; # -#-- 16. From WL#1612, The future" point 9.: +#-- From WL#1612, The future" point 9.: #-- Accept the data type and precision and scale as the user #-- asks, or return an error, but don't change to something else. # @@ -817,7 +794,7 @@ select 1 / 0; # #drop table t1; # -#-- 17. The scripts in the following bugs should work: +#-- The scripts in the following bugs should work: # #BUG#559 Maximum precision for DECIMAL column ... @@ -833,7 +810,7 @@ select 1 / 0; #BUG#6048 Stored procedure causes operating system reboot #BUG#6053 DOUBLE PRECISION literal --- 18. Tests from 'traditional' mode tests +-- Tests from 'traditional' mode tests # set sql_mode='ansi,traditional'; # @@ -1050,3 +1027,61 @@ select cast(@non_existing_user_var/2 as DECIMAL); # --error 1427 create table t (d decimal(0,10)); + +# +# Bug #14268 (bad FLOAT->DECIMAL conversion) +# + +CREATE TABLE t1 ( + my_float FLOAT, + my_double DOUBLE, + my_varchar VARCHAR(50), + my_decimal DECIMAL(65,30) +); +SHOW CREATE TABLE t1; + +let $max_power= 32; +while ($max_power) +{ + eval INSERT INTO t1 SET my_float = 1.175494345e-$max_power, + my_double = 1.175494345e-$max_power, + my_varchar = '1.175494345e-$max_power'; + dec $max_power; +} +SELECT my_float, my_double, my_varchar FROM t1; + +SELECT CAST(my_float AS DECIMAL(65,30)), my_float FROM t1; +SELECT CAST(my_double AS DECIMAL(65,30)), my_double FROM t1; +SELECT CAST(my_varchar AS DECIMAL(65,30)), my_varchar FROM t1; + +# We have to disable warnings here as the test in +# Field_new_decimal::store(double): +# if (nr2 != nr) +# fails randomly depending on compiler options + +--disable_warnings +UPDATE t1 SET my_decimal = my_float; +SELECT my_decimal, my_float FROM t1; +UPDATE t1 SET my_decimal = my_double; +SELECT my_decimal, my_double FROM t1; +--enable_warnings +UPDATE t1 SET my_decimal = my_varchar; +SELECT my_decimal, my_varchar FROM t1; + +DROP TABLE t1; + +# +# Bug #13573 (Wrong data inserted for too big values) +# + +create table t1 (c1 decimal(64)); +--disable_ps_protocol +insert into t1 values( +89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000); +insert into t1 values( +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 * +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); +--enable_ps_protocol +insert into t1 values(1e100); +select * from t1; +drop table t1; diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test index 7ae3f65f7cc..9abfe914335 100644 --- a/mysql-test/t/type_time.test +++ b/mysql-test/t/type_time.test @@ -21,4 +21,18 @@ select t, time_to_sec(t),sec_to_time(time_to_sec(t)) from t1; select sec_to_time(time_to_sec(t)) from t1; drop table t1; +# +# BUG #12440: Incorrect processing of time values containing +# long fraction part and/or large exponent part. +# +# These must return normal result: +SELECT CAST(235959.123456 AS TIME); +SELECT CAST(0.235959123456e+6 AS TIME); +SELECT CAST(235959123456e-6 AS TIME); +# These must cut fraction part and produce warning: +SELECT CAST(235959.1234567 AS TIME); +SELECT CAST(0.2359591234567e6 AS TIME); +# This must return NULL and produce warning: +SELECT CAST(0.2359591234567e+30 AS TIME); + # End of 4.1 tests diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index daa83ef0fa4..6de90dd446d 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -753,6 +753,24 @@ create table t2 select a from t1 union select b from t1; show columns from t2; drop table t2, t1; +# +# Bug #14216: UNION + DECIMAL wrong values in result +# +create table t1 (f1 decimal(60,25), f2 decimal(60,25)); +insert into t1 values (0.0,0.0); +select f1 from t1 union all select f2 from t1; +select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 +union all +select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; +drop table t1; +create table t1 (f1 decimal(60,24), f2 decimal(60,24)); +insert into t1 values (0.0,0.0); +select f1 from t1 union all select f2 from t1; +select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 +union all +select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; +drop table t1; + # # Test that union with VARCHAR produces dynamic row tables # diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 13ced76079f..d0496b48c7a 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -228,15 +228,16 @@ delete from t1 where count(*)=1; drop table t1; # BUG#12915: Optimize "DELETE|UPDATE ... ORDER BY ... LIMIT n" to use an index -create table t1 ( a int, index (a) ); -insert into t1 values (0),(0),(0),(0),(0),(0),(0),(0); +create table t1 ( a int, b int default 0, index (a) ); +insert into t1 (a) values (0),(0),(0),(0),(0),(0),(0),(0); flush status; select a from t1 order by a limit 1; show status like 'handler_read%'; flush status; -update t1 set a=unix_timestamp() order by a limit 1; +update t1 set a=9999 order by a limit 1; +update t1 set b=9999 order by a limit 1; show status like 'handler_read%'; flush status; @@ -253,7 +254,37 @@ flush status; delete from t1 order by a limit 1; show status like 'handler_read%'; -select count(*) from t1; +select * from t1; +update t1 set a=a+10,b=1 order by a limit 3; +update t1 set a=a+11,b=2 order by a limit 3; +update t1 set a=a+12,b=3 order by a limit 3; +select * from t1 order by a; drop table t1; + +# +# Bug#14186 select datefield is null not updated +# +create table t1 (f1 date not null); +insert into t1 values('2000-01-01'),('0000-00-00'); +update t1 set f1='2002-02-02' where f1 is null; +select * from t1; +drop table t1; + +# +# Bug#15028 Multitable update returns different numbers of matched rows +# depending on table order +create table t1 (f1 int); +create table t2 (f2 int); +insert into t1 values(1),(2); +insert into t2 values(1),(1); +--enable_info +update t1,t2 set f1=3,f2=3 where f1=f2 and f1=1; +--disable_info +update t2 set f2=1; +update t1 set f1=1 where f1=3; +--enable_info +update t2,t1 set f1=3,f2=3 where f1=f2 and f1=1; +--disable_info +drop table t1,t2; # End of 4.1 tests diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index e3b5b4ef33e..61861c26ea8 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -70,6 +70,10 @@ create table t1 (i int not null); insert t1 values (1),(2),(2),(3),(3),(3); select @a:=0; select @a, @a:=@a+count(*), count(*), @a from t1 group by i; select @a:=0; select @a+0, @a:=@a+0+count(*), count(*), @a+0 from t1 group by i; + +set @a=0; +select @a,@a:="hello",@a,@a:=3,@a,@a:="hello again" from t1 group by i; +select @a,@a:="hello",@a,@a:=3,@a,@a:="hello again" from t1 group by i; drop table t1; # diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index f23cc0152c1..2d0e2dbc9c9 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -237,6 +237,10 @@ set global rpl_recovery_rank=100; set global server_id=100; set global slow_launch_time=100; set sort_buffer_size=100; +set @@max_sp_recursion_depth=10; +select @@max_sp_recursion_depth; +set @@max_sp_recursion_depth=0; +select @@max_sp_recursion_depth; set sql_auto_is_null=1; select @@sql_auto_is_null; set @@sql_auto_is_null=0; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index dd773c4c650..db6c12fdacb 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1,5 +1,5 @@ --disable_warnings -drop table if exists t1,t2,t9,`t1a``b`,v1,v2,v3,v4,v5,v6; +drop table if exists t1,t2,t3,t4,t9,`t1a``b`,v1,v2,v3,v4,v5,v6; drop view if exists t1,t2,`t1a``b`,v1,v2,v3,v4,v5,v6; drop database if exists mysqltest; --enable_warnings @@ -147,11 +147,9 @@ insert into t1 values (1), (2), (3); create view v1 (a) as select a+1 from t1; create view v2 (a) as select a-1 from t1; ---disable_parsing # WL #2486 should enable these tests select * from t1 natural left join v1; select * from v2 natural left join t1; select * from v2 natural left join v1; ---enable_parsing drop view v1, v2; drop table t1; @@ -1746,7 +1744,6 @@ drop function f1; CHECK TABLE v1, v2, v3, v4, v5, v6; create function f1 () returns int return (select max(col1) from t1); DROP TABLE t1; -# following will show underlying table until BUG#11555 fix CHECK TABLE v1, v2, v3, v4, v5, v6; drop function f1; drop function f2; @@ -2081,8 +2078,8 @@ drop table t1, t2; # # DEFINER information check # --- error ER_NO_VIEW_USER -create definer=some_user@__% sql security invoker view v1 as select 1; +-- error ER_MALFORMED_DEFINER +create definer=some_user@`` sql security invoker view v1 as select 1; create definer=some_user@localhost sql security invoker view v1 as select 1; show create view v1; drop view v1; @@ -2189,4 +2186,156 @@ EXPLAIN SELECT * FROM v2 WHERE a=1; DROP VIEW v1,v2; DROP TABLE t1,t2,t3; +# +# Bug #13622 Wrong view .frm created if some field's alias contain \n +# +create table t1 (f1 int); +create view v1 as select t1.f1 as '123 +456' from t1; +select * from v1; +drop view v1; +drop table t1; + +# Bug #14466 lost sort order in GROUP_CONCAT() in a view +# +create table t1 (f1 int, f2 int); +insert into t1 values(1,1),(1,2),(1,3); +create view v1 as select f1 ,group_concat(f2 order by f2 asc) from t1 group by f1; +create view v2 as select f1 ,group_concat(f2 order by f2 desc) from t1 group by f1; +select * from v1; +select * from v2; +drop view v1,v2; +drop table t1; + +# +# BUG#14026 Crash on second PS execution when using views +# +create table t1 (x int, y int); +create table t2 (x int, y int, z int); +create table t3 (x int, y int, z int); +create table t4 (x int, y int, z int); + +create view v1 as +select t1.x +from ( + (t1 join t2 on ((t1.y = t2.y))) + join + (t3 left join t4 on (t3.y = t4.y) and (t3.z = t4.z)) +); + +prepare stmt1 from "select count(*) from v1 where x = ?"; +set @parm1=1; + +execute stmt1 using @parm1; +execute stmt1 using @parm1; +drop view v1; +drop table t1,t2,t3,t4; +# +# Bug #14540: OPTIMIZE, ANALYZE, REPAIR applied to not a view +# + +CREATE TABLE t1(id INT); +CREATE VIEW v1 AS SELECT id FROM t1; + +OPTIMIZE TABLE v1; +ANALYZE TABLE v1; +REPAIR TABLE v1; + +DROP TABLE t1; +OPTIMIZE TABLE v1; + +DROP VIEW v1; + + +# +# BUG#14719: Views DEFINER grammar is incorrect +# + +create definer = current_user() sql security invoker view v1 as select 1; +show create view v1; +drop view v1; + +create definer = current_user sql security invoker view v1 as select 1; +show create view v1; +drop view v1; + +# +# Bug #14816 test_if_order_by_key() expected only Item_fields. +# +create table t1 (id INT, primary key(id)); +insert into t1 values (1),(2); +create view v1 as select * from t1; +explain select id from v1 order by id; +drop view v1; +drop table t1; + +# +# Bug #14850 Item_ref's values wasn't updated +# +create table t1(f1 int, f2 int); +insert into t1 values (null, 10), (null,2); +select f1, sum(f2) from t1 group by f1; +create view v1 as select * from t1; +select f1, sum(f2) from v1 group by f1; +drop view v1; +drop table t1; + +# +# BUG#14885: incorrect SOURCE in view created in a procedure +# TODO: here SOURCE string must be shown when it will be possible +# +--disable_warnings +drop procedure if exists p1; +--enable_warnings +delimiter //; +create procedure p1 () deterministic +begin +create view v1 as select 1; +end; +// +delimiter ;// +call p1(); +show create view v1; +drop view v1; +drop procedure p1; + +# +# BUG#15096: using function with view for view creation +# +CREATE VIEW v1 AS SELECT 42 AS Meaning; +--disable_warnings +DROP FUNCTION IF EXISTS f1; +--enable_warnings +DELIMITER //; +CREATE FUNCTION f1() RETURNS INTEGER +BEGIN + DECLARE retn INTEGER; + SELECT Meaning FROM v1 INTO retn; + RETURN retn; +END +// +DELIMITER ;// +CREATE VIEW v2 AS SELECT f1(); +select * from v2; +drop view v2,v1; +drop function f1; + +# +# Bug#14861: aliased column names are not preserved. +# +create table t1 (id numeric, warehouse_id numeric); +create view v1 as select id from t1; +create view v2 as +select t1.warehouse_id, v1.id as receipt_id +from t1, v1 where t1.id = v1.id; + +insert into t1 (id, warehouse_id) values(3, 2); +insert into t1 (id, warehouse_id) values(4, 2); +insert into t1 (id, warehouse_id) values(5, 1); + +select v2.receipt_id as alias1, v2.receipt_id as alias2 from v2 +order by v2.receipt_id; + +drop view v2, v1; +drop table t1; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index ea93345e894..04d6d2f323b 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -24,7 +24,7 @@ grant create view,select on test.* to mysqltest_1@localhost; connect (user1,localhost,mysqltest_1,,test); connection user1; --- error ER_VIEW_OTHER_USER +-- error ER_SPECIFIC_ACCESS_DENIED create definer=root@localhost view v1 as select * from mysqltest.t1; create view v1 as select * from mysqltest.t1; # try to modify view without DROP privilege on it @@ -401,8 +401,302 @@ grant all privileges on mysqltest.* to mysqltest_1@localhost; connection user1; use mysqltest; create view v1 as select * from t1; +use test; connection root; revoke all privileges on mysqltest.* from mysqltest_1@localhost; drop database mysqltest; +# +# view definer grants revoking +# +connection root; +--disable_warnings +create database mysqltest; +--enable_warnings + +create table mysqltest.t1 (a int, b int); + +grant select on mysqltest.t1 to mysqltest_1@localhost; +grant create view,select on test.* to mysqltest_1@localhost; + +connection user1; + +create view v1 as select * from mysqltest.t1; + +connection root; +# check view definer information +show create view v1; +revoke select on mysqltest.t1 from mysqltest_1@localhost; +-- error ER_VIEW_INVALID +select * from v1; +grant select on mysqltest.t1 to mysqltest_1@localhost; +select * from v1; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; +drop view v1; +drop database mysqltest; + +# +# rights on execution of view underlying functiond (BUG#9505) +# +connection root; +--disable_warnings +create database mysqltest; +--enable_warnings + +use mysqltest; +create table t1 (a int); +insert into t1 values (1); +create table t2 (s1 int); +--disable_warnings +drop function if exists f2; +--enable_warnings +delimiter //; +create function f2 () returns int begin declare v int; select s1 from t2 +into v; return v; end// +delimiter ;// +create algorithm=TEMPTABLE view v1 as select f2() from t1; +create algorithm=MERGE view v2 as select f2() from t1; +create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select f2() from t1; +create algorithm=MERGE SQL SECURITY INVOKER view v4 as select f2() from t1; +create SQL SECURITY INVOKER view v5 as select * from v4; +grant select on v1 to mysqltest_1@localhost; +grant select on v2 to mysqltest_1@localhost; +grant select on v3 to mysqltest_1@localhost; +grant select on v4 to mysqltest_1@localhost; +grant select on v5 to mysqltest_1@localhost; + +connection user1; +use mysqltest; +select * from v1; +select * from v2; +-- error ER_VIEW_INVALID +select * from v3; +-- error ER_VIEW_INVALID +select * from v4; +-- error ER_VIEW_INVALID +select * from v5; +use test; + +connection root; +drop view v1, v2, v3, v4, v5; +drop function f2; +drop table t1, t2; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; +drop database mysqltest; + +# +# revertion of previous test, definer of view lost his/her rights to execute +# function +# + +connection root; +--disable_warnings +create database mysqltest; +--enable_warnings + +use mysqltest; +create table t1 (a int); +insert into t1 values (1); +create table t2 (s1 int); +--disable_warnings +drop function if exists f2; +--enable_warnings +delimiter //; +create function f2 () returns int begin declare v int; select s1 from t2 +into v; return v; end// +delimiter ;// +grant select on t1 to mysqltest_1@localhost; +grant execute on function f2 to mysqltest_1@localhost; +grant create view on mysqltest.* to mysqltest_1@localhost; + +connection user1; +use mysqltest; +create algorithm=TEMPTABLE view v1 as select f2() from t1; +create algorithm=MERGE view v2 as select f2() from t1; +create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select f2() from t1; +create algorithm=MERGE SQL SECURITY INVOKER view v4 as select f2() from t1; +use test; + +connection root; +create view v5 as select * from v1; +revoke execute on function f2 from mysqltest_1@localhost; +-- error ER_VIEW_INVALID +select * from v1; +-- error ER_VIEW_INVALID +select * from v2; +select * from v3; +select * from v4; +-- error ER_VIEW_INVALID +select * from v5; + +drop view v1, v2, v3, v4, v5; +drop function f2; +drop table t1, t2; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; +drop database mysqltest; + +# +# definer/invoker rights for columns +# +connection root; +--disable_warnings +create database mysqltest; +--enable_warnings + +use mysqltest; +create table t1 (a int); +create table v1 (a int); +insert into t1 values (1); +grant select on t1 to mysqltest_1@localhost; +grant select on v1 to mysqltest_1@localhost; +grant create view on mysqltest.* to mysqltest_1@localhost; +drop table v1; + +connection user1; +use mysqltest; +create algorithm=TEMPTABLE view v1 as select *, a as b from t1; +create algorithm=MERGE view v2 as select *, a as b from t1; +create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select *, a as b from t1; +create algorithm=MERGE SQL SECURITY INVOKER view v4 as select *, a as b from t1; +create view v5 as select * from v1; +use test; + +connection root; +revoke select on t1 from mysqltest_1@localhost; +-- error ER_VIEW_INVALID +select * from v1; +-- error ER_VIEW_INVALID +select * from v2; +select * from v3; +select * from v4; +-- error ER_VIEW_INVALID +select * from v5; + +#drop view v1, v2, v3, v4, v5; +drop table t1; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; +drop database mysqltest; + + +connection root; +--disable_warnings +create database mysqltest; +--enable_warnings + +use mysqltest; +create table t1 (a int); +insert into t1 values (1); +create algorithm=TEMPTABLE view v1 as select *, a as b from t1; +create algorithm=MERGE view v2 as select *, a as b from t1; +create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select *, a as b from t1; +create algorithm=MERGE SQL SECURITY INVOKER view v4 as select *, a as b from t1; +create SQL SECURITY INVOKER view v5 as select * from v4; +grant select on v1 to mysqltest_1@localhost; +grant select on v2 to mysqltest_1@localhost; +grant select on v3 to mysqltest_1@localhost; +grant select on v4 to mysqltest_1@localhost; +grant select on v5 to mysqltest_1@localhost; + +connection user1; +use mysqltest; +select * from v1; +select * from v2; +-- error ER_VIEW_INVALID +select * from v3; +-- error ER_VIEW_INVALID +select * from v4; +-- error ER_VIEW_INVALID +select * from v5; +use test; + +connection root; +drop view v1, v2, v3, v4, v5; +drop table t1; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; +drop database mysqltest; + +# +# BUG#14256: definer in view definition is not fully qualified +# +--disable_warnings +drop view if exists v1; +--enable_warnings + +# Backup anonymous users and remove them. (They get in the way of +# the one we test with here otherwise.) +create table t1 as select * from mysql.user where user=''; +delete from mysql.user where user=''; +flush privileges; + +# Create the test user +grant all on test.* to 'test14256'@'%'; + +connect (test14256,localhost,test14256,,test); +connection test14256; +use test; + +create view v1 as select 42; +show create view v1; + +select definer into @v1def1 from information_schema.views + where table_schema = 'test' and table_name='v1'; +drop view v1; + +create definer=`test14256`@`%` view v1 as select 42; +show create view v1; + +select definer into @v1def2 from information_schema.views + where table_schema = 'test' and table_name='v1'; +drop view v1; + +select @v1def1, @v1def2, @v1def1=@v1def2; + +connection root; +drop user test14256; + +# Restore the anonymous users. +insert into mysql.user select * from t1; +flush privileges; + +drop table t1; + +# +# BUG#14726: freeing stack variable in case of an error of opening +# a view when we have locked tables with LOCK TABLES statement. +# +connection root; +--disable_warnings +create database mysqltest; +--enable_warnings + +use mysqltest; +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT * FROM t1; +SHOW CREATE VIEW v1; +GRANT SELECT, LOCK TABLES ON mysqltest.* TO mysqltest_1@localhost; + +connection user1; + +use mysqltest; +LOCK TABLES v1 READ; +-- error ER_TABLEACCESS_DENIED_ERROR +SHOW CREATE TABLE v1; +UNLOCK TABLES; +use test; + +connection root; +use test; +drop user mysqltest_1@localhost; +drop database mysqltest; + +# +# switch to default connaction +# +disconnect user1; +disconnect root; +connection default; diff --git a/mysql-test/t/view_query_cache.test b/mysql-test/t/view_query_cache.test index 81994407641..d4ebe45b7ac 100644 --- a/mysql-test/t/view_query_cache.test +++ b/mysql-test/t/view_query_cache.test @@ -96,4 +96,35 @@ unlock tables; set query_cache_wlock_invalidate=default; drop view v1; drop table t1; + +# +# BUG#15119: returning temptable view from the query cache. +# +flush status; +create table t1 (a int, b int); +create algorithm=temptable view v1 as select * from t1; +select * from v1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +select * from v1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +insert into t1 values (1,1); +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +select * from v1; +select * from v1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +drop view v1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +drop table t1; + +# Reset default environment. set GLOBAL query_cache_size=default; diff --git a/mysys/base64.c b/mysys/base64.c index 0fcd6f096f5..b29c8ff8360 100644 --- a/mysys/base64.c +++ b/mysys/base64.c @@ -15,7 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <base64.h> -#include <m_string.h> // strchr() +#include <m_string.h> /* strchr() */ #ifndef MAIN @@ -27,9 +27,13 @@ static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" int base64_needed_encoded_length(int length_of_data) { - return ceil(length_of_data * 4 / 3) /* base64 chars */ + - ceil(length_of_data / (76 * 3 / 4)) /* Newlines */ + - 3 /* Padding */; + int nb_base64_chars; + nb_base64_chars= (length_of_data + 2) / 3 * 4; + + return + nb_base64_chars + /* base64 char incl padding */ + (nb_base64_chars - 1)/ 76 + /* newlines */ + 1; /* NUL termination of string */ } @@ -89,6 +93,7 @@ base64_encode(const void *src, size_t src_len, char *dst) else *dst++= base64_table[(c >> 0) & 0x3f]; } + *dst= '\0'; return 0; } @@ -129,7 +134,8 @@ base64_decode(const char *src, size_t size, void *dst) { char b[3]; size_t i= 0; - void *d= dst; + char *dst_base= (char *)dst; + char *d= dst_base; size_t j; while (i < size) @@ -181,14 +187,14 @@ base64_decode(const char *src, size_t size, void *dst) b[2]= (c >> 0) & 0xff; for (j=0; j<3-mark; j++) - *(char *)d++= b[j]; + *d++= b[j]; } if (i != size) { return -1; } - return d - dst; + return d - dst_base; } @@ -209,6 +215,7 @@ main(void) size_t j; size_t k, l; size_t dst_len; + size_t needed_length; for (i= 0; i < 500; i++) { @@ -227,8 +234,12 @@ main(void) } /* Encode */ - str= (char *) malloc(base64_needed_encoded_length(src_len)); + needed_length= base64_needed_encoded_length(src_len); + str= (char *) malloc(needed_length); + for (k= 0; k < needed_length; k++) + str[k]= 0xff; /* Fill memory to check correct NUL termination */ require(base64_encode(src, src_len, str) == 0); + require(needed_length == strlen(str) + 1); /* Decode */ dst= (char *) malloc(base64_needed_decoded_length(strlen(str))); diff --git a/mysys/charset-def.c b/mysys/charset-def.c index 5b30d1ee135..0559fe59d06 100644 --- a/mysys/charset-def.c +++ b/mysys/charset-def.c @@ -43,6 +43,7 @@ extern CHARSET_INFO my_charset_ucs2_spanish2_uca_ci; extern CHARSET_INFO my_charset_ucs2_roman_uca_ci; extern CHARSET_INFO my_charset_ucs2_persian_uca_ci; extern CHARSET_INFO my_charset_ucs2_esperanto_uca_ci; +extern CHARSET_INFO my_charset_ucs2_hungarian_uca_ci; #endif #ifdef HAVE_CHARSET_utf8 @@ -64,6 +65,7 @@ extern CHARSET_INFO my_charset_utf8_spanish2_uca_ci; extern CHARSET_INFO my_charset_utf8_roman_uca_ci; extern CHARSET_INFO my_charset_utf8_persian_uca_ci; extern CHARSET_INFO my_charset_utf8_esperanto_uca_ci; +extern CHARSET_INFO my_charset_utf8_hungarian_uca_ci; #ifdef HAVE_UTF8_GENERAL_CS extern CHARSET_INFO my_charset_utf8_general_cs; #endif @@ -151,6 +153,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_ucs2_roman_uca_ci); add_compiled_collation(&my_charset_ucs2_persian_uca_ci); add_compiled_collation(&my_charset_ucs2_esperanto_uca_ci); + add_compiled_collation(&my_charset_ucs2_hungarian_uca_ci); #endif #endif @@ -184,6 +187,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_utf8_roman_uca_ci); add_compiled_collation(&my_charset_utf8_persian_uca_ci); add_compiled_collation(&my_charset_utf8_esperanto_uca_ci); + add_compiled_collation(&my_charset_utf8_hungarian_uca_ci); #endif #endif diff --git a/mysys/hash.c b/mysys/hash.c index 45cf7d5ff1d..99479ef6769 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -36,9 +36,10 @@ typedef struct st_hash_info { static uint hash_mask(uint hashnr,uint buffmax,uint maxlength); static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); -static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length); +static int hashcmp(const HASH *hash, HASH_LINK *pos, const byte *key, + uint length); -static uint calc_hash(HASH *hash,const byte *key,uint length) +static uint calc_hash(const HASH *hash, const byte *key, uint length) { ulong nr1=1, nr2=4; hash->charset->coll->hash_sort(hash->charset,(uchar*) key,length,&nr1,&nr2); @@ -63,7 +64,6 @@ _hash_init(HASH *hash,CHARSET_INFO *charset, hash->key_offset=key_offset; hash->key_length=key_length; hash->blength=1; - hash->current_record= NO_RECORD; /* For the future */ hash->get_key=get_key; hash->free=free_element; hash->flags=flags; @@ -135,7 +135,6 @@ void my_hash_reset(HASH *hash) reset_dynamic(&hash->array); /* Set row pointers so that the hash can be reused at once */ hash->blength= 1; - hash->current_record= NO_RECORD; DBUG_VOID_RETURN; } @@ -147,7 +146,8 @@ void my_hash_reset(HASH *hash) */ static inline char* -hash_key(HASH *hash,const byte *record,uint *length,my_bool first) +hash_key(const HASH *hash, const byte *record, uint *length, + my_bool first) { if (hash->get_key) return (*hash->get_key)(record,length,first); @@ -163,8 +163,8 @@ static uint hash_mask(uint hashnr,uint buffmax,uint maxlength) return (hashnr & ((buffmax >> 1) -1)); } -static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax, - uint maxlength) +static uint hash_rec_mask(const HASH *hash, HASH_LINK *pos, + uint buffmax, uint maxlength) { uint length; byte *key= (byte*) hash_key(hash,pos->data,&length,0); @@ -186,14 +186,25 @@ unsigned int rec_hashnr(HASH *hash,const byte *record) } - /* Search after a record based on a key */ - /* Sets info->current_ptr to found record */ +gptr hash_search(const HASH *hash, const byte *key, uint length) +{ + HASH_SEARCH_STATE state; + return hash_first(hash, key, length, &state); +} + +/* + Search after a record based on a key + + NOTE + Assigns the number of the found record to HASH_SEARCH_STATE state +*/ -gptr hash_search(HASH *hash,const byte *key,uint length) +gptr hash_first(const HASH *hash, const byte *key, uint length, + HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; uint flag,idx; - DBUG_ENTER("hash_search"); + DBUG_ENTER("hash_first"); flag=1; if (hash->records) @@ -206,7 +217,7 @@ gptr hash_search(HASH *hash,const byte *key,uint length) if (!hashcmp(hash,pos,key,length)) { DBUG_PRINT("exit",("found key at %d",idx)); - hash->current_record= idx; + *current_record= idx; DBUG_RETURN (pos->data); } if (flag) @@ -218,31 +229,32 @@ gptr hash_search(HASH *hash,const byte *key,uint length) } while ((idx=pos->next) != NO_RECORD); } - hash->current_record= NO_RECORD; + *current_record= NO_RECORD; DBUG_RETURN(0); } /* Get next record with identical key */ /* Can only be called if previous calls was hash_search */ -gptr hash_next(HASH *hash,const byte *key,uint length) +gptr hash_next(const HASH *hash, const byte *key, uint length, + HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; uint idx; - if (hash->current_record != NO_RECORD) + if (*current_record != NO_RECORD) { HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*); - for (idx=data[hash->current_record].next; idx != NO_RECORD ; idx=pos->next) + for (idx=data[*current_record].next; idx != NO_RECORD ; idx=pos->next) { pos=data+idx; if (!hashcmp(hash,pos,key,length)) { - hash->current_record= idx; + *current_record= idx; return pos->data; } } - hash->current_record=NO_RECORD; + *current_record= NO_RECORD; } return 0; } @@ -281,7 +293,8 @@ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink) != 0 key of record != key */ -static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) +static int hashcmp(const HASH *hash, HASH_LINK *pos, const byte *key, + uint length) { uint rec_keylength; byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1); @@ -307,7 +320,6 @@ my_bool my_hash_insert(HASH *info,const byte *record) if (!(empty=(HASH_LINK*) alloc_dynamic(&info->array))) return(TRUE); /* No more memory */ - info->current_record= NO_RECORD; data=dynamic_element(&info->array,0,HASH_LINK*); halfbuff= info->blength >> 1; @@ -450,7 +462,6 @@ my_bool hash_delete(HASH *hash,byte *record) } if ( --(hash->records) < hash->blength >> 1) hash->blength>>=1; - hash->current_record= NO_RECORD; lastpos=data+hash->records; /* Remove link to record */ @@ -543,7 +554,6 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length) if ((idx=pos->next) == NO_RECORD) DBUG_RETURN(1); /* Not found in links */ } - hash->current_record= NO_RECORD; org_link= *pos; empty=idx; @@ -593,10 +603,10 @@ byte *hash_element(HASH *hash,uint idx) isn't changed */ -void hash_replace(HASH *hash, uint idx, byte *new_row) +void hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record, byte *new_row) { - if (idx != NO_RECORD) /* Safety */ - dynamic_element(&hash->array,idx,HASH_LINK*)->data=new_row; + if (*current_record != NO_RECORD) /* Safety */ + dynamic_element(&hash->array, *current_record, HASH_LINK*)->data= new_row; } diff --git a/mysys/my_copy.c b/mysys/my_copy.c index 072492172e3..2fb022a25f2 100644 --- a/mysys/my_copy.c +++ b/mysys/my_copy.c @@ -53,7 +53,7 @@ struct utimbuf { int my_copy(const char *from, const char *to, myf MyFlags) { uint Count; - my_bool new_file_stat; /* 1 if we could stat "to" */ + my_bool new_file_stat= 0; /* 1 if we could stat "to" */ int create_flag; File from_file,to_file; char buff[IO_SIZE]; @@ -62,7 +62,6 @@ int my_copy(const char *from, const char *to, myf MyFlags) DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); from_file=to_file= -1; - LINT_INIT(new_file_stat); DBUG_ASSERT(!(MyFlags & (MY_FNABP | MY_NABP))); /* for my_read/my_write */ if (MyFlags & MY_HOLD_ORIGINAL_MODES) /* Copy stat if possible */ new_file_stat= test(my_stat((char*) to, &new_stat_buff, MYF(0))); diff --git a/mysys/my_create.c b/mysys/my_create.c index 5fa97a9ca78..a85417c7701 100644 --- a/mysys/my_create.c +++ b/mysys/my_create.c @@ -47,13 +47,16 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, #elif defined(VMS) fd = open((my_string) FileName, access_flags | O_CREAT, 0, "ctx=stm","ctx=bin"); -#elif defined(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2) +#elif defined(MSDOS) || defined(__EMX__) || defined(OS2) if (access_flags & O_SHARE) fd = sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY, SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); else fd = open((my_string) FileName, access_flags | O_CREAT | O_BINARY, MY_S_IREAD | MY_S_IWRITE); +#elif defined(__WIN__) + fd= my_sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY, + SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); #else fd = open(FileName, access_flags); #endif diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 31ef21632b9..95dc5afeae9 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -723,10 +723,10 @@ static longlong getopt_ll(char *arg, const struct my_option *optp, int *err) ulonglong block_size= (optp->block_size ? (ulonglong) optp->block_size : 1L); num= eval_num_suffix(arg, err, (char*) optp->name); - if (num > 0 && (ulonglong) num > (ulonglong) (ulong) optp->max_value && + if (num > 0 && (ulonglong) num > (ulonglong) optp->max_value && optp->max_value) /* if max value is not set -> no upper limit */ - num= (longlong) (ulong) optp->max_value; - num= ((num - (longlong) optp->sub_size) / block_size); + num= (ulonglong) optp->max_value; + num= ((num - optp->sub_size) / block_size); num= (longlong) (num * block_size); return max(num, optp->min_value); } diff --git a/mysys/my_handler.c b/mysys/my_handler.c index e14bd7529f9..56f2298a9f0 100644 --- a/mysys/my_handler.c +++ b/mysys/my_handler.c @@ -75,7 +75,7 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length, SYNOPSIS ha_key_cmp() - keyseg Key segments of key to compare + keyseg Array of key segments of key to compare a First key to compare, in format from _mi_pack_key() This is normally key specified by user b Second key to compare. This is always from a row @@ -84,10 +84,26 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length, next_flag How keys should be compared If bit SEARCH_FIND is not set the keys includes the row position and this should also be compared + diff_pos OUT Number of first keypart where values differ, counting + from one. + diff_pos[1] OUT (b + diff_pos[1]) points to first value in tuple b + that is different from corresponding value in tuple a. + + EXAMPLES + Example1: if the function is called for tuples + ('aaa','bbb') and ('eee','fff'), then + diff_pos[0] = 1 (as 'aaa' != 'eee') + diff_pos[1] = 0 (offset from beggining of tuple b to 'eee' keypart). + + Example2: if the index function is called for tuples + ('aaa','bbb') and ('aaa','fff'), + diff_pos[0] = 2 (as 'aaa' != 'eee') + diff_pos[1] = 3 (offset from beggining of tuple b to 'fff' keypart, + here we assume that first key part is CHAR(3) NOT NULL) NOTES Number-keys can't be splited - + RETURN VALUES <0 If a < b 0 If a == b @@ -107,6 +123,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, float f_1,f_2; double d_1,d_2; uint next_key_length; + uchar *orig_b= b; *diff_pos=0; for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++) @@ -114,6 +131,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, uchar *end; uint piks=! (keyseg->flag & HA_NO_SORT); (*diff_pos)++; + diff_pos[1]= (uint)(b - orig_b); /* Handle NULL part */ if (keyseg->null_bit) @@ -451,3 +469,84 @@ end: } return 0; } /* ha_key_cmp */ + + +/* + Find the first NULL value in index-suffix values tuple + + SYNOPSIS + ha_find_null() + keyseg Array of keyparts for key suffix + a Key suffix value tuple + + DESCRIPTION + Find the first NULL value in index-suffix values tuple. + TODO Consider optimizing this fuction or its use so we don't search for + NULL values in completely NOT NULL index suffixes. + + RETURN + First key part that has NULL as value in values tuple, or the last key part + (with keyseg->type==HA_TYPE_END) if values tuple doesn't contain NULLs. +*/ + +HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a) +{ + for (; (enum ha_base_keytype) keyseg->type != HA_KEYTYPE_END; keyseg++) + { + uchar *end; + if (keyseg->null_bit) + { + if (!*a++) + return keyseg; + } + end= a+ keyseg->length; + + switch ((enum ha_base_keytype) keyseg->type) { + case HA_KEYTYPE_TEXT: + case HA_KEYTYPE_BINARY: + if (keyseg->flag & HA_SPACE_PACK) + { + int a_length; + get_key_length(a_length, a); + a += a_length; + break; + } + else + a= end; + break; + case HA_KEYTYPE_VARTEXT1: + case HA_KEYTYPE_VARBINARY1: + { + int a_length; + get_key_length(a_length, a); + a+= a_length; + break; + } + case HA_KEYTYPE_NUM: + if (keyseg->flag & HA_SPACE_PACK) + { + int alength= *a++; + end= a+alength; + } + a= end; + break; + case HA_KEYTYPE_INT8: + case HA_KEYTYPE_SHORT_INT: + case HA_KEYTYPE_USHORT_INT: + case HA_KEYTYPE_LONG_INT: + case HA_KEYTYPE_ULONG_INT: + case HA_KEYTYPE_INT24: + case HA_KEYTYPE_UINT24: +#ifdef HAVE_LONG_LONG + case HA_KEYTYPE_LONGLONG: + case HA_KEYTYPE_ULONGLONG: +#endif + case HA_KEYTYPE_FLOAT: + case HA_KEYTYPE_DOUBLE: + a= end; + break; + } + } + return keyseg; +} + diff --git a/mysys/my_open.c b/mysys/my_open.c index 69d63c49554..6ed3cb5becf 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -56,12 +56,18 @@ File my_open(const char *FileName, int Flags, myf MyFlags) DBUG_RETURN(my_register_filename(-1, FileName, FILE_BY_OPEN, EE_FILENOTFOUND, MyFlags)); } +#ifndef __WIN__ if (Flags & O_SHARE) fd = sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); else fd = open((my_string) FileName, Flags | O_BINARY, MY_S_IREAD | MY_S_IWRITE); +#else + fd= my_sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, + MY_S_IREAD | MY_S_IWRITE); +#endif + #elif !defined(NO_OPEN_3) fd = open(FileName, Flags, my_umask); /* Normal unix */ #else @@ -167,3 +173,181 @@ File my_register_filename(File fd, const char *FileName, enum file_type FileName, my_errno); return(fd); } + +#ifdef __WIN__ + +extern void __cdecl _dosmaperr(unsigned long); + +/* + Open a file with sharing. Similar to _sopen() from libc, but allows managing + share delete on win32 + + SYNOPSIS + my_sopen() + path fully qualified file name + oflag operation flags + shflag share flag + pmode permission flags + + RETURN VALUE + File descriptor of opened file if success + -1 and sets errno if fails. +*/ + +File my_sopen(const char *path, int oflag, int shflag, int pmode) +{ + int fh; /* handle of opened file */ + int mask; + HANDLE osfh; /* OS handle of opened file */ + DWORD fileaccess; /* OS file access (requested) */ + DWORD fileshare; /* OS file sharing mode */ + DWORD filecreate; /* OS method of opening/creating */ + DWORD fileattrib; /* OS file attribute flags */ + SECURITY_ATTRIBUTES SecurityAttributes; + + SecurityAttributes.nLength= sizeof(SecurityAttributes); + SecurityAttributes.lpSecurityDescriptor= NULL; + SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT); + + /* + * decode the access flags + */ + switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { + case _O_RDONLY: /* read access */ + fileaccess= GENERIC_READ; + break; + case _O_WRONLY: /* write access */ + fileaccess= GENERIC_WRITE; + break; + case _O_RDWR: /* read and write access */ + fileaccess= GENERIC_READ | GENERIC_WRITE; + break; + default: /* error, bad oflag */ + errno= EINVAL; + _doserrno= 0L; /* not an OS error */ + return -1; + } + + /* + * decode sharing flags + */ + switch (shflag) { + case _SH_DENYRW: /* exclusive access except delete */ + fileshare= FILE_SHARE_DELETE; + break; + case _SH_DENYWR: /* share read and delete access */ + fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE; + break; + case _SH_DENYRD: /* share write and delete access */ + fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE; + break; + case _SH_DENYNO: /* share read, write and delete access */ + fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + break; + case _SH_DENYRWD: /* exclusive access */ + fileshare= 0L; + break; + case _SH_DENYWRD: /* share read access */ + fileshare= FILE_SHARE_READ; + break; + case _SH_DENYRDD: /* share write access */ + fileshare= FILE_SHARE_WRITE; + break; + case _SH_DENYDEL: /* share read and write access */ + fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE; + break; + default: /* error, bad shflag */ + errno= EINVAL; + _doserrno= 0L; /* not an OS error */ + return -1; + } + + /* + * decode open/create method flags + */ + switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) { + case 0: + case _O_EXCL: /* ignore EXCL w/o CREAT */ + filecreate= OPEN_EXISTING; + break; + + case _O_CREAT: + filecreate= OPEN_ALWAYS; + break; + + case _O_CREAT | _O_EXCL: + case _O_CREAT | _O_TRUNC | _O_EXCL: + filecreate= CREATE_NEW; + break; + + case _O_TRUNC: + case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */ + filecreate= TRUNCATE_EXISTING; + break; + + case _O_CREAT | _O_TRUNC: + filecreate= CREATE_ALWAYS; + break; + + default: + /* this can't happen ... all cases are covered */ + errno= EINVAL; + _doserrno= 0L; + return -1; + } + + /* + * decode file attribute flags if _O_CREAT was specified + */ + fileattrib= FILE_ATTRIBUTE_NORMAL; /* default */ + if (oflag & _O_CREAT) + { + _umask((mask= _umask(0))); + + if (!((pmode & ~mask) & _S_IWRITE)) + fileattrib= FILE_ATTRIBUTE_READONLY; + } + + /* + * Set temporary file (delete-on-close) attribute if requested. + */ + if (oflag & _O_TEMPORARY) + { + fileattrib|= FILE_FLAG_DELETE_ON_CLOSE; + fileaccess|= DELETE; + } + + /* + * Set temporary file (delay-flush-to-disk) attribute if requested. + */ + if (oflag & _O_SHORT_LIVED) + fileattrib|= FILE_ATTRIBUTE_TEMPORARY; + + /* + * Set sequential or random access attribute if requested. + */ + if (oflag & _O_SEQUENTIAL) + fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN; + else if (oflag & _O_RANDOM) + fileattrib|= FILE_FLAG_RANDOM_ACCESS; + + /* + * try to open/create the file + */ + if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes, + filecreate, fileattrib, NULL)) == (HANDLE)0xffffffff) + { + /* + * OS call to open/create file failed! map the error, release + * the lock, and return -1. note that it's not necessary to + * call _free_osfhnd (it hasn't been used yet). + */ + _dosmaperr(GetLastError()); /* map error */ + return -1; /* return error to caller */ + } + + fh= _open_osfhandle((long)osfh, oflag & (_O_APPEND | _O_RDONLY | _O_TEXT)); + + return fh; /* return handle */ +} +#endif /* __WIN__ */ diff --git a/mysys/testhash.c b/mysys/testhash.c index 72badffdbcd..d15016113cd 100644 --- a/mysys/testhash.c +++ b/mysys/testhash.c @@ -74,7 +74,7 @@ static int do_test() bzero((char*) key1,sizeof(key1[0])*1000); printf("- Creating hash\n"); - if (hash_init(&hash,recant/2,0,6,0,free_record,0)) + if (hash_init(&hash, default_charset_info, recant/2, 0, 6, 0, free_record, 0)) goto err; printf("- Writing records:\n"); @@ -172,15 +172,16 @@ static int do_test() break; if (key1[j] > 1) { + HASH_SEARCH_STATE state; printf("- Testing identical read\n"); sprintf(key,"%6d",j); pos=1; - if (!(recpos=hash_search(&hash,key,0))) + if (!(recpos= hash_first(&hash, key, 0, &state))) { printf("can't find key1: \"%s\"\n",key); goto err; } - while (hash_next(&hash,key,0) && pos < (ulong) (key1[j]+10)) + while (hash_next(&hash, key, 0, &state) && pos < (ulong) (key1[j]+10)) pos++; if (pos != (ulong) key1[j]) { @@ -189,7 +190,7 @@ static int do_test() } } printf("- Creating output heap-file 2\n"); - if (hash_init(&hash2,hash.records,0,0,hash2_key,free_record,0)) + if (hash_init(&hash2, default_charset_info, hash.records, 0, 0, hash2_key, free_record,0)) goto err; printf("- Copying and removing records\n"); diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index e5b77de5e38..41914080a9d 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -401,7 +401,7 @@ void end_thr_alarm(my_bool free_structures) { DBUG_ENTER("end_thr_alarm"); if (alarm_aborted != 1) /* If memory not freed */ - { + { pthread_mutex_lock(&LOCK_alarm); DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements)); alarm_aborted= -1; /* mark aborted */ @@ -415,13 +415,10 @@ void end_thr_alarm(my_bool free_structures) if (free_structures) { struct timespec abstime; - /* - The following test is just for safety, the caller should not - depend on this - */ + DBUG_ASSERT(!alarm_queue.elements); - /* Wait until alarm thread dies */ + /* Wait until alarm thread dies */ set_timespec(abstime, 10); /* Wait up to 10 seconds */ while (alarm_thread_running) { @@ -429,16 +426,13 @@ void end_thr_alarm(my_bool free_structures) if (error == ETIME || error == ETIMEDOUT) break; /* Don't wait forever */ } - if (!alarm_queue.elements) + delete_queue(&alarm_queue); + alarm_aborted= 1; + pthread_mutex_unlock(&LOCK_alarm); + if (!alarm_thread_running) /* Safety */ { - delete_queue(&alarm_queue); - alarm_aborted= 1; - pthread_mutex_unlock(&LOCK_alarm); - if (!alarm_thread_running) /* Safety */ - { - pthread_mutex_destroy(&LOCK_alarm); - pthread_cond_destroy(&COND_alarm); - } + pthread_mutex_destroy(&LOCK_alarm); + pthread_cond_destroy(&COND_alarm); } } else diff --git a/ndb/docs/Makefile.am b/ndb/docs/Makefile.am index afa91857771..78fced4b2e4 100644 --- a/ndb/docs/Makefile.am +++ b/ndb/docs/Makefile.am @@ -1,7 +1,7 @@ DOXYDIR = doxygen noinst_HEADERS = $(DOXYDIR)/predoxy.pl $(DOXYDIR)/postdoxy.pl $(DOXYDIR)/Doxyfile.ndbapi $(DOXYDIR)/Doxyfile.mgmapi $(DOXYDIR)/header.ndbapi.tex $(DOXYDIR)/header.mgmapi.tex -all: do-check-html ndbapidoc-html mgmapidoc-html +all-local: do-check-html ndbapidoc-html mgmapidoc-html all-pdf: do-check-pdf ndbapidoc-pdf mgmapidoc-pdf DOXYTMP = .doxytmp diff --git a/ndb/include/kernel/signaldata/DumpStateOrd.hpp b/ndb/include/kernel/signaldata/DumpStateOrd.hpp index bde690e056d..4dd22cf5092 100644 --- a/ndb/include/kernel/signaldata/DumpStateOrd.hpp +++ b/ndb/include/kernel/signaldata/DumpStateOrd.hpp @@ -78,6 +78,8 @@ public: LqhDumpAllScanRec = 2301, LqhDumpAllActiveScanRec = 2302, LqhDumpLcpState = 2303, + LqhErrorInsert5042 = 2315, + AccDumpOneScanRec = 2400, AccDumpAllScanRec = 2401, AccDumpAllActiveScanRec = 2402, diff --git a/ndb/include/ndb_version.h.in b/ndb/include/ndb_version.h.in index 826f5124407..38b72306d03 100644 --- a/ndb/include/ndb_version.h.in +++ b/ndb/include/ndb_version.h.in @@ -57,5 +57,8 @@ char ndb_version_string_buf[NDB_VERSION_STRING_BUF_SZ]; */ /*#define NDB_VERSION_ID 0*/ +#define NDBD_INCL_NODECONF_VERSION_4 MAKE_VERSION(4,1,17) +#define NDBD_INCL_NODECONF_VERSION_5 MAKE_VERSION(5,0,18) + #endif diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp index b3d0221fedb..a44550da48b 100644 --- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp +++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp @@ -336,14 +336,21 @@ ConfigRetriever::setNodeId(Uint32 nodeid) Uint32 ConfigRetriever::allocNodeId(int no_retries, int retry_delay_in_seconds) { + int res; _ownNodeId= 0; if(m_handle != 0) { while (1) { - int res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type); + if(!ndb_mgm_is_connected(m_handle)) + if(!ndb_mgm_connect(m_handle, 0, 0, 0)) + goto next; + + res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type); if(res >= 0) return _ownNodeId= (Uint32)res; + + next: if (no_retries == 0) break; no_retries--; diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt index 1a72537a77e..0be5e91cd71 100644 --- a/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/ndb/src/kernel/blocks/ERROR_codes.txt @@ -61,6 +61,8 @@ Insert system error in GCP participant when receiving GCP_SAVEREQ. 5007: Delay GCP_SAVEREQ by 10 secs +7165: Delay INCL_NODE_REQ in starting node yeilding error in GCP_PREPARE + ERROR CODES FOR TESTING NODE FAILURE, LOCAL CHECKPOINT HANDLING: ----------------------------------------------------------------- @@ -155,11 +157,15 @@ Insert node failure handling when receiving COMPLETEREQ. 5006: Insert node failure handling when receiving ABORTREQ. +5042: +As 5002, but with specified table (see DumpStateOrd) + These error code can be combined with error codes for testing time-out handling in DBTC to ensure that node failures are also well handled in time-out handling. They can also be used to test multiple node failure handling. + ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBLQH ------------------------------------------------- 5011: @@ -198,6 +204,9 @@ Delay execution of ABORTREQ signal 2 seconds to generate time-out. 8050: Send TCKEYREF is operation is non local +5100,5101: Drop ABORT req in primary replica + Crash on "next" ABORT + ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC ------------------------------------------------- 8040: diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index 2379bd6cf21..2d50890e962 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -886,13 +886,17 @@ Backup::checkNodeFail(Signal* signal, pos= &ref->nodeId - signal->getDataPtr(); break; } + case GSN_WAIT_GCP_REQ: + case GSN_DROP_TRIG_REQ: case GSN_CREATE_TRIG_REQ: case GSN_ALTER_TRIG_REQ: - case GSN_WAIT_GCP_REQ: + ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail); + return; case GSN_UTIL_SEQUENCE_REQ: case GSN_UTIL_LOCK_REQ: - case GSN_DROP_TRIG_REQ: return; + default: + ndbrequire(false); } for(Uint32 i = 0; (i = mask.find(i+1)) != NdbNodeBitmask::NotFound; ) @@ -1903,7 +1907,7 @@ Backup::execBACKUP_FRAGMENT_CONF(Signal* signal) const Uint32 nodeId = refToNode(signal->senderBlockRef()); const Uint32 noOfBytes = conf->noOfBytes; const Uint32 noOfRecords = conf->noOfRecords; - + BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptrI); @@ -1980,7 +1984,7 @@ Backup::execBACKUP_FRAGMENT_REF(Signal* signal) } } } - ndbrequire(false); + goto err; done: ptr.p->masterData.sendCounter--; @@ -1992,7 +1996,8 @@ done: masterAbort(signal, ptr); return; }//if - + +err: AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend(); ord->backupId = ptr.p->backupId; ord->backupPtr = ptr.i; @@ -3866,7 +3871,7 @@ Backup::checkFile(Signal* signal, BackupFilePtr filePtr) req->userReference = reference(); req->varIndex = 0; req->offset = tmp - c_startOfPages; - req->size = sz; // Avrunda uppot + req->size = sz; // Round up sendSignal(NDBFS_REF, GSN_FSAPPENDREQ, signal, FsAppendReq::SignalLength, JBA); diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 29de0368212..2a28c4db770 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -215,7 +215,7 @@ void Dbdih::sendINCL_NODEREQ(Signal* signal, Uint32 nodeId) signal->theData[2] = c_nodeStartMaster.failNr; signal->theData[3] = 0; signal->theData[4] = currentgcp; - sendSignal(nodeDihRef, GSN_INCL_NODEREQ, signal, 5, JBB); + sendSignal(nodeDihRef, GSN_INCL_NODEREQ, signal, 5, JBA); }//Dbdih::sendINCL_NODEREQ() void Dbdih::sendMASTER_GCPREQ(Signal* signal, Uint32 nodeId) @@ -1863,6 +1863,14 @@ void Dbdih::gcpBlockedLab(Signal* signal) // global checkpoint id and the correct state. We do not wait for any reply // since the starting node will not send any. /*-------------------------------------------------------------------------*/ + Uint32 startVersion = getNodeInfo(c_nodeStartMaster.startNode).m_version; + + if ((getMajor(startVersion) == 4 && startVersion >= NDBD_INCL_NODECONF_VERSION_4) || + (getMajor(startVersion) == 5 && startVersion >= NDBD_INCL_NODECONF_VERSION_5)) + { + c_INCL_NODEREQ_Counter.setWaitingFor(c_nodeStartMaster.startNode); + } + sendINCL_NODEREQ(signal, c_nodeStartMaster.startNode); }//Dbdih::gcpBlockedLab() @@ -2065,6 +2073,13 @@ void Dbdih::execINCL_NODEREQ(Signal* signal) jamEntry(); Uint32 retRef = signal->theData[0]; Uint32 nodeId = signal->theData[1]; + if (nodeId == getOwnNodeId() && ERROR_INSERTED(7165)) + { + CLEAR_ERROR_INSERT_VALUE; + sendSignalWithDelay(reference(), GSN_INCL_NODEREQ, signal, 5000, signal->getLength()); + return; + } + Uint32 tnodeStartFailNr = signal->theData[2]; currentgcp = signal->theData[4]; CRASH_INSERTION(7127); @@ -2092,6 +2107,15 @@ void Dbdih::execINCL_NODEREQ(Signal* signal) // id's and the lcp status. /*-----------------------------------------------------------------------*/ CRASH_INSERTION(7171); + Uint32 masterVersion = getNodeInfo(refToNode(cmasterdihref)).m_version; + + if ((NDB_VERSION_MAJOR == 4 && masterVersion >= NDBD_INCL_NODECONF_VERSION_4) || + (NDB_VERSION_MAJOR == 5 && masterVersion >= NDBD_INCL_NODECONF_VERSION_5)) + { + signal->theData[0] = getOwnNodeId(); + signal->theData[1] = getOwnNodeId(); + sendSignal(cmasterdihref, GSN_INCL_NODECONF, signal, 2, JBB); + } return; }//if if (getNodeStatus(nodeId) != NodeRecord::STARTING) { @@ -3741,9 +3765,23 @@ void Dbdih::execNODE_FAILREP(Signal* signal) /*------------------------------------------------------------------------*/ // Verify that a starting node has also crashed. Reset the node start record. /*-------------------------------------------------------------------------*/ - if (c_nodeStartMaster.startNode != RNIL) { - ndbrequire(getNodeStatus(c_nodeStartMaster.startNode)!= NodeRecord::ALIVE); +#if 0 + /** + * Node will crash by itself... + * nodeRestart is run then... + */ + if (false && c_nodeStartMaster.startNode != RNIL && getNodeStatus(c_nodeStartMaster.startNode) == NodeRecord::ALIVE) + { + BlockReference cntrRef = calcNdbCntrBlockRef(c_nodeStartMaster.startNode); + SystemError * const sysErr = (SystemError*)&signal->theData[0]; + sysErr->errorCode = SystemError::StartInProgressError; + sysErr->errorRef = reference(); + sysErr->data1= 0; + sysErr->data2= __LINE__; + sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal, SystemError::SignalLength, JBA); + nodeResetStart(); }//if +#endif /*--------------------------------------------------*/ /* */ @@ -5189,15 +5227,16 @@ void Dbdih::removeNodeFromTable(Signal* signal, /** * For each of replica record */ - Uint32 replicaNo = 0; + bool found = false; ReplicaRecordPtr replicaPtr; for(replicaPtr.i = fragPtr.p->storedReplicas; replicaPtr.i != RNIL; - replicaPtr.i = replicaPtr.p->nextReplica, replicaNo++) { + replicaPtr.i = replicaPtr.p->nextReplica) { jam(); ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord); if(replicaPtr.p->procNode == nodeId){ jam(); + found = true; noOfRemovedReplicas++; removeNodeFromStored(nodeId, fragPtr, replicaPtr); if(replicaPtr.p->lcpOngoingFlag){ @@ -5213,6 +5252,15 @@ void Dbdih::removeNodeFromTable(Signal* signal, } } } + if (!found) + { + jam(); + /** + * Run updateNodeInfo to remove any dead nodes from list of activeNodes + * see bug#15587 + */ + updateNodeInfo(fragPtr); + } noOfRemainingLcpReplicas += fragPtr.p->noLcpReplicas; } @@ -11087,7 +11135,11 @@ void Dbdih::initCommonData() cnoReplicas = 1; ndb_mgm_get_int_parameter(p, CFG_DB_NO_REPLICAS, &cnoReplicas); - cnoReplicas = cnoReplicas > 4 ? 4 : cnoReplicas; + if (cnoReplicas > 4) + { + progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, + "Only up to four replicas are supported. Check NoOfReplicas."); + } cgcpDelay = 2000; ndb_mgm_get_int_parameter(p, CFG_DB_GCP_INTERVAL, &cgcpDelay); @@ -11675,14 +11727,14 @@ void Dbdih::execCHECKNODEGROUPSREQ(Signal* signal) break; case CheckNodeGroups::GetNodeGroupMembers: { ok = true; - Uint32 ownNodeGoup = + Uint32 ownNodeGroup = Sysfile::getNodeGroup(sd->nodeId, SYSFILE->nodeGroups); - sd->output = ownNodeGoup; + sd->output = ownNodeGroup; sd->mask.clear(); NodeGroupRecordPtr ngPtr; - ngPtr.i = ownNodeGoup; + ngPtr.i = ownNodeGroup; ptrAss(ngPtr, nodeGroupRecord); for (Uint32 j = 0; j < ngPtr.p->nodeCount; j++) { jam(); @@ -11690,7 +11742,7 @@ void Dbdih::execCHECKNODEGROUPSREQ(Signal* signal) } #if 0 for (int i = 0; i < MAX_NDB_NODES; i++) { - if (ownNodeGoup == + if (ownNodeGroup == Sysfile::getNodeGroup(i, SYSFILE->nodeGroups)) { sd->mask.set(i); } diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp index 94a40adcd4a..1ed383853ba 100644 --- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp +++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp @@ -2885,6 +2885,7 @@ private: UintR ctransidHash[1024]; Uint32 c_diskless; + Uint32 c_error_insert_table_id; public: /** diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 2170f890f35..803377f9dd1 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -3543,6 +3543,7 @@ void Dblqh::execLQHKEYREQ(Signal* signal) jam(); regTcPtr->activeCreat = ZTRUE; CRASH_INSERTION(5002); + CRASH_INSERTION2(5042, tabptr.i == c_error_insert_table_id); } else { regTcPtr->activeCreat = ZFALSE; }//if @@ -5880,12 +5881,21 @@ void Dblqh::execABORT(Signal* signal) warningReport(signal, 8); return; }//if + + TcConnectionrec * const regTcPtr = tcConnectptr.p; + + if (ERROR_INSERTED(5100)) + { + SET_ERROR_INSERT_VALUE(5101); + return; + } + CRASH_INSERTION2(5101, regTcPtr->nextReplica != ZNIL); + /* ------------------------------------------------------------------------- */ /*A GUIDING DESIGN PRINCIPLE IN HANDLING THESE ERROR SITUATIONS HAVE BEEN */ /*KEEP IT SIMPLE. THUS WE RATHER INSERT A WAIT AND SET THE ABORT_STATE TO */ /*ACTIVE RATHER THAN WRITE NEW CODE TO HANDLE EVERY SPECIAL SITUATION. */ /* ------------------------------------------------------------------------- */ - TcConnectionrec * const regTcPtr = tcConnectptr.p; if (regTcPtr->nextReplica != ZNIL) { /* ------------------------------------------------------------------------- */ // We will immediately send the ABORT message also to the next LQH node in line. @@ -18522,6 +18532,12 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal) } } + + if (dumpState->args[0] == DumpStateOrd::LqhErrorInsert5042 && signal->getLength() == 2) + { + c_error_insert_table_id = dumpState->args[1]; + SET_ERROR_INSERT_VALUE(5042); + } }//Dblqh::execDUMP_STATE_ORD() void Dblqh::execSET_VAR_REQ(Signal* signal) @@ -18562,60 +18578,54 @@ void Dblqh::execCREATE_TRIG_REQ(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference tupref = calcTupBlockRef(myNodeId); - sendSignal(tupref, GSN_CREATE_TRIG_REQ, signal, CreateTrigReq::SignalLength, JBB); + sendSignal(DBTUP_REF, GSN_CREATE_TRIG_REQ, signal, + CreateTrigReq::SignalLength, JBB); } void Dblqh::execCREATE_TRIG_CONF(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference dictref = calcDictBlockRef(myNodeId); - sendSignal(dictref, GSN_CREATE_TRIG_CONF, signal, CreateTrigConf::SignalLength, JBB); + sendSignal(DBDICT_REF, GSN_CREATE_TRIG_CONF, signal, + CreateTrigConf::SignalLength, JBB); } void Dblqh::execCREATE_TRIG_REF(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference dictref = calcDictBlockRef(myNodeId); - sendSignal(dictref, GSN_CREATE_TRIG_REF, signal, CreateTrigRef::SignalLength, JBB); + sendSignal(DBDICT_REF, GSN_CREATE_TRIG_REF, signal, + CreateTrigRef::SignalLength, JBB); } void Dblqh::execDROP_TRIG_REQ(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference tupref = calcTupBlockRef(myNodeId); - sendSignal(tupref, GSN_DROP_TRIG_REQ, signal, DropTrigReq::SignalLength, JBB); + sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ, signal, + DropTrigReq::SignalLength, JBB); } void Dblqh::execDROP_TRIG_CONF(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference dictref = calcDictBlockRef(myNodeId); - sendSignal(dictref, GSN_DROP_TRIG_CONF, signal, DropTrigConf::SignalLength, JBB); + sendSignal(DBDICT_REF, GSN_DROP_TRIG_CONF, signal, + DropTrigConf::SignalLength, JBB); } void Dblqh::execDROP_TRIG_REF(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference dictref = calcDictBlockRef(myNodeId); - sendSignal(dictref, GSN_DROP_TRIG_REF, signal, DropTrigRef::SignalLength, JBB); + sendSignal(DBDICT_REF, GSN_DROP_TRIG_REF, signal, + DropTrigRef::SignalLength, JBB); } Uint32 Dblqh::calcPageCheckSum(LogPageRecordPtr logP){ diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp index 8218acc0ea7..cb4f1c6244b 100644 --- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp +++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp @@ -141,6 +141,8 @@ #define ZALREADYEXIST 630 #define ZINCONSISTENTHASHINDEX 892 #define ZNOTUNIQUE 893 + +#define ZINVALID_KEY 290 #endif class Dbtc: public SimulatedBlock { diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index f2646fd4176..d7232030c41 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -2313,7 +2313,10 @@ Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen, { keyPartLenPtr = keyPartLen; dstPos = xfrm_key(tabPtrI, src, dst, sizeof(Tmp) >> 2, keyPartLenPtr); - ndbrequire(dstPos); + if (unlikely(dstPos == 0)) + { + goto error; + } } else { @@ -2334,6 +2337,10 @@ Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen, dstHash[1] = tmp[1]; } return true; // success + +error: + terrorCode = ZINVALID_KEY; + return false; } /* @@ -2941,7 +2948,15 @@ void Dbtc::tckeyreq050Lab(Signal* signal) UintR tnoOfStandby; UintR tnodeinfo; + terrorCode = 0; + hash(signal); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/ + + if (unlikely(terrorCode)) + { + releaseAtErrorLab(signal); + return; + } CacheRecord * const regCachePtr = cachePtr.p; TcConnectRecord * const regTcPtr = tcConnectptr.p; @@ -6183,7 +6198,6 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr) << " - place: " << c_apiConTimer_line[apiConnectptr.i]); switch (apiConnectptr.p->apiConnectstate) { case CS_STARTED: - ndbrequire(c_apiConTimer_line[apiConnectptr.i] != 3615); if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec){ jam(); /* @@ -6443,8 +6457,8 @@ void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck) warningEvent(buf); ndbout_c(buf); ndbrequire(false); + releaseAbortResources(signal); } - releaseAbortResources(signal); return; }//if TloopCount++; diff --git a/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp b/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp index 470b98fd04c..e16d3df6d8d 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp @@ -445,6 +445,7 @@ Dbtup::commitRecord(Signal* signal, befOpPtr.p->changeMask.bitOR(attributeMask); befOpPtr.p->gci = regOperPtr->gci; + befOpPtr.p->optype = opType; operPtr.p = befOpPtr.p; checkDetachedTriggers(signal, befOpPtr.p, @@ -483,6 +484,7 @@ Dbtup::commitRecord(Signal* signal, befOpPtr.p->pageIndex = befOpPtr.p->pageIndexC; befOpPtr.p->gci = regOperPtr->gci; + befOpPtr.p->optype = opType; operPtr.p = befOpPtr.p; checkDetachedTriggers(signal, befOpPtr.p, diff --git a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp index acdad3f9f1a..8a55777ac05 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp @@ -684,6 +684,21 @@ Dbtup::checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr) Uint32 attrDescriptorIndex = regTabPtr->tabDescriptor + (attributeId << ZAD_LOG_SIZE); Uint32 attrDescriptor = tableDescriptor[attrDescriptorIndex].tabDescr; Uint32 attributeOffset = tableDescriptor[attrDescriptorIndex + 1].tabDescr; + + Uint32 xfrmBuffer[1 + MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY]; + Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attributeOffset); + if (charsetFlag) { + Uint32 csIndex = AttributeOffset::getCharsetPos(attributeOffset); + CHARSET_INFO* cs = regTabPtr->charsetArray[csIndex]; + Uint32 srcPos = 0; + Uint32 dstPos = 0; + xfrm_attr(attrDescriptor, cs, &updateBuffer[1], srcPos, + &xfrmBuffer[1], dstPos, MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY); + ahIn.setDataSize(dstPos); + xfrmBuffer[0] = ahIn.m_value; + updateBuffer = xfrmBuffer; + } + ReadFunction f = regTabPtr->readFunctionArray[attributeId]; AttributeHeader::init(&attributeHeader, attributeId, 0); @@ -691,7 +706,7 @@ Dbtup::checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr) tMaxRead = MAX_KEY_SIZE_IN_WORDS; bool tmp = tXfrmFlag; - tXfrmFlag = false; + tXfrmFlag = true; ndbrequire((this->*f)(&keyReadBuffer[0], ahOut, attrDescriptor, attributeOffset)); tXfrmFlag = tmp; ndbrequire(tOutBufIndex == ahOut->getDataSize()); diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp index 7003d70e8b1..ed18a4ddb8b 100644 --- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp +++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp @@ -2030,29 +2030,32 @@ void Qmgr::execAPI_REGREQ(Signal* signal) }//Qmgr::execAPI_REGREQ() -void +void Qmgr::execAPI_VERSION_REQ(Signal * signal) { jamEntry(); ApiVersionReq * const req = (ApiVersionReq *)signal->getDataPtr(); - + Uint32 senderRef = req->senderRef; Uint32 nodeId = req->nodeId; ApiVersionConf * conf = (ApiVersionConf *)req; if(getNodeInfo(nodeId).m_connected) + { conf->version = getNodeInfo(nodeId).m_version; + struct in_addr in= globalTransporterRegistry.get_connect_address(nodeId); + conf->inet_addr= in.s_addr; + } else + { conf->version = 0; + conf->inet_addr= 0; + } conf->nodeId = nodeId; - struct in_addr in= globalTransporterRegistry.get_connect_address(nodeId); - conf->inet_addr= in.s_addr; - sendSignal(senderRef, + sendSignal(senderRef, GSN_API_VERSION_CONF, signal, ApiVersionConf::SignalLength, JBB); - - } diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp index d708052ca4e..3fe76e45322 100644 --- a/ndb/src/kernel/vm/SimulatedBlock.cpp +++ b/ndb/src/kernel/vm/SimulatedBlock.cpp @@ -1868,56 +1868,66 @@ SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src, while (i < noOfKeyAttr) { const KeyDescriptor::KeyAttr& keyAttr = desc->keyAttr[i]; - - Uint32 srcBytes = - AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor); - Uint32 srcWords = (srcBytes + 3) / 4; - Uint32 dstWords = ~0; - uchar* dstPtr = (uchar*)&dst[dstPos]; - const uchar* srcPtr = (const uchar*)&src[srcPos]; - CHARSET_INFO* cs = keyAttr.charsetInfo; - - if (cs == NULL) - { - jam(); - memcpy(dstPtr, srcPtr, srcWords << 2); - dstWords = srcWords; - } - else - { - jam(); - Uint32 typeId = - AttributeDescriptor::getType(keyAttr.attributeDescriptor); - Uint32 lb, len; - bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len); - ndbrequire(ok); - Uint32 xmul = cs->strxfrm_multiply; - if (xmul == 0) - xmul = 1; - /* - * Varchar is really Char. End spaces do not matter. To get - * same hash we blank-pad to maximum length via strnxfrm. - * TODO use MySQL charset-aware hash function instead - */ - Uint32 dstLen = xmul * (srcBytes - lb); - ndbrequire(dstLen <= ((dstSize - dstPos) << 2)); - int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len); - ndbrequire(n != -1); - while ((n & 3) != 0) - { - dstPtr[n++] = 0; - } - dstWords = (n >> 2); - } - dstPos += dstWords; - srcPos += srcWords; + Uint32 dstWords = + xfrm_attr(keyAttr.attributeDescriptor, keyAttr.charsetInfo, + src, srcPos, dst, dstPos, dstSize); keyPartLen[i++] = dstWords; + if (unlikely(dstWords == 0)) + return 0; } return dstPos; } Uint32 +SimulatedBlock::xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs, + const Uint32* src, Uint32 & srcPos, + Uint32* dst, Uint32 & dstPos, Uint32 dstSize) const +{ + Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDesc); + Uint32 srcWords = (srcBytes + 3) / 4; + Uint32 dstWords = ~0; + uchar* dstPtr = (uchar*)&dst[dstPos]; + const uchar* srcPtr = (const uchar*)&src[srcPos]; + + if (cs == NULL) + { + jam(); + memcpy(dstPtr, srcPtr, srcWords << 2); + dstWords = srcWords; + } + else + { + jam(); + Uint32 typeId = AttributeDescriptor::getType(attrDesc); + Uint32 lb, len; + bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len); + if (unlikely(!ok)) + return 0; + Uint32 xmul = cs->strxfrm_multiply; + if (xmul == 0) + xmul = 1; + /* + * Varchar end-spaces are ignored in comparisons. To get same hash + * we blank-pad to maximum length via strnxfrm. + */ + Uint32 dstLen = xmul * (srcBytes - lb); + ndbrequire(dstLen <= ((dstSize - dstPos) << 2)); + int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len); + if (unlikely(n == -1)) + return 0; + while ((n & 3) != 0) + { + dstPtr[n++] = 0; + } + dstWords = (n >> 2); + } + dstPos += dstWords; + srcPos += srcWords; + return dstWords; +} + +Uint32 SimulatedBlock::create_distr_key(Uint32 tableId, Uint32 *data, const Uint32 diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp index ce77fa916d8..b7bd8c57ee8 100644 --- a/ndb/src/kernel/vm/SimulatedBlock.hpp +++ b/ndb/src/kernel/vm/SimulatedBlock.hpp @@ -395,8 +395,12 @@ protected: * @return length */ Uint32 xfrm_key(Uint32 tab, const Uint32* src, - Uint32 *dst, Uint32 dstLen, + Uint32 *dst, Uint32 dstSize, Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const; + + Uint32 xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs, + const Uint32* src, Uint32 & srcPos, + Uint32* dst, Uint32 & dstPos, Uint32 dstSize) const; /** * diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index 9bb238ca90b..a69a61dcda7 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -336,10 +336,16 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, const Properties* p = parser.parse(ctx, session); if (p == NULL){ if(!ndb_mgm_is_connected(handle)) { - return NULL; + DBUG_RETURN(NULL); } else { + if(ctx.m_status==Parser_t::Eof + || ctx.m_status==Parser_t::NoLine) + { + ndb_mgm_disconnect(handle); + DBUG_RETURN(NULL); + } /** * Print some info about why the parser returns NULL */ diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/ndb/src/ndbapi/NdbEventOperationImpl.cpp index 208525bfc15..9c147be9f16 100644 --- a/ndb/src/ndbapi/NdbEventOperationImpl.cpp +++ b/ndb/src/ndbapi/NdbEventOperationImpl.cpp @@ -250,10 +250,10 @@ NdbEventOperationImpl::execute() int hasSubscriber; int r= m_bufferHandle->prepareAddSubscribeEvent(this, hasSubscriber /*return value*/); - m_error.code= 4709; if (r < 0) { + m_error.code= 4709; DBUG_RETURN(-1); } diff --git a/ndb/src/ndbapi/NdbImpl.hpp b/ndb/src/ndbapi/NdbImpl.hpp index d50f1fa84fe..c668533457d 100644 --- a/ndb/src/ndbapi/NdbImpl.hpp +++ b/ndb/src/ndbapi/NdbImpl.hpp @@ -89,11 +89,9 @@ public: /** * NOTE free lists must be _after_ theNdbObjectIdMap take * assure that destructors are run in correct order + * NOTE these has to be in this specific order to make destructor run in + * correct order */ - Ndb_free_list_t<NdbTransaction> theConIdleList; - Ndb_free_list_t<NdbOperation> theOpIdleList; - Ndb_free_list_t<NdbIndexScanOperation> theScanOpIdleList; - Ndb_free_list_t<NdbIndexOperation> theIndexOpIdleList; Ndb_free_list_t<NdbRecAttr> theRecAttrIdleList; Ndb_free_list_t<NdbApiSignal> theSignalIdleList; Ndb_free_list_t<NdbLabel> theLabelList; @@ -102,6 +100,10 @@ public: Ndb_free_list_t<NdbCall> theCallList; Ndb_free_list_t<NdbBlob> theNdbBlobIdleList; Ndb_free_list_t<NdbReceiver> theScanList; + Ndb_free_list_t<NdbIndexScanOperation> theScanOpIdleList; + Ndb_free_list_t<NdbOperation> theOpIdleList; + Ndb_free_list_t<NdbIndexOperation> theIndexOpIdleList; + Ndb_free_list_t<NdbTransaction> theConIdleList; }; #ifdef VM_TRACE diff --git a/ndb/src/ndbapi/NdbRecAttr.cpp b/ndb/src/ndbapi/NdbRecAttr.cpp index 2245707bf65..771da56523c 100644 --- a/ndb/src/ndbapi/NdbRecAttr.cpp +++ b/ndb/src/ndbapi/NdbRecAttr.cpp @@ -24,6 +24,7 @@ NdbRecAttr::NdbRecAttr(Ndb*) { + theStorageX = 0; init(); } @@ -53,6 +54,9 @@ NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue) theNULLind = 0; m_nullable = anAttrInfo->m_nullable; + if (theStorageX) + delete[] theStorageX; + // check alignment to signal data // a future version could check alignment per data type as well diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index 4a9ac9affb7..5ca8ad7be60 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -227,6 +227,7 @@ ErrorBundle ErrorCodes[] = { { 277, IE, "277" }, { 278, IE, "278" }, { 287, IE, "Index corrupted" }, + { 290, IE, "Corrupt key in TC, unable to xfrm" }, { 631, IE, "631" }, { 632, IE, "632" }, { 702, IE, "Request to non-master" }, @@ -295,7 +296,6 @@ ErrorBundle ErrorCodes[] = { { 4608, AE, "You can not takeOverScan unless you have used openScanExclusive"}, { 4609, AE, "You must call nextScanResult before trying to takeOverScan"}, { 4232, AE, "Parallelism can only be between 1 and 240" }, - { 290, AE, "Scan not started or has been closed by kernel due to timeout" }, /** * Event schema errors diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am index d83e9614eb5..0533493ba09 100644 --- a/ndb/test/ndbapi/Makefile.am +++ b/ndb/test/ndbapi/Makefile.am @@ -35,7 +35,8 @@ testPartitioning \ testBitfield \ DbCreate DbAsyncGenerator \ test_event_multi_table \ -testSRBank +testSRBank \ +test_event_merge #flexTimedAsynch #testBlobs @@ -80,6 +81,7 @@ DbCreate_SOURCES = bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterfa DbAsyncGenerator_SOURCES = bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp test_event_multi_table_SOURCES = test_event_multi_table.cpp testSRBank_SOURCES = testSRBank.cpp +test_event_merge_SOURCES = test_event_merge.cpp INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel @@ -160,3 +162,4 @@ testScan.dsp: Makefile \ @$(top_srcdir)/ndb/config/win-includes $@ $(INCLUDES) @$(top_srcdir)/ndb/config/win-sources $@ $(testScan_SOURCES) @$(top_srcdir)/ndb/config/win-libraries $@ LINK $(LDADD) + diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp index 6ef3da2d760..92d6c1830ef 100644 --- a/ndb/test/ndbapi/testNodeRestart.cpp +++ b/ndb/test/ndbapi/testNodeRestart.cpp @@ -21,6 +21,7 @@ #include <NdbRestarter.hpp> #include <NdbRestarts.hpp> #include <Vector.hpp> +#include <signaldata/DumpStateOrd.hpp> int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){ @@ -409,6 +410,132 @@ int runLateCommit(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int runBug15587(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + NdbRestarter restarter; + + Uint32 tableId = ctx->getTab()->getTableId(); + int dump[2] = { DumpStateOrd::LqhErrorInsert5042, 0 }; + dump[1] = tableId; + + int nodeId = restarter.getDbNodeId(1); + + ndbout << "Restart node " << nodeId << endl; + + if (restarter.restartOneDbNode(nodeId, + /** initial */ false, + /** nostart */ true, + /** abort */ true)) + return NDBT_FAILED; + + if (restarter.waitNodesNoStart(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.dumpStateOneNode(nodeId, dump, 2)) + return NDBT_FAILED; + + if (restarter.startNodes(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.waitNodesStarted(&nodeId, 1)) + return NDBT_FAILED; + + ctx->stopTest(); + return NDBT_OK; +} + +int runBug15632(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + NdbRestarter restarter; + + int nodeId = restarter.getDbNodeId(1); + + ndbout << "Restart node " << nodeId << endl; + + if (restarter.restartOneDbNode(nodeId, + /** initial */ false, + /** nostart */ true, + /** abort */ true)) + return NDBT_FAILED; + + if (restarter.waitNodesNoStart(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.insertErrorInNode(nodeId, 7165)) + return NDBT_FAILED; + + if (restarter.startNodes(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.waitNodesStarted(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.restartOneDbNode(nodeId, + /** initial */ false, + /** nostart */ true, + /** abort */ true)) + return NDBT_FAILED; + + if (restarter.waitNodesNoStart(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.insertErrorInNode(nodeId, 7171)) + return NDBT_FAILED; + + if (restarter.startNodes(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.waitNodesStarted(&nodeId, 1)) + return NDBT_FAILED; + + ctx->stopTest(); + return NDBT_OK; +} + +int runBug15685(NDBT_Context* ctx, NDBT_Step* step){ + + Ndb* pNdb = GETNDB(step); + HugoOperations hugoOps(*ctx->getTab()); + NdbRestarter restarter; + + HugoTransactions hugoTrans(*ctx->getTab()); + if (hugoTrans.loadTable(GETNDB(step), 10) != 0){ + return NDBT_FAILED; + } + + if(hugoOps.startTransaction(pNdb) != 0) + goto err; + + if(hugoOps.pkUpdateRecord(pNdb, 0, 1, rand()) != 0) + goto err; + + if(hugoOps.execute_NoCommit(pNdb) != 0) + goto err; + + if (restarter.insertErrorInAllNodes(5100)) + return NDBT_FAILED; + + hugoOps.execute_Rollback(pNdb); + + if (restarter.waitClusterStarted() != 0) + goto err; + + if (restarter.insertErrorInAllNodes(0)) + return NDBT_FAILED; + + ctx->stopTest(); + return NDBT_OK; + +err: + ctx->stopTest(); + return NDBT_FAILED; +} + + NDBT_TESTSUITE(testNodeRestart); TESTCASE("NoLoad", "Test that one node at a time can be stopped and then restarted "\ @@ -558,6 +685,8 @@ TESTCASE("RestartNFDuringNR", INITIALIZER(runCheckAllNodesStarted); INITIALIZER(runLoadTable); STEP(runRestarts); + STEP(runPkUpdateUntilStopped); + STEP(runScanUpdateUntilStopped); FINALIZER(runScanReadVerify); FINALIZER(runClearTable); } @@ -647,6 +776,8 @@ TESTCASE("RestartNodeDuringLCP", INITIALIZER(runCheckAllNodesStarted); INITIALIZER(runLoadTable); STEP(runRestarts); + STEP(runPkUpdateUntilStopped); + STEP(runScanUpdateUntilStopped); FINALIZER(runScanReadVerify); FINALIZER(runClearTable); } @@ -671,6 +802,24 @@ TESTCASE("LateCommit", STEP(runLateCommit); FINALIZER(runClearTable); } +TESTCASE("Bug15587", + "Test bug with NF during NR"){ + INITIALIZER(runLoadTable); + STEP(runScanUpdateUntilStopped); + STEP(runBug15587); + FINALIZER(runClearTable); +} +TESTCASE("Bug15632", + "Test bug with NF during NR"){ + INITIALIZER(runLoadTable); + STEP(runBug15632); + FINALIZER(runClearTable); +} +TESTCASE("Bug15685", + "Test bug with NF during abort"){ + STEP(runBug15685); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testNodeRestart); int main(int argc, const char** argv){ diff --git a/ndb/test/ndbapi/test_event_merge.cpp b/ndb/test/ndbapi/test_event_merge.cpp new file mode 100644 index 00000000000..1332455cdc5 --- /dev/null +++ b/ndb/test/ndbapi/test_event_merge.cpp @@ -0,0 +1,1286 @@ +/* Copyright (C) 2005 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 + 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 */ + +#include <ndb_global.h> +#include <ndb_opts.h> +#include <NdbApi.hpp> +#include <NdbTest.hpp> +#include <my_sys.h> +#include <ndb_version.h> + +#if NDB_VERSION_D < MAKE_VERSION(5, 1, 0) +#define version50 +#else +#undef version50 +#endif + +#if !defined(min) || !defined(max) +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) +#endif + +/* + * Test composite operations on same PK via events. The merge of event + * data can happen in 2 places: + * + * 1) In TUP at commit, the detached triggers report a single composite + * operation and its post/pre data + * + * 2) In event API version >= 5.1 separate commits within same GCI are + * by default merged. This is required to read blob data via NdbBlob. + * + * This test program ignores Blob columns in version 5.0. + * + * There are 5 ways (ignoring NUL operand) to compose 2 ops: + * 5.0 bugs 5.1 bugs + * INS o DEL = NUL + * INS o UPD = INS 5.1 + * DEL o INS = UPD type=INS 5.1 + * UPD o DEL = DEL no event + * UPD o UPD = UPD + */ + +struct Opts { + my_bool abort_on_error; + int loglevel; + uint loop; + uint maxops; + uint maxpk; + const char* opstr; + uint seed; + my_bool separate_events; + my_bool use_table; +}; + +static Opts g_opts; +static const uint g_maxops = 10000; +static const uint g_maxpk = 100; + +static Ndb_cluster_connection* g_ncc = 0; +static Ndb* g_ndb = 0; +static NdbDictionary::Dictionary* g_dic = 0; +static NdbTransaction* g_con = 0; +static NdbOperation* g_op = 0; + +static const char* g_tabname = "tem1"; +static const char* g_evtname = "tem1ev1"; +static const uint g_charlen = 5; +static const char* g_csname = "latin1_swedish_ci"; + +static const NdbDictionary::Table* g_tab = 0; +static const NdbDictionary::Event* g_evt = 0; + +static NdbEventOperation* g_evt_op = 0; + +static uint +urandom(uint n) +{ + uint r = (uint)random(); + if (n != 0) + r = r % n; + return r; +} + +static int& g_loglevel = g_opts.loglevel; // default log level + +#define chkdb(x) \ + do { if (x) break; ndbout << "line " << __LINE__ << " FAIL " << #x << endl; errdb(); if (g_opts.abort_on_error) abort(); return -1; } while (0) + +#define chkrc(x) \ + do { if (x) break; ndbout << "line " << __LINE__ << " FAIL " << #x << endl; if (g_opts.abort_on_error) abort(); return -1; } while (0) + +#define reqrc(x) \ + do { if (x) break; ndbout << "line " << __LINE__ << " ASSERT " << #x << endl; abort(); } while (0) + +#define ll0(x) \ + do { if (g_loglevel < 0) break; ndbout << x << endl; } while (0) + +#define ll1(x) \ + do { if (g_loglevel < 1) break; ndbout << x << endl; } while (0) + +#define ll2(x) \ + do { if (g_loglevel < 2) break; ndbout << x << endl; } while (0) + +static void +errdb() +{ + uint any = 0; + if (g_ndb != 0) { + const NdbError& e = g_ndb->getNdbError(); + if (e.code != 0) + ll0(++any << " ndb: error " << e); + } + if (g_dic != 0) { + const NdbError& e = g_dic->getNdbError(); + if (e.code != 0) + ll0(++any << " dic: error " << e); + } + if (g_con != 0) { + const NdbError& e = g_con->getNdbError(); + if (e.code != 0) + ll0(++any << " con: error " << e); + } + if (g_op != 0) { + const NdbError& e = g_op->getNdbError(); + if (e.code != 0) + ll0(++any << " op: error " << e); + } + if (g_evt_op != 0) { + const NdbError& e = g_evt_op->getNdbError(); + if (e.code != 0) + ll0(++any << " evt_op: error " << e); + } + if (! any) + ll0("unknown db error"); +} + +struct Col { + uint no; + const char* name; + NdbDictionary::Column::Type type; + bool pk; + bool nullable; + uint length; + uint size; +}; + +static Col g_col[] = { + { 0, "pk1", NdbDictionary::Column::Unsigned, true, false, 1, 4 }, + { 1, "pk2", NdbDictionary::Column::Char, true, false, g_charlen, g_charlen }, + { 2, "seq", NdbDictionary::Column::Unsigned, false, false, 1, 4 }, + { 3, "cc1", NdbDictionary::Column::Char, false, true, g_charlen, g_charlen } +}; + +static const uint g_ncol = sizeof(g_col)/sizeof(g_col[0]); + +static const Col& +getcol(uint i) +{ + if (i < g_ncol) + return g_col[i]; + assert(false); + return g_col[g_ncol]; +} + +static const Col& +getcol(const char* name) +{ + uint i; + for (i = 0; i < g_ncol; i++) + if (strcmp(g_col[i].name, name) == 0) + break; + return getcol(i); +} + +static int +createtable() +{ + g_tab = 0; + NdbDictionary::Table tab(g_tabname); + tab.setLogging(false); + CHARSET_INFO* cs; + chkrc((cs = get_charset_by_name(g_csname, MYF(0))) != 0); + uint i; + for (i = 0; i < g_ncol; i++) { + const Col& c = g_col[i]; + NdbDictionary::Column col(c.name); + col.setType(c.type); + col.setPrimaryKey(c.pk); + if (! c.pk) + col.setNullable(true); + col.setLength(c.length); + switch (c.type) { + case NdbDictionary::Column::Unsigned: + break; + case NdbDictionary::Column::Char: + col.setLength(c.length); + col.setCharset(cs); + break; + default: + assert(false); + break; + } + tab.addColumn(col); + } + g_dic = g_ndb->getDictionary(); + if (! g_opts.use_table) { + if (g_dic->getTable(g_tabname) != 0) + chkdb(g_dic->dropTable(g_tabname) == 0); + chkdb(g_dic->createTable(tab) == 0); + } + chkdb((g_tab = g_dic->getTable(g_tabname)) != 0); + g_dic = 0; + if (! g_opts.use_table) { + // extra row for GCI probe + chkdb((g_con = g_ndb->startTransaction()) != 0); + chkdb((g_op = g_con->getNdbOperation(g_tabname)) != 0); + chkdb(g_op->insertTuple() == 0); + Uint32 pk1; + char pk2[g_charlen]; + pk1 = g_maxpk; + memset(pk2, 0x20, g_charlen); + chkdb(g_op->equal("pk1", (char*)&pk1) == 0); + chkdb(g_op->equal("pk2", (char*)&pk2[0]) == 0); + chkdb(g_con->execute(Commit) == 0); + g_ndb->closeTransaction(g_con); + g_op = 0; + g_con = 0; + } + return 0; +} + +static int +droptable() +{ + if (! g_opts.use_table) { + g_dic = g_ndb->getDictionary(); + chkdb(g_dic->dropTable(g_tab->getName()) == 0); + g_tab = 0; + g_dic = 0; + } + return 0; +} + +struct Data { + Uint32 pk1; + char pk2[g_charlen]; + Uint32 seq; + char cc1[g_charlen]; + void* ptr[g_ncol]; + int ind[g_ncol]; // -1 = no data, 1 = NULL, 0 = not NULL + void init() { + uint i; + pk1 = 0; + memset(pk2, 0, sizeof(pk2)); + seq = 0; + memset(cc1, 0, sizeof(cc1)); + ptr[0] = &pk1; + ptr[1] = pk2; + ptr[2] = &seq; + ptr[3] = cc1; + for (i = 0; i < g_ncol; i++) + ind[i] = -1; + } +}; + +static NdbOut& +operator<<(NdbOut& out, const Data& d) +{ + uint i; + for (i = 0; i < g_ncol; i++) { + const Col& c = getcol(i); + out << (i == 0 ? "" : " ") << c.name << "="; + if (d.ind[i] == -1) + continue; + if (d.ind[i] == 1) { + out << "NULL"; + continue; + } + switch (c.type) { + case NdbDictionary::Column::Unsigned: + out << *(Uint32*)d.ptr[i]; + break; + case NdbDictionary::Column::Char: + { + char buf[g_charlen + 1]; + memcpy(buf, d.ptr[i], g_charlen); + uint n = g_charlen; + while (1) { + buf[n] = 0; + if (n == 0 || buf[n - 1] != 0x20) + break; + n--; + } + out << buf; + } + break; + default: + out << "?"; + break; + } + } + return out; +} + +static const uint g_optypes = 3; // real ops 0-2 + +/* + * Represents single or composite operation or received event. The + * post/pre data is either computed here for operations or received from + * the event. + */ +struct Op { // single or composite + enum Kind { OP = 1, EV = 2 }; + enum Type { NUL = -1, INS, DEL, UPD }; + Kind kind; + Type type; + Op* next_op; // within one commit + Op* next_com; // next commit chain or next event + uint num_op; + uint num_com; + Data data[2]; // 0-post 1-pre + bool match; // matched to event + void init() { + assert(kind == OP || kind == EV); + type = NUL; + next_op = next_com = 0; + num_op = num_com = 0; + data[0].init(); + data[1].init(); + match = false; + } +}; + +static NdbOut& +operator<<(NdbOut& out, Op::Type t) +{ + switch (t) { + case Op::NUL: + out << "NUL"; + break; + case Op::INS: + out << "INS"; + break; + case Op::DEL: + out << "DEL"; + break; + case Op::UPD: + out << "UPD"; + break; + default: + out << (int)t; + break; + } + return out; +} + +static NdbOut& +operator<<(NdbOut& out, const Op& op) +{ + out << "t=" << op.type; + out << " " << op.data[0]; + out << " [" << op.data[1] << "]"; + return out; +} + +static int +seteventtype(Op* ev, NdbDictionary::Event::TableEvent te) +{ + Op::Type t = Op::NUL; + switch (te) { + case NdbDictionary::Event::TE_INSERT: + t = Op::INS; + break; + case NdbDictionary::Event::TE_DELETE: + t = Op::DEL; + break; + case NdbDictionary::Event::TE_UPDATE: + t = Op::UPD; + break; + default: + ll0("EVT: " << *ev << ": bad event type" << (int)te); + return -1; + } + ev->type = t; + return 0; +} + +static uint g_usedops = 0; +static uint g_usedevs = 0; +static Op g_oplist[g_maxops]; +static Op g_evlist[g_maxops]; +static uint g_maxcom = 8; // max ops per commit + +static Op* g_pk_op[g_maxpk]; +static Op* g_pk_ev[g_maxpk]; +static uint g_seq = 0; + +static NdbRecAttr* g_ra[2][g_ncol]; // 0-post 1-pre +static Op* g_rec_ev; +static uint g_ev_cnt[g_maxpk]; + +static uint +getfreeops() +{ + assert(g_opts.maxops >= g_usedops); + return g_opts.maxops - g_usedops; +} + +static uint +getfreeevs() +{ + assert(g_opts.maxops >= g_usedevs); + return g_opts.maxops - g_usedevs; +} + +static Op* +getop() +{ + if (g_usedops < g_opts.maxops) { + Op* op = &g_oplist[g_usedops++]; + op->kind = Op::OP; + op->init(); + return op; + } + assert(false); + return 0; +} + +static Op* +getev() +{ + if (g_usedevs < g_opts.maxops) { + Op* ev = &g_evlist[g_usedevs++]; + ev->kind = Op::EV; + ev->init(); + return ev; + } + assert(false); + return 0; +} + +static void +resetmem() +{ + int i, j; + for (j = 0; j < 2; j++) + for (i = 0; i < g_ncol; i++) + g_ra[j][i] = 0; + g_rec_ev = 0; + for (i = 0; i < g_opts.maxpk; i++) + g_pk_op[i] = 0; + for (i = 0; i < g_opts.maxpk; i++) + g_ev_cnt[i] = 0; + g_seq = 0; + g_usedops = 0; + g_usedevs = 0; +} + +struct Comp { + Op::Type t1, t2, t3; +}; + +static Comp +g_comp[] = { + { Op::INS, Op::DEL, Op::NUL }, + { Op::INS, Op::UPD, Op::INS }, + { Op::DEL, Op::INS, Op::UPD }, + { Op::UPD, Op::DEL, Op::DEL }, + { Op::UPD, Op::UPD, Op::UPD } +}; + +static const uint g_ncomp = sizeof(g_comp)/sizeof(g_comp[0]); + +static int +checkop(const Op* op, Uint32& pk1) +{ + const Data (&d)[2] = op->data; + Op::Type t = op->type; + chkrc(t == Op::NUL || t == Op::INS || t == Op::DEL || t == Op::UPD); + { const Col& c = getcol("pk1"); + chkrc(d[0].ind[c.no] == 0); + pk1 = d[0].pk1; + chkrc(pk1 < g_opts.maxpk); + } + uint i; + for (i = 0; i < g_ncol; i++) { + const Col& c = getcol(i); + if (t != Op::NUL) { + if (c.pk) { + chkrc(d[0].ind[i] == 0); // even DEL has PK in post data + if (t == Op::INS) { + chkrc(d[1].ind[i] == -1); + } else if (t == Op::DEL) { +#ifdef ndb_event_cares_about_pk_pre_data + chkrc(d[1].ind[i] == -1); +#endif + } else { +#ifdef ndb_event_cares_about_pk_pre_data + chkrc(d[1].ind[i] == 0); +#endif + } + } else { + if (t == Op::INS) { + chkrc(d[0].ind[i] >= 0); + chkrc(d[1].ind[i] == -1); + } else if (t == Op::DEL) { + chkrc(d[0].ind[i] == -1); + chkrc(d[1].ind[i] >= 0); + } else if (op->kind == Op::OP) { + chkrc(d[0].ind[i] >= 0); + chkrc(d[1].ind[i] >= 0); + } + } + } + } + return 0; +} + +static Comp* +comptype(Op::Type t1, Op::Type t2) // only non-NUL +{ + uint i; + for (i = 0; i < g_ncomp; i++) + if (g_comp[i].t1 == t1 && g_comp[i].t2 == t2) + return &g_comp[i]; + return 0; +} + +static void +copycol(const Col& c, const Data& d1, Data& d3) +{ + if ((d3.ind[c.no] = d1.ind[c.no]) != -1) + memmove(d3.ptr[c.no], d1.ptr[c.no], c.size); +} + +static void +copykeys(const Data& d1, Data& d3) +{ + uint i; + for (i = 0; i < g_ncol; i++) { + const Col& c = g_col[i]; + if (c.pk) + copycol(c, d1, d3); + } +} + +static void +copydata(const Data& d1, Data& d3) +{ + uint i; + for (i = 0; i < g_ncol; i++) { + const Col& c = g_col[i]; + copycol(c, d1, d3); + } +} + +static void +copyop(const Op* op1, Op* op3) +{ + op3->type = op1->type; + copydata(op1->data[0], op3->data[0]); + copydata(op1->data[1], op3->data[1]); + Uint32 pk1_tmp; + reqrc(checkop(op3, pk1_tmp) == 0); +} + +// not needed for ops +static void +compdata(const Data& d1, const Data& d2, Data& d3) // d2 overrides d1 +{ + uint i; + for (i = 0; i < g_ncol; i++) { + const Col& c = g_col[i]; + const Data* d = 0; + if (d1.ind[i] == -1 && d2.ind[i] == -1) + d3.ind[i] = -1; + else if (d1.ind[i] == -1 && d2.ind[i] != -1) + d = &d2; + else if (d1.ind[i] != -1 && d2.ind[i] == -1) + d = &d1; + else + d = &d2; + if (d != 0) + copycol(c, *d, d3); + } +} + +static int +compop(const Op* op1, const Op* op2, Op* op3) // op1 o op2 = op3 +{ + Comp* comp; + if (op2->type == Op::NUL) { + copyop(op1, op3); + return 0; + } + if (op1->type == Op::NUL) { + copyop(op2, op3); + return 0; + } + chkrc((comp = comptype(op1->type, op2->type)) != 0); + op3->type = comp->t3; + copykeys(op2->data[0], op3->data[0]); + if (op3->type != Op::DEL) + copydata(op2->data[0], op3->data[0]); + if (op3->type != Op::INS) + copydata(op1->data[1], op3->data[1]); + Uint32 pk1_tmp; + reqrc(checkop(op3, pk1_tmp) == 0); + // not eliminating identical post-pre fields + return 0; +} + +static int +createevent() +{ + ll1("createevent"); + g_evt = 0; + g_dic = g_ndb->getDictionary(); + NdbDictionary::Event evt(g_evtname); + evt.setTable(*g_tab); + evt.addTableEvent(NdbDictionary::Event::TE_ALL); + // pk always + evt.addEventColumn("pk1"); + evt.addEventColumn("pk2"); + // simple cols + evt.addEventColumn("seq"); + evt.addEventColumn("cc1"); + if (g_dic->getEvent(evt.getName()) != 0) + chkdb(g_dic->dropEvent(evt.getName()) == 0); + chkdb(g_dic->createEvent(evt) == 0); + chkdb((g_evt = g_dic->getEvent(evt.getName())) != 0); + g_dic = 0; + return 0; +} + +static int +dropevent() +{ + ll1("dropevent"); + g_dic = g_ndb->getDictionary(); + chkdb(g_dic->dropEvent(g_evt->getName()) == 0); + g_evt = 0; + g_dic = 0; + return 0; +} + +static int +createeventop() +{ + ll1("createeventop"); +#ifdef version50 + uint bsz = 10 * g_opts.maxops; + chkdb((g_evt_op = g_ndb->createEventOperation(g_evt->getName(), bsz)) != 0); +#else + chkdb((g_evt_op = g_ndb->createEventOperation(g_evt->getName())) != 0); +#endif + uint i; + for (i = 0; i < g_ncol; i++) { + const Col& c = g_col[i]; + Data (&d)[2] = g_rec_ev->data; + switch (c.type) { + case NdbDictionary::Column::Unsigned: + case NdbDictionary::Column::Char: + chkdb((g_ra[0][i] = g_evt_op->getValue(c.name, (char*)d[0].ptr[i])) != 0); + chkdb((g_ra[1][i] = g_evt_op->getPreValue(c.name, (char*)d[1].ptr[i])) != 0); + break; + default: + assert(false); + break; + } + } + return 0; +} + +static int +dropeventop() +{ + ll1("dropeventop"); + chkdb(g_ndb->dropEventOperation(g_evt_op) == 0); + g_evt_op = 0; + return 0; +} + +static int +waitgci() // wait for event to be installed and for at least 1 GCI to pass +{ + const uint ngci = 3; + ll1("waitgci " << ngci); + Uint32 gci[2]; + uint i = 0; + while (1) { + chkdb((g_con = g_ndb->startTransaction()) != 0); + { // forced to exec a dummy op + Uint32 pk1; + char pk2[g_charlen]; + pk1 = g_maxpk; + memset(pk2, 0x20, g_charlen); + chkdb((g_op = g_con->getNdbOperation(g_tabname)) != 0); + chkdb(g_op->readTuple() == 0); + chkdb(g_op->equal("pk1", (char*)&pk1) == 0); + chkdb(g_op->equal("pk2", (char*)&pk2[0]) == 0); + chkdb(g_con->execute(Commit) == 0); + g_op = 0; + } + gci[i] = g_con->getGCI(); + g_ndb->closeTransaction(g_con); + g_con = 0; + if (i == 1 && gci[0] + ngci <= gci[1]) { + ll1("waitgci: " << gci[0] << " " << gci[1]); + break; + } + i = 1; + } + return 0; +} + +static int +makeop(Op* op, Uint32 pk1, Op::Type t, const Op* prev_op) +{ + op->type = t; + if (t != Op::INS) + copydata(prev_op->data[0], op->data[1]); + uint i; + for (i = 0; i < g_ncol; i++) { + const Col& c = getcol(i); + Data (&d)[2] = op->data; + if (i == getcol("pk1").no) { + d[0].pk1 = pk1; + d[0].ind[i] = 0; + continue; + } + if (i == getcol("pk2").no) { + sprintf(d[0].pk2, "%-*u", g_charlen, d[0].pk1); + d[0].ind[i] = 0; + continue; + } + if (t == Op::DEL) { + d[0].ind[i] = -1; + continue; + } + if (i == getcol("seq").no) { + d[0].seq = g_seq++; + d[0].ind[i] = 0; + continue; + } + uint u; + u = urandom(100); + if (c.nullable && u < 20) { + d[0].ind[i] = 1; + continue; + } + switch (c.type) { + case NdbDictionary::Column::Unsigned: + { + u = urandom(0); + Uint32* p = (Uint32*)d[0].ptr[i]; + *p = u; + } + break; + case NdbDictionary::Column::Char: + { + u = urandom(g_charlen); + char* p = (char*)d[0].ptr[i]; + uint j; + for (j = 0; j < g_charlen; j++) { + uint v = urandom(3); + p[j] = j < u ? "abcde"[v] : 0x20; + } + } + break; + default: + assert(false); + break; + } + d[0].ind[i] = 0; + } + Uint32 pk1_tmp = ~(Uint32)0; + chkrc(checkop(op, pk1_tmp) == 0); + reqrc(pk1 == pk1_tmp); + return 0; +} + +static void +makeop(Op* tot_op, Op* com_op, Uint32 pk1, Op::Type t) +{ + Op tmp_op; + tmp_op.kind = Op::OP; + Op* op = getop(); + reqrc(makeop(op, pk1, t, tot_op) == 0); + // add to end + Op* last_op = com_op; + while (last_op->next_op != 0) + last_op = last_op->next_op; + last_op->next_op = op; + // merge into chain head + tmp_op.init(); + reqrc(compop(com_op, op, &tmp_op) == 0); + copyop(&tmp_op, com_op); + // merge into total op + tmp_op.init(); + reqrc(compop(tot_op, op, &tmp_op) == 0); + copyop(&tmp_op, tot_op); + // counts + com_op->num_op += 1; + tot_op->num_op += 1; +} + +static void +makeops() +{ + ll1("makeops"); + uint resv = g_opts.opstr == 0 ? 2 * g_opts.maxpk : 0; // for final deletes + uint next = g_opts.opstr == 0 ? g_maxcom : strlen(g_opts.opstr); + Op tmp_op; + tmp_op.kind = Op::OP; + Uint32 pk1 = 0; + while (getfreeops() >= resv + 2 + next && pk1 < g_opts.maxpk) { + if (g_opts.opstr == 0) + pk1 = urandom(g_opts.maxpk); + ll2("makeops: pk1=" << pk1 << " free=" << getfreeops()); + // total op on the pk so far + // optype either NUL=initial/deleted or INS=created + Op* tot_op = g_pk_op[pk1]; + if (tot_op == 0) + tot_op = g_pk_op[pk1] = getop(); //1 + assert(tot_op->type == Op::NUL || tot_op->type == Op::INS); + // add new commit chain to end + Op* last_com = tot_op; + while (last_com->next_com != 0) + last_com = last_com->next_com; + Op* com_op = getop(); //2 + last_com->next_com = com_op; + // length of random chain + uint len = ~0; + if (g_opts.opstr == 0) + len = 1 + urandom(g_maxcom - 1); + ll2("makeops: com chain"); + uint n = 0; + while (1) { + // random or from g_opts.opstr + Op::Type t; + if (g_opts.opstr == 0) { + if (n == len) + break; + do { + t = (Op::Type)urandom(g_optypes); + } while (tot_op->type == Op::NUL && (t == Op::DEL || t == Op::UPD) || + tot_op->type == Op::INS && t == Op::INS); + } else { + uint m = strlen(g_opts.opstr); + uint k = tot_op->num_com + tot_op->num_op; + assert(k < m); + char c = g_opts.opstr[k]; + if (c == 'c') { + if (k + 1 == m) + pk1 += 1; + break; + } + const char* p = "idu"; + const char* q = strchr(p, c); + assert(q != 0); + t = (Op::Type)(q - p); + } + makeop(tot_op, com_op, pk1, t); + assert(tot_op->type == Op::NUL || tot_op->type == Op::INS); + n++; + } + tot_op->num_com += 1; + } + assert(getfreeops() >= resv); + // terminate with DEL if necessary + for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) { + Op* tot_op = g_pk_op[pk1]; + if (tot_op == 0) + continue; + if (tot_op->type == Op::NUL) + continue; + assert(g_opts.opstr == 0); + Op* last_com = tot_op; + while (last_com->next_com != 0) + last_com = last_com->next_com; + Op* com_op = getop(); //1 + last_com->next_com = com_op; + makeop(tot_op, com_op, pk1, Op::DEL); + assert(tot_op->type == Op::NUL); + tot_op->num_com += 1; + } +} + +static int +addndbop(Op* op) +{ + chkdb((g_op = g_con->getNdbOperation(g_tabname)) != 0); + switch (op->type) { + case Op::INS: + chkdb(g_op->insertTuple() == 0); + break; + case Op::DEL: + chkdb(g_op->deleteTuple() == 0); + break; + case Op::UPD: + chkdb(g_op->updateTuple() == 0); + break; + default: + assert(false); + break; + } + uint i; + for (i = 0; i < g_ncol; i++) { + const Col& c = getcol(i); + const Data& d = op->data[0]; + if (! c.pk) + continue; + chkdb(g_op->equal(c.name, (char*)d.ptr[i]) == 0); + } + if (op->type != Op::DEL) { + for (i = 0; i < g_ncol; i++) { + const Col& c = getcol(i); + const Data& d = op->data[0]; + if (c.pk) + continue; + if (d.ind[i] == -1) + continue; + const char* ptr = d.ind[i] == 0 ? (char*)d.ptr[i] : 0; + chkdb(g_op->setValue(c.name, ptr) == 0); + } + } + g_op = 0; + return 0; +} + +static int +runops() +{ + ll1("runops"); + Uint32 pk1; + const Op* com_op[g_maxpk]; + uint left = 0; + for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) { + com_op[pk1] = 0; + // total op on the pk + Op* tot_op = g_pk_op[pk1]; + if (tot_op == 0) + continue; + // first commit chain + assert(tot_op->next_com != 0); + com_op[pk1] = tot_op->next_com; + left++; + } + while (left != 0) { + pk1 = urandom(g_opts.maxpk); + if (com_op[pk1] == 0) + continue; + // do the ops in one transaction + ll2("runops: pk1=" << pk1); + chkdb((g_con = g_ndb->startTransaction()) != 0); + // first op in chain + Op* op = com_op[pk1]->next_op; + assert(op != 0); + while (op != 0) { + ll2("add op:" << *op); + chkrc(addndbop(op) == 0); + op = op->next_op; + } + chkdb(g_con->execute(Commit) == 0); + g_ndb->closeTransaction(g_con); + g_con = 0; + // next chain + com_op[pk1] = com_op[pk1]->next_com; + if (com_op[pk1] == 0) { + assert(left != 0); + left--; + } + } + assert(left == 0); + return 0; +} + +static int +matchevent(Op* ev) +{ + Op::Type t = ev->type; + Data (&d)[2] = ev->data; + // get PK + Uint32 pk1 = d[0].pk1; + chkrc(pk1 < g_opts.maxpk); + // on error repeat and print details + uint loop = 0; + while (loop <= 1) { + uint g_loglevel = loop == 0 ? g_opts.loglevel : 2; + ll1("matchevent: pk1=" << pk1 << " type=" << t); + ll2("EVT: " << *ev); + Op* tot_op = g_pk_op[pk1]; + Op* com_op = tot_op ? tot_op->next_com : 0; + uint cnt = 0; + bool ok = false; + while (com_op != 0) { + ll2("COM: " << *com_op); + Op* op = com_op->next_op; + assert(op != 0); + while (op != 0) { + ll2("---: " << *op); + op = op->next_op; + } + if (com_op->type != Op::NUL) { + if (com_op->type == t) { + const Data (&d2)[2] = com_op->data; + if (t == Op::INS && d2[0].seq == d[0].seq || + t == Op::DEL && d2[1].seq == d[1].seq || + t == Op::UPD && d2[0].seq == d[0].seq) { + if (cnt == g_ev_cnt[pk1]) { + if (! com_op->match) { + ll2("match pos " << cnt); + ok = com_op->match = true; + } else { + ll2("duplicate match"); + } + } else { + ll2("match bad pos event=" << g_ev_cnt[pk1] << " op=" << cnt); + } + } + } + cnt++; + } + com_op = com_op->next_com; + } + if (ok) + return 0; + ll2("no match"); + if (g_loglevel >= 2) + return -1; + loop++; + } + return 0; +} + +static int +matchevents() +{ + uint nomatch = 0; + Uint32 pk1; + for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) { + Op* tot_ev = g_pk_ev[pk1]; + if (tot_ev == 0) + continue; + Op* com_ev = tot_ev->next_com; + while (com_ev != 0) { + if (matchevent(com_ev) < 0) + nomatch++; + g_ev_cnt[pk1]++; + com_ev = com_ev->next_com; + } + } + chkrc(nomatch == 0); + return 0; +} + +static int +matchops() +{ + Uint32 pk1; + for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) { + Op* tot_op = g_pk_op[pk1]; + if (tot_op == 0) + continue; + Op* com_op = tot_op->next_com; + while (com_op != 0) { + if (com_op->type != Op::NUL && ! com_op->match) { + ll0("COM: " << *com_op); + Op* op = com_op->next_op; + assert(op != 0); + while (op != 0) { + ll0("---: " << *op); + op = op->next_op; + } + ll0("no matching event"); + return -1; + } + com_op = com_op->next_com; + } + } + return 0; +} + +static int +runevents() +{ + ll1("runevents"); + NdbEventOperation* evt_op; + uint npoll = 3; + while (npoll != 0) { + npoll--; + int ret; + ll1("poll"); + ret = g_ndb->pollEvents(1000); + if (ret <= 0) + continue; + while (1) { + g_rec_ev->init(); + Data (&d)[2] = g_rec_ev->data; +#ifdef version50 + int overrun = g_opts.maxops; + chkdb((ret = g_evt_op->next(&overrun)) >= 0); + chkrc(overrun == 0); + if (ret == 0) + break; +#else + NdbEventOperation* tmp_op = g_ndb->nextEvent(); + if (tmp_op == 0) + break; + reqrc(g_evt_op == tmp_op); +#endif + chkrc(seteventtype(g_rec_ev, g_evt_op->getEventType()) == 0); + // get indicators + { int i, j; + for (j = 0; j < 2; j++) + for (i = 0; i < g_ncol; i++) + d[j].ind[i] = g_ra[j][i]->isNULL(); + } + ll2("runevents: EVT: " << *g_rec_ev); + // check basic sanity + Uint32 pk1 = ~(Uint32)0; + chkrc(checkop(g_rec_ev, pk1) == 0); + // add to events + chkrc(getfreeevs() >= 2); + Op* tot_ev = g_pk_ev[pk1]; + if (tot_ev == 0) + tot_ev = g_pk_ev[pk1] = getev(); //1 + Op* last_com = tot_ev; + while (last_com->next_com != 0) + last_com = last_com->next_com; + // copy and add + Op* ev = getev(); //3 + copyop(g_rec_ev, ev); + last_com->next_com = ev; + } + } + chkrc(matchevents() == 0); + chkrc(matchops() == 0); + return 0; +} + +static void +setseed(int n) +{ + uint seed; + if (n == -1) { + if (g_opts.seed == 0) + return; + if (g_opts.seed != -1) + seed = (uint)g_opts.seed; + else + seed = 1 + (ushort)getpid(); + } else { + if (g_opts.seed != 0) + return; + seed = n; + } + ll0("seed=" << seed); + srandom(seed); +} + +static int +runtest() +{ + setseed(-1); + chkrc(createtable() == 0); + chkrc(createevent() == 0); + uint n; + for (n = 0; n < g_opts.loop; n++) { + ll0("loop " << n); + setseed(n); + resetmem(); + g_rec_ev = getev(); + chkrc(createeventop() == 0); + chkdb(g_evt_op->execute() == 0); + chkrc(waitgci() == 0); + makeops(); + chkrc(runops() == 0); + chkrc(runevents() == 0); + chkrc(dropeventop() == 0); + } + chkrc(dropevent() == 0); + chkrc(droptable() == 0); + return 0; +} + +NDB_STD_OPTS_VARS; + +static struct my_option +my_long_options[] = +{ + NDB_STD_OPTS("test_event_merge"), + { "abort-on-error", 1008, "Do abort() on any error", + (gptr*)&g_opts.abort_on_error, (gptr*)&g_opts.abort_on_error, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "loglevel", 1001, "Logging level in this program (default 0)", + (gptr*)&g_opts.loglevel, (gptr*)&g_opts.loglevel, 0, + GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "loop", 1002, "Number of test loops (default 1, 0=forever)", + (gptr*)&g_opts.loop, (gptr*)&g_opts.loop, 0, + GET_INT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0 }, + { "maxops", 1003, "Number of PK operations (default 2000)", + (gptr*)&g_opts.maxops, (gptr*)&g_opts.maxops, 0, + GET_UINT, REQUIRED_ARG, 2000, 0, g_maxops, 0, 0, 0 }, + { "maxpk", 1004, "Number of different PK values (default 10)", + (gptr*)&g_opts.maxpk, (gptr*)&g_opts.maxpk, 0, + GET_UINT, REQUIRED_ARG, 10, 1, g_maxpk, 0, 0, 0 }, + { "opstr", 1005, "Ops to run e.g. idiucdc (c = commit, default random)", + (gptr*)&g_opts.opstr, (gptr*)&g_opts.opstr, 0, + GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "seed", 1006, "Random seed (0=loop number, default -1=random)", + (gptr*)&g_opts.seed, (gptr*)&g_opts.seed, 0, + GET_INT, REQUIRED_ARG, -1, 0, 0, 0, 0, 0 }, + { "separate-events", 1007, "Do not combine events per GCI >5.0", + (gptr*)&g_opts.separate_events, (gptr*)&g_opts.separate_events, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "use-table", 1008, "Use existing table 'tem1'", + (gptr*)&g_opts.use_table, (gptr*)&g_opts.use_table, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, + 0, 0, 0, + GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 } +}; + +static void +usage() +{ + my_print_help(my_long_options); +} + +static int +checkopts() +{ + if (g_opts.opstr != 0) { + const char* s = g_opts.opstr; + uint n = strlen(s); + if (n < 3 || s[0] != 'i' || s[n-2] != 'd' || s[n-1] != 'c') + return -1; + while (*s != 0) + if (strchr("iduc", *s++) == 0) + return -1; + } + return 0; +} + +int +main(int argc, char** argv) +{ + ndb_init(); + const char* progname = + strchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0]; + uint i; + ndbout << progname; + for (i = 1; i < argc; i++) + ndbout << " " << argv[i]; + ndbout << endl; + int ret; + ret = handle_options(&argc, &argv, my_long_options, ndb_std_get_one_option); + if (ret != 0 || argc != 0 || checkopts() != 0) + return NDBT_ProgramExit(NDBT_WRONGARGS); + g_ncc = new Ndb_cluster_connection(); + if (g_ncc->connect(30) == 0) { + g_ndb = new Ndb(g_ncc, "TEST_DB"); + if (g_ndb->init() == 0 && g_ndb->waitUntilReady(30) == 0) { + if (runtest() == 0) + return NDBT_ProgramExit(NDBT_OK); + } + } + delete g_ndb; + delete g_ncc; + return NDBT_ProgramExit(NDBT_FAILED); +} diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index 8b44594a9b5..59f51044b51 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -413,6 +413,27 @@ max-time: 500 cmd: testScan args: -n ScanParallelism +max-time: 500 +cmd: testNodeRestart +args: -n Bug15587 T1 + +max-time: 500 +cmd: testNodeRestart +args: -n Bug15632 T1 + +max-time: 500 +cmd: testNodeRestart +args: -n Bug15685 T1 + +# OLD FLEX +max-time: 500 +cmd: flexBench +args: -c 25 -t 10 + +max-time: 500 +cmd: flexHammer +args: -r 5 -t 32 + # # DICT TESTS max-time: 1500 diff --git a/ndb/test/src/HugoCalculator.cpp b/ndb/test/src/HugoCalculator.cpp index 8e01f6442bb..d4d7ca2f95f 100644 --- a/ndb/test/src/HugoCalculator.cpp +++ b/ndb/test/src/HugoCalculator.cpp @@ -17,7 +17,6 @@ #include <ndb_global.h> #include "HugoCalculator.hpp" #include <NDBT.hpp> -#include <Base64.hpp> static Uint32 diff --git a/ndb/tools/ndb_error_reporter b/ndb/tools/ndb_error_reporter new file mode 100755 index 00000000000..2b5aadb6171 --- /dev/null +++ b/ndb/tools/ndb_error_reporter @@ -0,0 +1,88 @@ +#!/usr/bin/perl -w + +use strict; + +if(@ARGV < 1) +{ + print STDERR "Usage:\n"; + print STDERR "\tndb_error_reporter config.ini [username] [--fs]\n\n"; + print STDERR "\tusername is a user that you can use to ssh into\n"; + print STDERR "\t all of your nodes with.\n\n"; + print STDERR "\t--fs means include the filesystems in the report\n"; + print STDERR "\t WARNING: This may require a lot of disk space.\n"; + print STDERR "\t Only use this option when asked to.\n\n"; + exit(1); +} + +my $config_file= $ARGV[0]; +my $config_get_fs= 0; +my $config_username= ''; +if(defined($ARGV[1])) +{ + $config_get_fs= 1 if $ARGV[1] eq '--fs'; + $config_username= $ARGV[1].'@' if $ARGV[1] ne '--fs'; + $config_get_fs= (defined $ARGV[2] && $ARGV[2] eq '--fs')?1:$config_get_fs; +} + +if(!stat($config_file)) +{ + print STDERR "Cannot open configuration file.\n\n"; + exit(1); +} + +my @nodes= split ' ',`ndb_config --config-file=$ARGV[0] --nodes --query=id --type=ndbd`; + +push @nodes, split ' ',`ndb_config --config-file=$ARGV[0] --nodes --query=id --type=ndb_mgmd`; + +sub config { + my $nodeid= shift; + my $query= shift; + my $res= `ndb_config --config-file=$ARGV[0] --id=$nodeid --query=$query`; + chomp $res; + $res; +} + +my @t= localtime(); +my $reportdir= sprintf('ndb_error_report_%u%02u%02u%02u%02u%02u', + ($t[5]+1900),($t[4]+1),$t[3],$t[2],$t[1],$t[0]); + +if(stat($reportdir) || stat($reportdir.'tar.bz2')) +{ + print STDERR "It looks like another ndb_error_report process is running.\n"; + print STDERR "If that is not the case, remove the ndb_error_report directory"; + print STDERR " and run ndb_error_report again.\n\n"; + exit(1); +} + +mkdir($reportdir); + +foreach my $node (@nodes) +{ + print "\n\n Copying data from node $node". + (($config_get_fs)?" with filesystem":""). + "\n\n"; + my $recurse= ($config_get_fs)?'-r ':''; + system 'scp '.$recurse.$config_username.config($node,'host'). + ':'.config($node,'datadir')."/ndb_".$node."* ". + "$reportdir/\n"; +} + +print "\n\n Copying configuration file...\n\n\t$config_file\n\n"; +system "cp $config_file $reportdir/"; + +my $r = system 'bzip2 2>&1 > /dev/null < /dev/null'; +my $outfile; +if($r==0) +{ + $outfile= "$reportdir.tar.bz2"; + system "tar c $reportdir|bzip2 > $outfile"; +} +else +{ + $outfile= "$reportdir.tar.gz"; + system "tar c $reportdir|gzip > $outfile"; +} + +system "rm -rf $reportdir"; + +print "\n\nPlease attach $outfile to your error report\n\n"; diff --git a/ndb/tools/ndb_size.pl b/ndb/tools/ndb_size.pl index 64a20423636..e0085c619f0 100644 --- a/ndb/tools/ndb_size.pl +++ b/ndb/tools/ndb_size.pl @@ -26,24 +26,33 @@ use HTML::Template; # BUGS # ---- # - enum/set is 0 byte storage! Woah - efficient! +# - DECIMAL is 0 byte storage. A bit too efficient. # - some float stores come out weird (when there's a comma e.g. 'float(4,1)') # - no disk data values # - computes the storage requirements of views (and probably MERGE) # - ignores character sets. my $template = HTML::Template->new(filename => 'ndb_size.tmpl', - die_on_bad_params => 0); + die_on_bad_params => 0) + or die "Could not open ndb_size.tmpl."; my $dbh; +if(@ARGV < 3 || $ARGV[0] eq '--usage' || $ARGV[0] eq '--help') +{ + print STDERR "Usage:\n"; + print STDERR "\tndb_size.pl database hostname user password\n\n"; + print STDERR "If you need to specify a port number, use host:port\n\n"; + exit(1); +} + { my $database= $ARGV[0]; my $hostname= $ARGV[1]; - my $port= $ARGV[2]; - my $user= $ARGV[3]; - my $password= $ARGV[4]; - my $dsn = "DBI:mysql:database=$database;host=$hostname;port=$port"; - $dbh= DBI->connect($dsn, $user, $password); + my $user= $ARGV[2]; + my $password= $ARGV[3]; + my $dsn = "DBI:mysql:database=$database;host=$hostname"; + $dbh= DBI->connect($dsn, $user, $password) or exit(1); $template->param(db => $database); $template->param(dsn => $dsn); } @@ -55,6 +64,14 @@ my $tables = $dbh->selectall_arrayref("show tables"); my @table_size; +my @dbDataMemory; +my @dbIndexMemory; +my @NoOfAttributes; +my @NoOfIndexes; +my @NoOfTables; +$NoOfTables[$_]{val} = @{$tables} foreach 0..$#releases; + + sub align { my($to,@unaligned) = @_; my @aligned; @@ -68,9 +85,8 @@ foreach(@{$tables}) { my $table= @{$_}[0]; my @columns; - my $info= $dbh->selectall_hashref("describe ".$dbh->quote($table),"Field"); - my @count = $dbh->selectrow_array("select count(*) from " - .$dbh->quote($table)); + my $info= $dbh->selectall_hashref('describe `'.$table.'`',"Field"); + my @count = $dbh->selectrow_array('select count(*) from `'.$table.'`'); my %columnsize; # used for index calculations # We now work out the DataMemory usage @@ -130,16 +146,19 @@ foreach(@{$tables}) elsif($type =~ /varchar/ || $type =~ /varbinary/) { my $fixed= 1+$size; - my @dynamic=$dbh->selectrow_array("select avg(length(" - .$dbh->quote($name) - .")) from ".$dbh->quote($table)); + my @dynamic=$dbh->selectrow_array("select avg(length(`" + .$name. + ."`)) from `".$table.'`'); $dynamic[0]=0 if !$dynamic[0]; @realsize= ($fixed,$fixed,ceil($dynamic[0])); } elsif($type =~ /binary/ || $type =~ /char/) {@realsize=($size,$size,$size)} elsif($type =~ /text/ || $type =~ /blob/) - {@realsize=(256,256,1)} # FIXME check if 5.1 is correct + { + @realsize=(256,256,1); + $NoOfTables[$_]{val} += 1 foreach 0..$#releases; # blob uses table + } # FIXME check if 5.1 is correct @realsize= align(4,@realsize); @@ -166,7 +185,7 @@ foreach(@{$tables}) # we can still connect to pre-5.0 mysqlds. my %indexes; { - my $sth= $dbh->prepare("show index from "$dbh->quote($table)); + my $sth= $dbh->prepare("show index from `".$table.'`'); $sth->execute; while(my $i = $sth->fetchrow_hashref) { @@ -257,7 +276,51 @@ foreach(@{$tables}) IndexMemory=>\@IndexMemory, }; + + $dbDataMemory[$_]{val} += $DataMemory[$_]{val} foreach 0..$#releases; + $dbIndexMemory[$_]{val} += $IndexMemory[$_]{val} foreach 0..$#releases; + $NoOfAttributes[$_]{val} += @columns foreach 0..$#releases; + $NoOfIndexes[$_]{val} += @indexes foreach 0..$#releases; +} + +my @NoOfTriggers; +# for unique hash indexes +$NoOfTriggers[$_]{val} += $NoOfIndexes[$_]{val}*3 foreach 0..$#releases; +# for ordered index +$NoOfTriggers[$_]{val} += $NoOfIndexes[$_]{val} foreach 0..$#releases; + +my @ParamMemory; +foreach (0..$#releases) { + $ParamMemory[0]{releases}[$_]{val}= POSIX::ceil(200*$NoOfAttributes[$_]{val}/1024); + $ParamMemory[0]{name}= 'Attributes'; + + $ParamMemory[1]{releases}[$_]{val}= 20*$NoOfTables[$_]{val}; + $ParamMemory[1]{name}= 'Tables'; + + $ParamMemory[2]{releases}[$_]{val}= 10*$NoOfIndexes[$_]{val}; + $ParamMemory[2]{name}= 'OrderedIndexes'; + + $ParamMemory[3]{releases}[$_]{val}= 15*$NoOfIndexes[$_]{val}; + $ParamMemory[3]{name}= 'UniqueHashIndexes'; } $template->param(tables => \@table_size); +$template->param(Parameters => [{name=>'DataMemory (kb)', + releases=>\@dbDataMemory}, + {name=>'IndexMemory (kb)', + releases=>\@dbIndexMemory}, + {name=>'MaxNoOfTables', + releases=>\@NoOfTables}, + {name=>'MaxNoOfAttributes', + releases=>\@NoOfAttributes}, + {name=>'MaxNoOfOrderedIndexes', + releases=>\@NoOfIndexes}, + {name=>'MaxNoOfUniqueHashIndexes', + releases=>\@NoOfIndexes}, + {name=>'MaxNoOfTriggers', + releases=>\@NoOfTriggers} + ] + ); +$template->param(ParamMemory => \@ParamMemory); + print $template->output; diff --git a/ndb/tools/ndb_size.tmpl b/ndb/tools/ndb_size.tmpl index d83d5d2c6af..dc02b5a5970 100644 --- a/ndb/tools/ndb_size.tmpl +++ b/ndb/tools/ndb_size.tmpl @@ -13,18 +13,58 @@ td,th { border: 1px solid black } <h1>MySQL Cluster analysis for <TMPL_VAR NAME="db" escape="html"></h1> <p>This is an automated analysis of the <TMPL_VAR NAME="DSN" escape="html"> database for migration into <a href="http://www.mysql.com/">MySQL</a> Cluster. No warranty is made to the accuracy of the information.</p> -<p>This information should be valid for MySQL 4.1</p> +<p>This information should be valid for MySQL 4.1 and 5.0. Since 5.1 is not a final release yet, the numbers should be used as a guide only.</p> +<h2>Parameter Settings</h2> +<p><b>NOTE</b> the configuration parameters below do not take into account system tables and other requirements.</p> +<table> + <tr> + <th>Parameter</th> + <TMPL_LOOP NAME=releases> + <th><TMPL_VAR NAME=rel></th> + </TMPL_LOOP> + </tr> +<TMPL_LOOP NAME=Parameters> + <tr> + <td><TMPL_VAR NAME=name></td> + <TMPL_LOOP NAME=releases> + <td><TMPL_VAR NAME=val></td> + </TMPL_LOOP> + </tr> +</TMPL_LOOP> +</table> + +<h2>Memory usage because of parameters</h2> + +<p>Usage is in kilobytes. Actual usage will vary as you should set the parameters larger than those listed in the table above.</p> +<table> + <tr> + <th>Parameter</th> + <TMPL_LOOP NAME=releases> + <th><TMPL_VAR NAME=rel></th> + </TMPL_LOOP> + </tr> +<TMPL_LOOP NAME=ParamMemory> + <tr> + <td><TMPL_VAR NAME=name></td> + <TMPL_LOOP NAME=releases> + <td><TMPL_VAR NAME=val></td> + </TMPL_LOOP> + </tr> +</TMPL_LOOP> +</table> + +<h2>Table List</h2> <ul> <TMPL_LOOP NAME="tables"> -<li><TMPL_VAR NAME="table"></li> +<li><a href="#<TMPL_VAR NAME="table">"><TMPL_VAR NAME="table"></a></li> </TMPL_LOOP> </ul> <hr/> <TMPL_LOOP NAME="tables"> -<h2><TMPL_VAR NAME="table"></h2> +<h2><a name="<TMPL_VAR NAME="table">"><TMPL_VAR NAME="table"></a></h2> <table> <tr> <th>Column</th> diff --git a/netware/BUILD/compile-linux-tools b/netware/BUILD/compile-linux-tools index c85fced5739..14422ea5a3f 100755 --- a/netware/BUILD/compile-linux-tools +++ b/netware/BUILD/compile-linux-tools @@ -18,7 +18,6 @@ path=`dirname $0` if test -e "Makefile"; then make -k clean; fi # remove files -rm -f NEW-RPMS/* rm -f */.deps/*.P rm -f */*.linux @@ -29,7 +28,8 @@ rm -f */*.linux ./configure --without-innodb --without-docs # build tools only -make clean all-local +make clean +make # Create mysql_version.h which was deleted my previous step ./config.status include/mysql_version.h @@ -56,7 +56,7 @@ make clean all-local # copying required linux tools cp extra/comp_err extra/comp_err.linux cp libmysql/conf_to_src libmysql/conf_to_src.linux -cp libmysql_r/conf_to_src libmysql_r/conf_to_src.linux +#cp libmysql_r/conf_to_src libmysql_r/conf_to_src.linux cp sql/gen_lex_hash sql/gen_lex_hash.linux cp strings/conf_to_src strings/conf_to_src.linux diff --git a/netware/BUILD/compile-netware-END b/netware/BUILD/compile-netware-END index 60ef428b2a9..f7da0d9596e 100755 --- a/netware/BUILD/compile-netware-END +++ b/netware/BUILD/compile-netware-END @@ -12,7 +12,6 @@ path=`dirname $0` if test -e "Makefile"; then make -k clean; fi # remove files -rm -f NEW-RPMS/* rm -f */.deps/*.P rm -rf Makefile.in.bk diff --git a/netware/BUILD/compile-netware-src b/netware/BUILD/compile-netware-src index df7f6fcdd1a..f4e8a53ffea 100644 --- a/netware/BUILD/compile-netware-src +++ b/netware/BUILD/compile-netware-src @@ -21,7 +21,6 @@ if test -e "Makefile"; then fi # remove other files -rm -f NEW-RPMS/* rm -f */.deps/*.P rm -rf Makefile.in.bk diff --git a/netware/Makefile.am b/netware/Makefile.am index be59efd1deb..ab88d97f9bc 100644 --- a/netware/Makefile.am +++ b/netware/Makefile.am @@ -40,10 +40,10 @@ netware_build_files = client/mysql.def client/mysqladmin.def \ link_sources: set -x; \ for f in $(netware_build_files); do \ - rm -f $(srcdir)/../$$f; \ + rm -f ../$$f; \ org=`echo $$f | sed -e 's/.*\/\(.*\)/\1/g'`; \ - @LN_CP_F@ $(srcdir)/$$org $(srcdir)/../$$f; \ - done; + @LN_CP_F@ $(srcdir)/$$org ../$$f; \ + done else EXTRA_DIST= comp_err.def init_db.sql install_test_db.ncf \ libmysql.def libmysql.imp \ diff --git a/netware/libmysql.def b/netware/libmysql.def index fea117dedd1..8a34754e092 100644 --- a/netware/libmysql.def +++ b/netware/libmysql.def @@ -7,5 +7,6 @@ COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Res DESCRIPTION "MySQL Client Library" VERSION 4, 0 AUTOUNLOAD +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/my_print_defaults.def b/netware/my_print_defaults.def index d88c5adf4cc..778a5204ebd 100644 --- a/netware/my_print_defaults.def +++ b/netware/my_print_defaults.def @@ -4,7 +4,7 @@ MODULE libc.nlm COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Print Defaults Tool" -VERSION 5, 0, 8 +VERSION 5, 0, 17 STACKSIZE 32767 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/myisamlog.def b/netware/myisamlog.def index 3580c870c10..553a818a2ae 100644 --- a/netware/myisamlog.def +++ b/netware/myisamlog.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL MyISAM Table Log Tool" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL MyISAM Table Log Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/myisampack.def b/netware/myisampack.def index a6946982236..d1f85fe03f8 100644 --- a/netware/myisampack.def +++ b/netware/myisampack.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL MyISAM Table Pack Tool" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL MyISAM Table Pack Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysql_install_db.def b/netware/mysql_install_db.def index 1657b7c17af..372bbf15570 100644 --- a/netware/mysql_install_db.def +++ b/netware/mysql_install_db.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Install" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Initial Database Installer" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysql_test_run.c b/netware/mysql_test_run.c index 92ed89b4770..6bab2f0149c 100644 --- a/netware/mysql_test_run.c +++ b/netware/mysql_test_run.c @@ -349,6 +349,8 @@ void start_master() add_arg(&al, "--tmpdir=%s", mysql_tmp_dir); add_arg(&al, "--language=%s", lang_dir); add_arg(&al, "--log-bin-trust-routine-creators"); + add_arg(&al, "--log-slow-queries"); + add_arg(&al, "--log-queries-not-using-indexes"); #ifdef DEBUG //only for debug builds add_arg(&al, "--debug"); #endif @@ -523,6 +525,8 @@ void start_slave() add_arg(&al, "-O"); add_arg(&al, "slave_net_timeout=10"); add_arg(&al, "--log-bin-trust-routine-creators"); + add_arg(&al, "--log-slow-queries"); + add_arg(&al, "--log-queries-not-using-indexes"); #ifdef DEBUG //only for debug builds add_arg(&al, "--debug"); #endif @@ -1173,6 +1177,9 @@ void setup(char *file) setenv("MYSQL",file_path,1); snprintf(file_path, PATH_MAX*2, "%s/mysqlshow --no-defaults --user=root --port=%u", bin_dir, master_port); setenv("MYSQL_SHOW",file_path,1); + snprintf(file_path, PATH_MAX*2, "%s/mysqlcheck --no-defaults -uroot --port=%u", bin_dir, master_port); + setenv("MYSQL_CHECK",file_path,1); + } /****************************************************************************** diff --git a/netware/mysqladmin.def b/netware/mysqladmin.def index e7f2d90bf9e..6532cab84a0 100644 --- a/netware/mysqladmin.def +++ b/netware/mysqladmin.def @@ -6,7 +6,7 @@ SCREENNAME "MySQL Admin[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Admin Tool" VERSION 4, 0 -STACKSIZE 32767 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqlbinlog.def b/netware/mysqlbinlog.def index 3e75cf07a57..aced63429c5 100644 --- a/netware/mysqlbinlog.def +++ b/netware/mysqlbinlog.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Binary Log Dump Tool[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Binary Log Dump Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqlcheck.def b/netware/mysqlcheck.def index cb70c1b394d..1b90b2a1dbe 100644 --- a/netware/mysqlcheck.def +++ b/netware/mysqlcheck.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Check Tool[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Check Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqld_safe.def b/netware/mysqld_safe.def index 2a9ef04b47d..ff3f1924906 100644 --- a/netware/mysqld_safe.def +++ b/netware/mysqld_safe.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Database Server" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Database Server Monitor" VERSION 4, 0 +STACKSIZE 32768 MULTIPLE XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqldump.def b/netware/mysqldump.def index 811c53ce5f6..5d7999c789f 100644 --- a/netware/mysqldump.def +++ b/netware/mysqldump.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Dump Tool[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Dump Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqlimport.def b/netware/mysqlimport.def index dc9af18aa09..f98d8021a73 100644 --- a/netware/mysqlimport.def +++ b/netware/mysqlimport.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Import[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Import Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/perror.def b/netware/perror.def index 18c95d8b236..d67bd6191b4 100644 --- a/netware/perror.def +++ b/netware/perror.def @@ -5,6 +5,7 @@ MODULE libc.nlm COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Error Code Description Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/pstack/Makefile.am b/pstack/Makefile.am index 77f84d212cd..20d5d8314ce 100644 --- a/pstack/Makefile.am +++ b/pstack/Makefile.am @@ -20,7 +20,7 @@ # SUBDIRS = aout -INCLUDES = -I$(top_srcdir)/include +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include noinst_HEADERS = bucomm.h debug.h ieee.h budbg.h demangle.h \ linuxthreads.h pstack.h pstacktrace.h SRC= bucomm.c filemode.c linuxthreads.c rddbg.c \ diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 2f6dd8c52e5..394e24c7c32 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -85,9 +85,10 @@ CLEANFILES = @server_scripts@ \ mysql_find_rows \ mysqlhotcopy \ mysqldumpslow \ + mysql_explain_log \ + mysql_tableinfo \ mysqld_multi \ make_win_src_distribution \ - make_win_binary_distribution \ mysql_create_system_tables DISTCLEANFILES = mysqlbug diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 5767728fe4f..d4d96d38d14 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -193,6 +193,7 @@ if [ $BASE_SYSTEM = "netware" ] ; then libname=`basename $i .a` $MV $i $BASE/lib/$libname.lib done + rm -f $BASE/lib/*.la fi copyfileto $BASE/include config.h include/* @@ -288,6 +289,9 @@ if [ $BASE_SYSTEM = "netware" ] ; then $BASE/support-files/mysql*.spec \ $BASE/support-files/mysql-log-rotate \ $BASE/support-files/binary-configure \ + $BASE/support-files/build-tags \ + $BASE/support-files/MySQL-shared-compat.spec \ + $BASE/support-files/ndb-config-2-node.ini \ $BASE/INSTALL-BINARY \ $BASE/MySQLEULA.txt else diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh index ea3ca66db6e..53f05c131ac 100644 --- a/scripts/make_win_src_distribution.sh +++ b/scripts/make_win_src_distribution.sh @@ -199,7 +199,7 @@ copy_dir_files() print_debug "Creating directory '$arg'" mkdir $BASE/$arg fi - for i in *.c *.cpp *.h *.ih *.i *.ic *.asm *.def *.hpp *.dsp *.dsw \ + for i in *.c *.cpp *.h *.ih *.i *.ic *.asm *.def *.hpp \ README INSTALL* LICENSE AUTHORS NEWS ChangeLog \ *.inc *.test *.result *.pem Moscow_leap des_key_file \ *.vcproj *.sln *.dat *.000001 *.require *.opt @@ -342,7 +342,7 @@ mv $BASE/sql/sql_yacc.cpp-new $BASE/sql/sql_yacc.cpp # # Search the tree for plain text files and adapt the line end marker # -find $BASE \( -name "*.dsp" -o -name "*.dsw" -o -name "*.cnf" -o -name "*.ini" \ +find $BASE \( -name "*.cnf" -o -name "*.ini" \ -o -name COPYING -o -name ChangeLog -o -name EXCEPTIONS-CLIENT \ -o -name "INSTALL*" -o -name LICENSE -o -name "README*" \ -o -name "*.vcproj" -o -name "*.sln" \) -type f -print \ diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index d1b0c35266e..ed0f9a6c68f 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -29,7 +29,7 @@ ALTER TABLE user add Grant_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,a ALTER TABLE host add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Index_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Alter_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL; ALTER TABLE db add Grant_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add References_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Index_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Alter_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL; ---- Fix privileges for old tables +-- Fix privileges for old tables UPDATE user SET Grant_priv=File_priv,References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; UPDATE db SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; UPDATE host SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 873aff251db..a584c384712 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -11,6 +11,7 @@ # executing mysqld_safe KILL_MYSQLD=1; +MYSQLD= trap '' 1 2 3 15 # we shouldn't let anyone kill us @@ -174,14 +175,6 @@ export MYSQL_HOME user=@MYSQLD_USER@ niceness=0 -# Use the mysqld-max binary by default if the user doesn't specify a binary -if test -x $ledir/mysqld-max -then - MYSQLD=mysqld-max -else - MYSQLD=mysqld -fi - # these rely on $DATADIR by default, so we'll set them later on pid_file= err_log= @@ -220,6 +213,16 @@ then chown $user $mysql_unix_port_dir fi +# Use the mysqld-max binary by default if the user doesn't specify a binary +if test -z "$MYSQLD" +then + if test -x $ledir/mysqld-max + then + MYSQLD=mysqld-max + else + MYSQLD=mysqld + fi +fi if test ! -x $ledir/$MYSQLD then diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 1c5cd6a4faf..bf53aa78e15 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -252,6 +252,7 @@ if ( defined $opt{regexp} ) { my $sth_dbs = $dbh->prepare("show databases"); $sth_dbs->execute; while ( my ($db_name) = $sth_dbs->fetchrow_array ) { + next if $db_name =~ m/^information_schema$/i; push @db_desc, { 'src' => $db_name, 't_regex' => $t_regex } if ( $db_name =~ m/$opt{regexp}/o ); } } diff --git a/server-tools/instance-manager/Makefile.am b/server-tools/instance-manager/Makefile.am index b872adca09d..7449735f0bf 100644 --- a/server-tools/instance-manager/Makefile.am +++ b/server-tools/instance-manager/Makefile.am @@ -15,7 +15,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA INCLUDES= @ZLIB_INCLUDES@ -I$(top_srcdir)/include \ - $(openssl_includes) -I$(top_builddir)/include + @openssl_includes@ @yassl_includes@ -I$(top_builddir)/include DEFS= -DMYSQL_INSTANCE_MANAGER -DMYSQL_SERVER @@ -53,12 +53,12 @@ libnet_a_LIBADD= $(top_builddir)/sql/password.$(OBJEXT) \ CLEANFILES= net_serv.cc client_settings.h net_serv.cc: - rm -f $(srcdir)/net_serv.cc - @LN_CP_F@ $(top_srcdir)/sql/net_serv.cc $(srcdir)/net_serv.cc + rm -f net_serv.cc + @LN_CP_F@ $(top_srcdir)/sql/net_serv.cc net_serv.cc client_settings.h: - rm -f $(srcdir)/client_settings.h - @LN_CP_F@ $(top_srcdir)/sql/client_settings.h $(srcdir)/client_settings.h + rm -f client_settings.h + @LN_CP_F@ $(top_srcdir)/sql/client_settings.h client_settings.h libexec_PROGRAMS= mysqlmanager @@ -85,7 +85,7 @@ mysqlmanager_LDADD= liboptions.a \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a \ $(top_builddir)/dbug/libdbug.a \ - @openssl_libs@ @ZLIB_LIBS@ + @openssl_libs@ @yassl_libs@ @ZLIB_LIBS@ tags: diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index 3d54d000d5f..3d04403f830 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -255,7 +255,10 @@ static void start_and_monitor_instance(Instance_options *old_instance_options, log_info("starting instance %s", instance_name_buff); if (start_process(old_instance_options, &process_info)) + { + instance_map->unlock(); return; /* error is logged */ + } /* allow users to delete instances */ instance_map->unlock(); diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index 25609f489af..83f13b34aa2 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -47,14 +47,12 @@ static inline int create_mysqld_command(Buffer *buf, if (buf->get_size()) /* malloc succeeded */ { #ifdef __WIN__ - buf->append(position, "\"", 1); - position++; + buf->append(position++, "\"", 1); #endif buf->append(position, mysqld_path_str, mysqld_path_len); position+= mysqld_path_len; #ifdef __WIN__ - buf->append(position, "\"", 1); - position++; + buf->append(position++, "\"", 1); #endif /* here the '\0' character is copied from the option string */ buf->append(position, option, option_len); @@ -336,10 +334,15 @@ int Instance_options::complete_initialization(const char *default_path, uint instance_type) { const char *tmp; + char *end; if (!mysqld_path && !(mysqld_path= strdup_root(&alloc, default_path))) goto err; + // it's safe to cast this to char* since this is a buffer we are allocating + end= convert_dirname((char*)mysqld_path, mysqld_path, NullS); + end[-1]= 0; + mysqld_path_len= strlen(mysqld_path); if (mysqld_port) diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index 08c28dc9f7d..67d798a1700 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -122,11 +122,15 @@ void Listener_thread::run() n++; timeval tv; - tv.tv_sec= 0; - tv.tv_usec= 100000; while (!thread_registry.is_shutdown()) { fd_set read_fds_arg= read_fds; + /* + We should reintialize timer as on linux it is modified + to reflect amount of time not slept. + */ + tv.tv_sec= 0; + tv.tv_usec= 100000; /* When using valgrind 2.0 this syscall doesn't get kicked off by a @@ -358,12 +362,13 @@ void Listener_thread::handle_new_mysql_connection(Vio *vio) pthread_attr_t mysql_thd_attr; pthread_attr_init(&mysql_thd_attr); pthread_attr_setdetachstate(&mysql_thd_attr, PTHREAD_CREATE_DETACHED); - if (pthread_create(&mysql_thd_id, &mysql_thd_attr, mysql_connection, - mysql_thread_args)) + if (set_stacksize_n_create_thread(&mysql_thd_id, &mysql_thd_attr, + mysql_connection, mysql_thread_args)) { delete mysql_thread_args; vio_delete(vio); - log_error("handle_one_mysql_connection(): pthread_create(mysql) failed"); + log_error("handle_one_mysql_connection():" + "set_stacksize_n_create_thread(mysql) failed"); } pthread_attr_destroy(&mysql_thd_attr); } diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index cc16ee6562f..3ecd5fbc0d0 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -162,12 +162,12 @@ void manager(const Options &options) pthread_attr_init(&listener_thd_attr); pthread_attr_setdetachstate(&listener_thd_attr, PTHREAD_CREATE_DETACHED); - rc= pthread_create(&listener_thd_id, &listener_thd_attr, listener, - &listener_args); + rc= set_stacksize_n_create_thread(&listener_thd_id, &listener_thd_attr, + listener, &listener_args); pthread_attr_destroy(&listener_thd_attr); if (rc) { - log_error("manager(): pthread_create(listener) failed"); + log_error("manager(): set_stacksize_n_create_thread(listener) failed"); goto err; } @@ -187,12 +187,12 @@ void manager(const Options &options) pthread_attr_init(&guardian_thd_attr); pthread_attr_setdetachstate(&guardian_thd_attr, PTHREAD_CREATE_DETACHED); - rc= pthread_create(&guardian_thd_id, &guardian_thd_attr, guardian, - &guardian_thread); + rc= set_stacksize_n_create_thread(&guardian_thd_id, &guardian_thd_attr, + guardian, &guardian_thread); pthread_attr_destroy(&guardian_thd_attr); if (rc) { - log_error("manager(): pthread_create(guardian) failed"); + log_error("manager(): set_stacksize_n_create_thread(guardian) failed"); goto err; } @@ -231,6 +231,12 @@ void manager(const Options &options) } #ifndef __WIN__ +/* + On some Darwin kernels SIGHUP is delivered along with most + signals. This is why we skip it's processing on these + platforms. For more details and test program see + Bug #14164 IM tests fail on MacOS X (powermacg5) +*/ #ifdef IGNORE_SIGHUP_SIGQUIT if ( SIGHUP == signo ) continue; diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc index b5af3cb83a7..ebc45c1f7d4 100644 --- a/server-tools/instance-manager/parse_output.cc +++ b/server-tools/instance-manager/parse_output.cc @@ -24,6 +24,20 @@ #include "portability.h" +void trim_space(const char **text, uint *word_len) +{ + const char *start= *text; + while (*start != 0 && *start == ' ') + start++; + *text= start; + + int len= strlen(start); + const char *end= start + len - 1; + while (end > start && my_isspace(&my_charset_latin1, *end)) + end--; + *word_len= (end - start)+1; +} + /* Parse output of the given command @@ -82,20 +96,17 @@ int parse_output_and_get_value(const char *command, const char *word, linebuf[sizeof(linebuf) - 1]= '\0'; /* safety */ /* - Get the word, which might contain non-alphanumeric characters. (Usually - these are '/', '-' and '.' in the path expressions and filenames) + Compare the start of our line with the word(s) we are looking for. */ - get_word((const char **) &linep, &found_word_len, NONSPACE); if (!strncmp(word, linep, wordlen)) { /* - If we have found the word, return the next one (this is usually - an option value) or the whole line (if flag) + If we have found our word(s), then move linep past the word(s) */ - linep+= found_word_len; /* swallow the previous one */ + linep+= wordlen; if (flag & GET_VALUE) { - get_word((const char **) &linep, &found_word_len, NONSPACE); + trim_space((const char**) &linep, &found_word_len); if (input_buffer_len <= found_word_len) goto err; strmake(result, linep, found_word_len); diff --git a/server-tools/instance-manager/priv.cc b/server-tools/instance-manager/priv.cc index 02a788ec469..e39c12f4ebb 100644 --- a/server-tools/instance-manager/priv.cc +++ b/server-tools/instance-manager/priv.cc @@ -18,6 +18,17 @@ #include "priv.h" #include "portability.h" +#if defined(__ia64__) || defined(__ia64) +/* + We can live with 32K, but reserve 64K. Just to be safe. + On ia64 we need to reserve double of the size. +*/ +#define IM_THREAD_STACK_SIZE (128*1024L) +#else +#define IM_THREAD_STACK_SIZE (64*1024) +#endif + + /* the pid of the manager process (of the signal thread on the LinuxThreads) */ pid_t manager_pid; @@ -52,3 +63,31 @@ unsigned int test_flags= 0; unsigned long bytes_sent = 0L, bytes_received = 0L; unsigned long mysqld_net_retry_count = 10L; unsigned long open_files_limit; + +/* + Change the stack size and start a thread. Return an error if either + pthread_attr_setstacksize or pthread_create fails. + Arguments are the same as for pthread_create(). +*/ + +int set_stacksize_n_create_thread(pthread_t *thread, pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + int rc= 0; + +#ifndef __WIN__ +#ifndef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 32768 +#endif + /* + Set stack size to be safe on the platforms with too small + default thread stack. + */ + rc= pthread_attr_setstacksize(attr, + (size_t) (PTHREAD_STACK_MIN + + IM_THREAD_STACK_SIZE)); +#endif + if (!rc) + rc= pthread_create(thread, attr, start_routine, arg); + return rc; +} diff --git a/server-tools/instance-manager/priv.h b/server-tools/instance-manager/priv.h index ce9d54293c7..4739bca68eb 100644 --- a/server-tools/instance-manager/priv.h +++ b/server-tools/instance-manager/priv.h @@ -22,7 +22,7 @@ #else #include <unistd.h> #endif - +#include "my_pthread.h" /* the pid of the manager process (of the signal thread on the LinuxThreads) */ extern pid_t manager_pid; @@ -80,4 +80,8 @@ extern unsigned long bytes_sent, bytes_received; extern unsigned long mysqld_net_retry_count; extern unsigned long open_files_limit; + +int set_stacksize_n_create_thread(pthread_t *thread, pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg); + #endif // INCLUDES_MYSQL_INSTANCE_MANAGER_PRIV_H diff --git a/sql-bench/Makefile.am b/sql-bench/Makefile.am index 579a2a9f7fe..12f3d5550b3 100644 --- a/sql-bench/Makefile.am +++ b/sql-bench/Makefile.am @@ -60,6 +60,8 @@ install-data-local: for i in $(srcdir)/limits/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/limits; done for i in $(srcdir)/Comments/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Comments; done +uninstall-local: + @RM@ -f -r $(DESTDIR)$(benchdir) SUFFIXES = .sh diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh index d61551ffb3b..31282d06abf 100644 --- a/sql-bench/bench-init.pl.sh +++ b/sql-bench/bench-init.pl.sh @@ -447,7 +447,7 @@ All benchmarks takes the following options: --create-options=# Extra argument to all create statements. If you for example want to create all MySQL tables as BDB tables use: - --create-options=TYPE=BDB + --create-options=ENGINE=BDB --database (Default $opt_database) In which database the test tables are created. diff --git a/sql-bench/server-cfg.sh b/sql-bench/server-cfg.sh index b0c40102a6b..75528b24b77 100644 --- a/sql-bench/server-cfg.sh +++ b/sql-bench/server-cfg.sh @@ -174,29 +174,29 @@ sub new # Some fixes that depends on the environment if (defined($main::opt_create_options) && - $main::opt_create_options =~ /type=heap/i) + $main::opt_create_options =~ /engine=heap/i) { $limits{'working_blobs'} = 0; # HEAP tables can't handle BLOB's } if (defined($main::opt_create_options) && - $main::opt_create_options =~ /type=innodb/i) + $main::opt_create_options =~ /engine=innodb/i) { $self->{'transactions'} = 1; # Transactions enabled } if (defined($main::opt_create_options) && - $main::opt_create_options =~ /type=ndb/i) + $main::opt_create_options =~ /engine=ndb/i) { $self->{'transactions'} = 1; # Transactions enabled $limits{'max_columns'} = 90; # Max number of columns in table $limits{'max_tables'} = 32; # No comments } if (defined($main::opt_create_options) && - $main::opt_create_options =~ /type=bdb/i) + $main::opt_create_options =~ /engine=bdb/i) { $self->{'transactions'} = 1; # Transactions enabled } if (defined($main::opt_create_options) && - $main::opt_create_options =~ /type=gemini/i) + $main::opt_create_options =~ /engine=gemini/i) { $limits{'working_blobs'} = 0; # Blobs not implemented yet $limits{'max_tables'} = 500; diff --git a/sql-common/client.c b/sql-common/client.c index 08ad906e2b6..4c2debd41ff 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -715,6 +715,7 @@ void free_old_query(MYSQL *mysql) init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */ mysql->fields= 0; mysql->field_count= 0; /* For API */ + mysql->warning_count= 0; mysql->info= 0; DBUG_VOID_RETURN; } @@ -1474,6 +1475,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , const char *capath __attribute__((unused)), const char *cipher __attribute__((unused))) { + DBUG_ENTER("mysql_ssl_set"); #ifdef HAVE_OPENSSL mysql->options.ssl_key= strdup_if_not_null(key); mysql->options.ssl_cert= strdup_if_not_null(cert); @@ -1481,7 +1483,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , mysql->options.ssl_capath= strdup_if_not_null(capath); mysql->options.ssl_cipher= strdup_if_not_null(cipher); #endif /* HAVE_OPENSSL */ - return 0; + DBUG_RETURN(0); } @@ -1494,11 +1496,17 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , static void mysql_ssl_free(MYSQL *mysql __attribute__((unused))) { + struct st_VioSSLConnectorFd *st= + (struct st_VioSSLConnectorFd*) mysql->connector_fd; + DBUG_ENTER("mysql_ssl_free"); + my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + if (st) + SSL_CTX_free(st->ssl_context); my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); mysql->options.ssl_key = 0; mysql->options.ssl_cert = 0; @@ -1507,6 +1515,7 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) mysql->options.ssl_cipher= 0; mysql->options.use_ssl = FALSE; mysql->connector_fd = 0; + DBUG_VOID_RETURN; } #endif /* HAVE_OPENSSL */ @@ -2476,7 +2485,6 @@ get_info: DBUG_RETURN(1); mysql->status= MYSQL_STATUS_GET_RESULT; mysql->field_count= (uint) field_count; - mysql->warning_count= 0; DBUG_PRINT("exit",("ok")); DBUG_RETURN(0); } diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 72809ee9b4b..c9d39260761 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -575,18 +575,34 @@ fractional: /* Get fractional second part */ if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1])) { - uint field_length=5; + int field_length= 5; str++; value=(uint) (uchar) (*str - '0'); - while (++str != end && - my_isdigit(&my_charset_latin1,str[0]) && - field_length--) - value=value*10 + (uint) (uchar) (*str - '0'); - if (field_length) + while (++str != end && my_isdigit(&my_charset_latin1, *str)) + { + if (field_length-- > 0) + value= value*10 + (uint) (uchar) (*str - '0'); + } + if (field_length > 0) value*= (long) log_10_int[field_length]; + else if (field_length < 0) + *was_cut= 1; date[4]=value; } else date[4]=0; + + /* Check for exponent part: E<gigit> | E<sign><digit> */ + /* (may occur as result of %g formatting of time value) */ + if ((end - str) > 1 && + (*str == 'e' || *str == 'E') && + (my_isdigit(&my_charset_latin1, str[1]) || + ((str[1] == '-' || str[1] == '+') && + (end - str) > 2 && + my_isdigit(&my_charset_latin1, str[2])))) + { + *was_cut= 1; + return 1; + } if (internal_format_positions[7] != 255) { diff --git a/sql/Makefile.am b/sql/Makefile.am index cd1de0ce3c9..1437751bf2f 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -22,7 +22,8 @@ MYSQLBASEdir= $(prefix) INCLUDES = @ZLIB_INCLUDES@ \ @bdb_includes@ @innodb_includes@ @ndbcluster_includes@ \ -I$(top_builddir)/include -I$(top_srcdir)/include \ - -I$(top_srcdir)/regex -I$(srcdir) $(openssl_includes) + -I$(top_srcdir)/regex -I$(srcdir) $(yassl_includes) \ + $(openssl_includes) WRAPLIBS= @WRAPLIBS@ SUBDIRS = share libexec_PROGRAMS = mysqld @@ -42,7 +43,8 @@ mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \ @bdb_libs@ @innodb_libs@ @pstack_libs@ \ @innodb_system_libs@ \ @ndbcluster_libs@ @ndbcluster_system_libs@ \ - $(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ @openssl_libs@ + $(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ \ + @yassl_libs@ @openssl_libs@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ item_strfunc.h item_timefunc.h item_uniq.h \ item_create.h item_subselect.h item_row.h \ @@ -120,17 +122,17 @@ AM_YFLAGS = -d mysql_tzinfo_to_sql.cc: rm -f mysql_tzinfo_to_sql.cc - @LN_CP_F@ tztime.cc mysql_tzinfo_to_sql.cc + @LN_CP_F@ $(srcdir)/tztime.cc mysql_tzinfo_to_sql.cc link_sources: mysql_tzinfo_to_sql.cc rm -f mini_client_errors.c - @LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c + @LN_CP_F@ $(top_srcdir)/libmysql/errmsg.c mini_client_errors.c rm -f pack.c - @LN_CP_F@ ../sql-common/pack.c pack.c + @LN_CP_F@ $(top_srcdir)/sql-common/pack.c pack.c rm -f client.c - @LN_CP_F@ ../sql-common/client.c client.c + @LN_CP_F@ $(top_srcdir)/sql-common/client.c client.c rm -f my_time.c - @LN_CP_F@ ../sql-common/my_time.c my_time.c + @LN_CP_F@ $(top_srcdir)/sql-common/my_time.c my_time.c mysql_tzinfo_to_sql.o: $(mysql_tzinfo_to_sql_SOURCES) $(CXXCOMPILE) -c $(INCLUDES) -DTZINFO2SQL $< diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc index d340b9289ec..471ece77490 100644 --- a/sql/examples/ha_example.cc +++ b/sql/examples/ha_example.cc @@ -480,6 +480,8 @@ int ha_example::rnd_pos(byte * buf, byte *pos) /* ::info() is used to return information to the optimizer. + see my_base.h for the complete description + Currently this table handler doesn't implement most of the fields really needed. SHOW also makes use of this data Another note, you will probably want to have the following in your diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc index 541e91f4b46..8ae82f97d0b 100644 --- a/sql/examples/ha_tina.cc +++ b/sql/examples/ha_tina.cc @@ -82,12 +82,16 @@ handlerton tina_hton= { ** TINA tables *****************************************************************************/ -/* - Used for sorting chains. +/* + Used for sorting chains with qsort(). */ int sort_set (tina_set *a, tina_set *b) { - return ( a->begin > b->begin ? 1 : ( a->begin < b->begin ? -1 : 0 ) ); + /* + We assume that intervals do not intersect. So, it is enought to compare + any two points. Here we take start of intervals for comparison. + */ + return ( a->begin > b->begin ? -1 : ( a->begin < b->begin ? 1 : 0 ) ); } static byte* tina_get_key(TINA_SHARE *share,uint *length, @@ -186,7 +190,8 @@ static TINA_SHARE *get_share(const char *table_name, TABLE *table) thr_lock_init(&share->lock); pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST); - if ((share->data_file= my_open(data_file_name, O_RDWR, MYF(0))) == -1) + if ((share->data_file= my_open(data_file_name, O_RDWR|O_APPEND, + MYF(0))) == -1) goto error2; /* We only use share->data_file for writing, so we scan to the end to append */ @@ -269,7 +274,8 @@ ha_tina::ha_tina(TABLE *table_arg) These definitions are found in hanler.h These are not probably completely right. */ - current_position(0), next_position(0), chain_alloced(0), chain_size(DEFAULT_CHAIN_LENGTH) + current_position(0), next_position(0), chain_alloced(0), + chain_size(DEFAULT_CHAIN_LENGTH), records_is_known(0) { /* Set our original buffers from pre-allocated memory */ buffer.set(byte_buffer, IO_SIZE, system_charset_info); @@ -499,6 +505,7 @@ int ha_tina::write_row(byte * buf) */ if (get_mmap(share, 0) > 0) DBUG_RETURN(-1); + records++; DBUG_RETURN(0); } @@ -663,6 +670,7 @@ int ha_tina::rnd_init(bool scan) current_position= next_position= 0; records= 0; + records_is_known= 0; chain_ptr= chain; #ifdef HAVE_MADVISE if (scan) @@ -740,7 +748,7 @@ void ha_tina::info(uint flag) { DBUG_ENTER("ha_tina::info"); /* This is a lie, but you don't want the optimizer to see zero or 1 */ - if (records < 2) + if (!records_is_known && records < 2) records= 2; DBUG_VOID_RETURN; } @@ -775,6 +783,8 @@ int ha_tina::rnd_end() { DBUG_ENTER("ha_tina::rnd_end"); + records_is_known= 1; + /* First position will be truncate position, second will be increment */ if ((chain_ptr - chain) > 0) { @@ -797,13 +807,8 @@ int ha_tina::rnd_end() qsort(chain, (size_t)(chain_ptr - chain), sizeof(tina_set), (qsort_cmp)sort_set); for (ptr= chain; ptr < chain_ptr; ptr++) { - /* We peek a head to see if this is the last chain */ - if (ptr+1 == chain_ptr) - memmove(share->mapped_file + ptr->begin, share->mapped_file + ptr->end, - length - (size_t)ptr->end); - else - memmove((caddr_t)share->mapped_file + ptr->begin, (caddr_t)share->mapped_file + ptr->end, - (size_t)((ptr++)->begin - ptr->end)); + memmove(share->mapped_file + ptr->begin, share->mapped_file + ptr->end, + length - (size_t)ptr->end); length= length - (size_t)(ptr->end - ptr->begin); } @@ -824,17 +829,21 @@ int ha_tina::rnd_end() } /* - Truncate table and others of its ilk call this. + DELETE without WHERE calls it */ int ha_tina::delete_all_rows() { DBUG_ENTER("ha_tina::delete_all_rows"); + if (!records_is_known) + return (my_errno=HA_ERR_WRONG_COMMAND); + int rc= my_chsize(share->data_file, 0, 0, MYF(MY_WME)); if (get_mmap(share, 0) > 0) DBUG_RETURN(-1); + records=0; DBUG_RETURN(rc); } diff --git a/sql/examples/ha_tina.h b/sql/examples/ha_tina.h index 84854e868fa..97659f99dd9 100644 --- a/sql/examples/ha_tina.h +++ b/sql/examples/ha_tina.h @@ -48,6 +48,7 @@ class ha_tina: public handler tina_set *chain_ptr; byte chain_alloced; uint32 chain_size; + bool records_is_known; public: ha_tina(TABLE *table_arg); diff --git a/sql/field.cc b/sql/field.cc index b4ba89f613c..1f3649e1b88 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1272,9 +1272,9 @@ my_decimal *Field::val_decimal(my_decimal *decimal) void Field_num::add_zerofill_and_unsigned(String &res) const { if (unsigned_flag) - res.append(" unsigned"); + res.append(STRING_WITH_LEN(" unsigned")); if (zerofill) - res.append(" zerofill"); + res.append(STRING_WITH_LEN(" zerofill")); } @@ -1628,6 +1628,7 @@ bool Field::needs_quotes(void) case FIELD_TYPE_MEDIUM_BLOB : case FIELD_TYPE_LONG_BLOB : case FIELD_TYPE_GEOMETRY : + case FIELD_TYPE_BIT: DBUG_RETURN(1); case FIELD_TYPE_DECIMAL : @@ -1654,7 +1655,7 @@ bool Field::needs_quotes(void) void Field_null::sql_type(String &res) const { - res.set_ascii("null", 4); + res.set_ascii(STRING_WITH_LEN("null")); } @@ -1666,7 +1667,7 @@ void Field_null::sql_type(String &res) const void Field_decimal::reset(void) { - Field_decimal::store("0",1,&my_charset_bin); + Field_decimal::store(STRING_WITH_LEN("0"),&my_charset_bin); } void Field_decimal::overflow(bool negative) @@ -3952,7 +3953,7 @@ longlong Field_float::val_int(void) else #endif memcpy_fixed((byte*) &j,ptr,sizeof(j)); - return ((longlong) j); + return (longlong) rint(j); } @@ -4112,7 +4113,7 @@ void Field_float::sql_type(String &res) const { if (dec == NOT_FIXED_DEC) { - res.set_ascii("float", 5); + res.set_ascii(STRING_WITH_LEN("float")); } else { @@ -4240,7 +4241,7 @@ longlong Field_double::val_int(void) else #endif doubleget(j,ptr); - return ((longlong) j); + return (longlong) rint(j); } @@ -4383,7 +4384,7 @@ void Field_double::sql_type(String &res) const CHARSET_INFO *cs=res.charset(); if (dec == NOT_FIXED_DEC) { - res.set_ascii("double",6); + res.set_ascii(STRING_WITH_LEN("double")); } else { @@ -4672,7 +4673,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr) if (temp == 0L) { /* Zero time is "000000" */ - val_ptr->set("0000-00-00 00:00:00", 19, &my_charset_bin); + val_ptr->set(STRING_WITH_LEN("0000-00-00 00:00:00"), &my_charset_bin); return val_ptr; } val_buffer->set_charset(&my_charset_bin); // Safety @@ -4804,7 +4805,7 @@ void Field_timestamp::sort_string(char *to,uint length __attribute__((unused))) void Field_timestamp::sql_type(String &res) const { - res.set_ascii("timestamp", 9); + res.set_ascii(STRING_WITH_LEN("timestamp")); } @@ -5073,7 +5074,7 @@ void Field_time::sort_string(char *to,uint length __attribute__((unused))) void Field_time::sql_type(String &res) const { - res.set_ascii("time", 4); + res.set_ascii(STRING_WITH_LEN("time")); } /**************************************************************************** @@ -5380,7 +5381,7 @@ void Field_date::sort_string(char *to,uint length __attribute__((unused))) void Field_date::sql_type(String &res) const { - res.set_ascii("date", 4); + res.set_ascii(STRING_WITH_LEN("date")); } @@ -5563,7 +5564,7 @@ void Field_newdate::sort_string(char *to,uint length __attribute__((unused))) void Field_newdate::sql_type(String &res) const { - res.set_ascii("date", 4); + res.set_ascii(STRING_WITH_LEN("date")); } @@ -5837,7 +5838,7 @@ void Field_datetime::sort_string(char *to,uint length __attribute__((unused))) void Field_datetime::sql_type(String &res) const { - res.set_ascii("datetime", 8); + res.set_ascii(STRING_WITH_LEN("datetime")); } /**************************************************************************** @@ -5854,44 +5855,52 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) char buff[STRING_BUFFER_USUAL_SIZE]; String tmpstr(buff,sizeof(buff), &my_charset_bin); uint copy_length; - + /* See the comment for Field_long::store(long long) */ DBUG_ASSERT(table->in_use == current_thd); - + /* Convert character set if necessary */ if (String::needs_conversion(length, cs, field_charset, ¬_used)) - { + { uint conv_errors; tmpstr.copy(from, length, cs, field_charset, &conv_errors); from= tmpstr.ptr(); - length= tmpstr.length(); + length= tmpstr.length(); if (conv_errors) error= 2; } - /* - Make sure we don't break a multibyte sequence - as well as don't copy a malformed data. - */ + /* Make sure we don't break a multibyte sequence or copy malformed data. */ copy_length= field_charset->cset->well_formed_len(field_charset, from,from+length, field_length/ field_charset->mbmaxlen, &well_formed_error); memcpy(ptr,from,copy_length); - if (copy_length < field_length) // Append spaces if shorter + + /* Append spaces if the string was shorter than the field. */ + if (copy_length < field_length) field_charset->cset->fill(field_charset,ptr+copy_length, - field_length-copy_length, + field_length-copy_length, field_charset->pad_char); - + + /* + Check if we lost any important data (anything in a binary string, + or any non-space in others). + */ if ((copy_length < length) && table->in_use->count_cuted_fields) - { // Check if we loosed some info - const char *end=from+length; - from+= copy_length; - from+= field_charset->cset->scan(field_charset, from, end, - MY_SEQ_SPACES); - if (from != end) + { + if (binary()) error= 2; + else + { + const char *end=from+length; + from+= copy_length; + from+= field_charset->cset->scan(field_charset, from, end, + MY_SEQ_SPACES); + if (from != end) + error= 2; + } } if (error) { @@ -6060,7 +6069,7 @@ void Field_string::sql_type(String &res) const res.length(length); if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) && has_charset() && (charset()->state & MY_CS_BINSORT)) - res.append(" binary"); + res.append(STRING_WITH_LEN(" binary")); } @@ -6193,6 +6202,8 @@ uint Field_string::max_packed_col_length(uint max_length) Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table) { + Field *new_field; + if (type() != MYSQL_TYPE_VAR_STRING || table == new_table) return Field::new_field(root, new_table); @@ -6201,9 +6212,17 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table) This is done to ensure that ALTER TABLE will convert old VARCHAR fields to now VARCHAR fields. */ - return new Field_varstring(field_length, maybe_null(), - field_name, new_table, - charset()); + if ((new_field= new Field_varstring(field_length, maybe_null(), + field_name, new_table, charset()))) + { + /* + delayed_insert::get_local_table() needs a ptr copied from old table. + This is what other new_field() methods do too. The above method of + Field_varstring sets ptr to NULL. + */ + new_field->ptr= ptr; + } + return new_field; } /**************************************************************************** @@ -6260,12 +6279,15 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) if ((copy_length < length) && table->in_use->count_cuted_fields && !error_code) { - const char *end= from + length; - from+= copy_length; - from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES); - /* If we lost only spaces then produce a NOTE, not a WARNING */ - if (from == end) - level= MYSQL_ERROR::WARN_LEVEL_NOTE; + if (!binary()) + { + const char *end= from + length; + from+= copy_length; + from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES); + /* If we lost only spaces then produce a NOTE, not a WARNING */ + if (from == end) + level= MYSQL_ERROR::WARN_LEVEL_NOTE; + } error_code= WARN_DATA_TRUNCATED; } if (error_code) @@ -6446,7 +6468,7 @@ void Field_varstring::sql_type(String &res) const res.length(length); if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) && has_charset() && (charset()->state & MY_CS_BINSORT)) - res.append(" binary"); + res.append(STRING_WITH_LEN(" binary")); } @@ -6737,7 +6759,10 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, { flags|= BLOB_FLAG; if (table) + { table->s->blob_fields++; + /* TODO: why do not fill table->s->blob_field array here? */ + } } @@ -7041,8 +7066,7 @@ void Field_blob::get_key_image(char *buff, uint length, imagetype type) return; } get_ptr(&blob); - gobj= Geometry::create_from_wkb(&buffer, - blob + SRID_SIZE, blob_length - SRID_SIZE); + gobj= Geometry::construct(&buffer, blob, blob_length); if (gobj->get_mbr(&mbr, &dummy)) bzero(buff, SIZEOF_STORED_DOUBLE*4); else @@ -7167,10 +7191,10 @@ void Field_blob::sql_type(String &res) const } res.set_ascii(str,length); if (charset() == &my_charset_bin) - res.append("blob"); + res.append(STRING_WITH_LEN("blob")); else { - res.append("text"); + res.append(STRING_WITH_LEN("text")); } } @@ -7371,8 +7395,7 @@ void Field_geom::get_key_image(char *buff, uint length, imagetype type) return; } get_ptr(&blob); - gobj= Geometry::create_from_wkb(&buffer, - blob + SRID_SIZE, blob_length - SRID_SIZE); + gobj= Geometry::construct(&buffer, blob, blob_length); if (gobj->get_mbr(&mbr, &dummy)) bzero(buff, SIZEOF_STORED_DOUBLE*4); else @@ -7391,28 +7414,28 @@ void Field_geom::sql_type(String &res) const switch (geom_type) { case GEOM_POINT: - res.set("point", 5, cs); + res.set(STRING_WITH_LEN("point"), cs); break; case GEOM_LINESTRING: - res.set("linestring", 10, cs); + res.set(STRING_WITH_LEN("linestring"), cs); break; case GEOM_POLYGON: - res.set("polygon", 7, cs); + res.set(STRING_WITH_LEN("polygon"), cs); break; case GEOM_MULTIPOINT: - res.set("multipoint", 10, cs); + res.set(STRING_WITH_LEN("multipoint"), cs); break; case GEOM_MULTILINESTRING: - res.set("multilinestring", 15, cs); + res.set(STRING_WITH_LEN("multilinestring"), cs); break; case GEOM_MULTIPOLYGON: - res.set("multipolygon", 12, cs); + res.set(STRING_WITH_LEN("multipolygon"), cs); break; case GEOM_GEOMETRYCOLLECTION: - res.set("geometrycollection", 18, cs); + res.set(STRING_WITH_LEN("geometrycollection"), cs); break; default: - res.set("geometry", 8, cs); + res.set(STRING_WITH_LEN("geometry"), cs); } } @@ -7453,7 +7476,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs) uint32 wkb_type; if (length < SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE*2) goto err; - wkb_type= uint4korr(from + WKB_HEADER_SIZE); + wkb_type= uint4korr(from + SRID_SIZE + 1); if (wkb_type < (uint32) Geometry::wkb_point || wkb_type > (uint32) Geometry::wkb_end) goto err; @@ -7689,7 +7712,7 @@ void Field_enum::sql_type(String &res) const String enum_item(buffer, sizeof(buffer), res.charset()); res.length(0); - res.append("enum("); + res.append(STRING_WITH_LEN("enum(")); bool flag=0; uint *len= typelib->type_lengths; @@ -7803,7 +7826,7 @@ void Field_set::sql_type(String &res) const String set_item(buffer, sizeof(buffer), res.charset()); res.length(0); - res.append("set("); + res.append(STRING_WITH_LEN("set(")); bool flag=0; uint *len= typelib->type_lengths; @@ -7932,7 +7955,7 @@ int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs) { int delta; - for (; !*from && length; from++, length--); // skip left 0's + for (; length && !*from; from++, length--); // skip left 0's delta= field_length - length; if (delta < -1 || @@ -8152,7 +8175,7 @@ int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs) int delta; uchar bits= create_length & 7; - for (; !*from && length; from++, length--); // skip left 0's + for (; length && !*from; from++, length--); // skip left 0's delta= field_length - length; if (delta < 0 || @@ -8186,8 +8209,20 @@ void Field_bit_as_char::sql_type(String &res) const Handling of field and create_field *****************************************************************************/ +/* + Convert create_field::length from number of characters to number of bytes + + SYNOPSIS + create_field::create_length_to_internal_length() + + DESCRIPTION + Convert create_field::length from number of characters to number of bytes, + save original value in chars_length. +*/ + void create_field::create_length_to_internal_length(void) { + chars_length= length; switch (sql_type) { case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: @@ -8251,6 +8286,350 @@ void create_field::init_for_tmp_table(enum_field_types sql_type_arg, } +/* + Initialize field definition for create + + SYNOPSIS + thd Thread handle + fld_name Field name + fld_type Field type + fld_length Field length + fld_decimals Decimal (if any) + fld_type_modifier Additional type information + fld_default_value Field default value (if any) + fld_on_update_value The value of ON UPDATE clause + fld_comment Field comment + fld_change Field change + fld_interval_list Interval list (if any) + fld_charset Field charset + fld_geom_type Field geometry type (if any) + + RETURN + FALSE on success + TRUE on error +*/ + +bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, + char *fld_length, char *fld_decimals, + uint fld_type_modifier, Item *fld_default_value, + Item *fld_on_update_value, LEX_STRING *fld_comment, + char *fld_change, List<String> *fld_interval_list, + CHARSET_INFO *fld_charset, uint fld_geom_type) +{ + uint sign_len, allowed_type_modifier= 0; + ulong max_field_charlength= MAX_FIELD_CHARLENGTH; + + DBUG_ENTER("create_field::init()"); + + field= 0; + field_name= fld_name; + def= fld_default_value; + flags= fld_type_modifier; + unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ? + Field::NEXT_NUMBER : Field::NONE); + decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0; + if (decimals >= NOT_FIXED_DEC) + { + my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name, + NOT_FIXED_DEC-1); + DBUG_RETURN(TRUE); + } + + sql_type= fld_type; + length= 0; + change= fld_change; + interval= 0; + pack_length= key_length= 0; + charset= fld_charset; + geom_type= (Field::geometry_type) fld_geom_type; + interval_list.empty(); + + comment= *fld_comment; + /* + Set flag if this field doesn't have a default value + */ + if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) && + (fld_type_modifier & NOT_NULL_FLAG) && fld_type != FIELD_TYPE_TIMESTAMP) + flags|= NO_DEFAULT_VALUE_FLAG; + + if (fld_length && !(length= (uint) atoi(fld_length))) + fld_length= 0; /* purecov: inspected */ + sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1; + + switch (fld_type) { + case FIELD_TYPE_TINY: + if (!fld_length) + length= MAX_TINYINT_WIDTH+sign_len; + allowed_type_modifier= AUTO_INCREMENT_FLAG; + break; + case FIELD_TYPE_SHORT: + if (!fld_length) + length= MAX_SMALLINT_WIDTH+sign_len; + allowed_type_modifier= AUTO_INCREMENT_FLAG; + break; + case FIELD_TYPE_INT24: + if (!fld_length) + length= MAX_MEDIUMINT_WIDTH+sign_len; + allowed_type_modifier= AUTO_INCREMENT_FLAG; + break; + case FIELD_TYPE_LONG: + if (!fld_length) + length= MAX_INT_WIDTH+sign_len; + allowed_type_modifier= AUTO_INCREMENT_FLAG; + break; + case FIELD_TYPE_LONGLONG: + if (!fld_length) + length= MAX_BIGINT_WIDTH; + allowed_type_modifier= AUTO_INCREMENT_FLAG; + break; + case FIELD_TYPE_NULL: + break; + case FIELD_TYPE_NEWDECIMAL: + if (!fld_length && !decimals) + length= 10; + if (length > DECIMAL_MAX_PRECISION) + { + my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name, + DECIMAL_MAX_PRECISION); + DBUG_RETURN(TRUE); + } + if (length < decimals) + { + my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name); + DBUG_RETURN(TRUE); + } + length= + my_decimal_precision_to_length(length, decimals, + fld_type_modifier & UNSIGNED_FLAG); + pack_length= + my_decimal_get_binary_size(length, decimals); + break; + case MYSQL_TYPE_VARCHAR: + /* + Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table + if they don't have a default value + */ + max_field_charlength= MAX_FIELD_VARCHARLENGTH; + break; + case MYSQL_TYPE_STRING: + break; + case FIELD_TYPE_BLOB: + case FIELD_TYPE_TINY_BLOB: + case FIELD_TYPE_LONG_BLOB: + case FIELD_TYPE_MEDIUM_BLOB: + case FIELD_TYPE_GEOMETRY: + if (fld_default_value) + { + /* Allow empty as default value. */ + String str,*res; + res= fld_default_value->val_str(&str); + if (res->length()) + { + my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), + fld_name); /* purecov: inspected */ + DBUG_RETURN(TRUE); + } + def= 0; + } + flags|= BLOB_FLAG; + break; + case FIELD_TYPE_YEAR: + if (!fld_length || length != 2) + length= 4; /* Default length */ + flags|= ZEROFILL_FLAG | UNSIGNED_FLAG; + break; + case FIELD_TYPE_FLOAT: + /* change FLOAT(precision) to FLOAT or DOUBLE */ + allowed_type_modifier= AUTO_INCREMENT_FLAG; + if (fld_length && !fld_decimals) + { + uint tmp_length= length; + if (tmp_length > PRECISION_FOR_DOUBLE) + { + my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name); + DBUG_RETURN(TRUE); + } + else if (tmp_length > PRECISION_FOR_FLOAT) + { + sql_type= FIELD_TYPE_DOUBLE; + length= DBL_DIG+7; /* -[digits].E+### */ + } + else + length= FLT_DIG+6; /* -[digits].E+## */ + decimals= NOT_FIXED_DEC; + break; + } + if (!fld_length && !fld_decimals) + { + length= FLT_DIG+6; + decimals= NOT_FIXED_DEC; + } + if (length < decimals && + decimals != NOT_FIXED_DEC) + { + my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name); + DBUG_RETURN(TRUE); + } + break; + case FIELD_TYPE_DOUBLE: + allowed_type_modifier= AUTO_INCREMENT_FLAG; + if (!fld_length && !fld_decimals) + { + length= DBL_DIG+7; + decimals= NOT_FIXED_DEC; + } + if (length < decimals && + decimals != NOT_FIXED_DEC) + { + my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name); + DBUG_RETURN(TRUE); + } + break; + case FIELD_TYPE_TIMESTAMP: + if (!fld_length) + length= 14; /* Full date YYYYMMDDHHMMSS */ + else if (length != 19) + { + /* + We support only even TIMESTAMP lengths less or equal than 14 + and 19 as length of 4.1 compatible representation. + */ + length= ((length+1)/2)*2; /* purecov: inspected */ + length= min(length,14); /* purecov: inspected */ + } + flags|= ZEROFILL_FLAG | UNSIGNED_FLAG; + if (fld_default_value) + { + /* Grammar allows only NOW() value for ON UPDATE clause */ + if (fld_default_value->type() == Item::FUNC_ITEM && + ((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC) + { + unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD: + Field::TIMESTAMP_DN_FIELD); + /* + We don't need default value any longer moreover it is dangerous. + Everything handled by unireg_check further. + */ + def= 0; + } + else + unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD: + Field::NONE); + } + else + { + /* + If we have default TIMESTAMP NOT NULL column without explicit DEFAULT + or ON UPDATE values then for the sake of compatiblity we should treat + this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't + have another TIMESTAMP column with auto-set option before this one) + or DEFAULT 0 (in other cases). + So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will + replace this value by TIMESTAMP_DNUN_FIELD or NONE later when + information about all TIMESTAMP fields in table will be availiable. + + If we have TIMESTAMP NULL column without explicit DEFAULT value + we treat it as having DEFAULT NULL attribute. + */ + unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD : + (flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD : + Field::NONE)); + } + break; + case FIELD_TYPE_DATE: + /* Old date type. */ + if (protocol_version != PROTOCOL_VERSION-1) + sql_type= FIELD_TYPE_NEWDATE; + /* fall trough */ + case FIELD_TYPE_NEWDATE: + length= 10; + break; + case FIELD_TYPE_TIME: + length= 10; + break; + case FIELD_TYPE_DATETIME: + length= 19; + break; + case FIELD_TYPE_SET: + { + if (fld_interval_list->elements > sizeof(longlong)*8) + { + my_error(ER_TOO_BIG_SET, MYF(0), fld_name); /* purecov: inspected */ + DBUG_RETURN(TRUE); + } + pack_length= get_set_pack_length(fld_interval_list->elements); + + List_iterator<String> it(*fld_interval_list); + String *tmp; + while ((tmp= it++)) + interval_list.push_back(tmp); + /* + Set fake length to 1 to pass the below conditions. + Real length will be set in mysql_prepare_table() + when we know the character set of the column + */ + length= 1; + break; + } + case FIELD_TYPE_ENUM: + { + /* Should be safe. */ + pack_length= get_enum_pack_length(fld_interval_list->elements); + + List_iterator<String> it(*fld_interval_list); + String *tmp; + while ((tmp= it++)) + interval_list.push_back(tmp); + length= 1; /* See comment for FIELD_TYPE_SET above. */ + break; + } + case MYSQL_TYPE_VAR_STRING: + DBUG_ASSERT(0); /* Impossible. */ + break; + case MYSQL_TYPE_BIT: + { + if (!fld_length) + length= 1; + if (length > MAX_BIT_FIELD_LENGTH) + { + my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name, + MAX_BIT_FIELD_LENGTH); + DBUG_RETURN(TRUE); + } + pack_length= (length + 7) / 8; + break; + } + case FIELD_TYPE_DECIMAL: + DBUG_ASSERT(0); /* Was obsolete */ + } + + if (!(flags & BLOB_FLAG) && + ((length > max_field_charlength && fld_type != FIELD_TYPE_SET && + fld_type != FIELD_TYPE_ENUM && + (fld_type != MYSQL_TYPE_VARCHAR || fld_default_value)) || + (!length && + fld_type != MYSQL_TYPE_STRING && + fld_type != MYSQL_TYPE_VARCHAR && fld_type != FIELD_TYPE_GEOMETRY))) + { + my_error((fld_type == MYSQL_TYPE_VAR_STRING || + fld_type == MYSQL_TYPE_VARCHAR || + fld_type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH : + ER_TOO_BIG_DISPLAYWIDTH, + MYF(0), + fld_name, max_field_charlength); /* purecov: inspected */ + DBUG_RETURN(TRUE); + } + fld_type_modifier&= AUTO_INCREMENT_FLAG; + if ((~allowed_type_modifier) & fld_type_modifier) + { + my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name); + DBUG_RETURN(TRUE); + } + + DBUG_RETURN(FALSE); /* success */ +} + + enum_field_types get_blob_type_from_length(ulong length) { enum_field_types type; diff --git a/sql/field.h b/sql/field.h index a9f47ecc4a9..67705523088 100644 --- a/sql/field.h +++ b/sql/field.h @@ -130,7 +130,19 @@ public: null_bit == field->null_bit); } virtual bool eq_def(Field *field); + + /* + pack_length() returns size (in bytes) used to store field data in memory + (i.e. it returns the maximum size of the field in a row of the table, + which is located in RAM). + */ virtual uint32 pack_length() const { return (uint32) field_length; } + + /* + pack_length_in_rec() returns size (in bytes) used to store field data on + storage (i.e. it returns the maximal size of the field in a row of the + table, which is located on disk). + */ virtual uint32 pack_length_in_rec() const { return pack_length(); } virtual uint32 sort_length() const { return pack_length(); } virtual void reset(void) { bzero(ptr,pack_length()); } @@ -1368,7 +1380,15 @@ public: LEX_STRING comment; // Comment for field Item *def; // Default value enum enum_field_types sql_type; + /* + At various stages in execution this can be length of field in bytes or + max number of characters. + */ ulong length; + /* + The value of 'length' before a call to create_length_to_internal_length + */ + uint32 chars_length; uint decimals, flags, pack_length, key_length; Field::utype unireg_check; TYPELIB *interval; // Which interval to use @@ -1387,6 +1407,12 @@ public: void init_for_tmp_table(enum_field_types sql_type_arg, uint32 max_length, uint32 decimals, bool maybe_null, bool is_unsigned); + + bool init(THD *thd, char *field_name, enum_field_types type, char *length, + char *decimals, uint type_modifier, Item *default_value, + Item *on_update_value, LEX_STRING *comment, char *change, + List<String> *interval_list, CHARSET_INFO *cs, + uint uint_geom_type); }; diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc index b4bcf162ff0..c60d40c2685 100644 --- a/sql/ha_archive.cc +++ b/sql/ha_archive.cc @@ -20,7 +20,7 @@ #include "mysql_priv.h" -#ifdef HAVE_ARCHIVE_DB +#if defined(HAVE_ARCHIVE_DB) #include "ha_archive.h" #include <my_dir.h> @@ -233,7 +233,8 @@ ha_archive::ha_archive(TABLE *table_arg) buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info); /* The size of the offset value we will use for position() */ - ref_length = sizeof(z_off_t); + ref_length = 2 << ((zlibCompileFlags() >> 6) & 3); + DBUG_ASSERT(ref_length <= sizeof(z_off_t)); } /* @@ -453,7 +454,6 @@ int ha_archive::free_share(ARCHIVE_SHARE *share) */ static const char *ha_archive_exts[] = { ARZ, - ARN, ARM, NullS }; diff --git a/sql/ha_archive.h b/sql/ha_archive.h index 6ba6d95685e..56a4b9d1e27 100644 --- a/sql/ha_archive.h +++ b/sql/ha_archive.h @@ -68,7 +68,7 @@ public: ulong table_flags() const { return (HA_REC_NOT_IN_SEQ | HA_NOT_EXACT_COUNT | HA_NO_AUTO_INCREMENT | - HA_FILE_BASED | HA_CAN_INSERT_DELAYED); + HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY); } ulong index_flags(uint idx, uint part, bool all_parts) const { diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 7cbb4e90452..72af402a0dc 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -308,7 +308,7 @@ int berkeley_show_logs(Protocol *protocol) { protocol->prepare_for_resend(); protocol->store(*a, system_charset_info); - protocol->store("BDB", 3, system_charset_info); + protocol->store(STRING_WITH_LEN("BDB"), system_charset_info); if (f && *f && strcmp(*a, *f) == 0) { f++; @@ -392,6 +392,7 @@ ha_berkeley::ha_berkeley(TABLE *table_arg) int_table_flags(HA_REC_NOT_IN_SEQ | HA_FAST_KEY_READ | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_NOT_EXACT_COUNT | HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED | + HA_CAN_GEOMETRY | HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX), changed_rows(0), last_dup_key((uint) -1), version(0), using_ignore(0) {} diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h index 59f11bfd74a..16e4db59c10 100644 --- a/sql/ha_berkeley.h +++ b/sql/ha_berkeley.h @@ -94,6 +94,9 @@ class ha_berkeley: public handler uint max_supported_keys() const { return MAX_KEY-1; } uint extra_rec_buf_length() { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; } ha_rows estimate_rows_upper_bound(); + uint max_supported_key_length() const { return UINT_MAX32; } + uint max_supported_key_part_length() const { return UINT_MAX32; } + const key_map *keys_to_use_for_scanning() { return &key_map_full; } bool has_transactions() { return 1;} diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index d6d6b5980f6..14b79a9a418 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -469,8 +469,7 @@ bool federated_db_end() table, and if so, does the foreign table exist. */ -static int check_foreign_data_source( - FEDERATED_SHARE *share, +static int check_foreign_data_source(FEDERATED_SHARE *share, bool table_create_flag) { char escaped_table_name[NAME_LEN*2]; @@ -496,15 +495,17 @@ static int check_foreign_data_source( share->port, share->socket, 0)) { - /* - we want the correct error message, but it to return - ER_CANT_CREATE_FEDERATED_TABLE if called by ::create - */ - error_code= table_create_flag? - ER_CANT_CREATE_FEDERATED_TABLE : ER_CONNECT_TO_FOREIGN_DATA_SOURCE; + /* + we want the correct error message, but it to return + ER_CANT_CREATE_FEDERATED_TABLE if called by ::create + */ + error_code= (table_create_flag ? + ER_CANT_CREATE_FEDERATED_TABLE : + ER_CONNECT_TO_FOREIGN_DATA_SOURCE); my_sprintf(error_buffer, - (error_buffer, " database %s username %s hostname %s", + (error_buffer, + "database: '%s' username: '%s' hostname: '%s'", share->database, share->username, share->hostname)); my_error(ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), error_buffer); @@ -545,8 +546,8 @@ static int check_foreign_data_source( { error_code= table_create_flag ? ER_CANT_CREATE_FEDERATED_TABLE : ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST; - my_sprintf(error_buffer, (error_buffer, ": %d : %s", - mysql_errno(mysql), mysql_error(mysql))); + my_sprintf(error_buffer, (error_buffer, "error: %d '%s'", + mysql_errno(mysql), mysql_error(mysql))); my_error(error_code, MYF(0), error_buffer); goto error; @@ -2035,7 +2036,7 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, } if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length())) { - my_sprintf(error_buffer, (error_buffer, ": %d : %s", + my_sprintf(error_buffer, (error_buffer, "error: %d '%s'", mysql_errno(mysql), mysql_error(mysql))); retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE; goto error; @@ -2615,8 +2616,7 @@ int ha_federated::stash_remote_error() { DBUG_ENTER("ha_federated::stash_remote_error()"); remote_error_number= mysql_errno(mysql); - my_snprintf(remote_error_buf, FEDERATED_QUERY_BUFFER_SIZE, - mysql_error(mysql)); + strmake(remote_error_buf, mysql_error(mysql), sizeof(remote_error_buf)-1); DBUG_RETURN(HA_FEDERATED_ERROR_WITH_REMOTE_SYSTEM); } @@ -2627,10 +2627,10 @@ bool ha_federated::get_error_message(int error, String* buf) DBUG_PRINT("enter", ("error: %d", error)); if (error == HA_FEDERATED_ERROR_WITH_REMOTE_SYSTEM) { - buf->append("Error on remote system: "); + buf->append(STRING_WITH_LEN("Error on remote system: ")); buf->qs_append(remote_error_number); - buf->append(": "); - buf->append(remote_error_buf, FEDERATED_QUERY_BUFFER_SIZE); + buf->append(STRING_WITH_LEN(": ")); + buf->append(remote_error_buf); remote_error_number= 0; remote_error_buf[0]= '\0'; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index c9aa08f3992..744bd242fca 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -142,15 +142,16 @@ uint innobase_init_flags = 0; ulong innobase_cache_size = 0; ulong innobase_large_page_size = 0; -/* The default values for the following, type long, start-up parameters -are declared in mysqld.cc: */ +/* The default values for the following, type long or longlong, start-up +parameters are declared in mysqld.cc: */ long innobase_mirrored_log_groups, innobase_log_files_in_group, - innobase_log_file_size, innobase_log_buffer_size, - innobase_buffer_pool_awe_mem_mb, - innobase_buffer_pool_size, innobase_additional_mem_pool_size, - innobase_file_io_threads, innobase_lock_wait_timeout, - innobase_force_recovery, innobase_open_files; + innobase_log_buffer_size, innobase_buffer_pool_awe_mem_mb, + innobase_additional_mem_pool_size, innobase_file_io_threads, + innobase_lock_wait_timeout, innobase_force_recovery, + innobase_open_files; + +longlong innobase_buffer_pool_size, innobase_log_file_size; /* The default values for the following char* start-up parameters are determined in innobase_init below: */ @@ -812,6 +813,7 @@ ha_innobase::ha_innobase(TABLE *table_arg) HA_CAN_SQL_HANDLER | HA_NOT_EXACT_COUNT | HA_PRIMARY_KEY_IN_READ_INDEX | + HA_CAN_GEOMETRY | HA_TABLE_SCAN_ON_INDEX), last_dup_key((uint) -1), start_of_scan(0), @@ -1209,6 +1211,25 @@ innobase_init(void) ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); + /* Check that values don't overflow on 32-bit systems. */ + if (sizeof(ulint) == 4) { + if (innobase_buffer_pool_size > UINT_MAX32) { + sql_print_error( + "innobase_buffer_pool_size can't be over 4GB" + " on 32-bit systems"); + + goto error; + } + + if (innobase_log_file_size > UINT_MAX32) { + sql_print_error( + "innobase_log_file_size can't be over 4GB" + " on 32-bit systems"); + + goto error; + } + } + os_innodb_umask = (ulint)my_umask; /* First calculate the default path for innodb_data_home_dir etc., @@ -2177,11 +2198,13 @@ innobase_savepoint( DBUG_ENTER("innobase_savepoint"); - if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { - /* In the autocommit state there is no sense to set a - savepoint: we return immediate success */ - DBUG_RETURN(0); - } + /* + In the autocommit mode there is no sense to set a savepoint + (unless we are in sub-statement), so SQL layer ensures that + this method is never called in such situation. + */ + DBUG_ASSERT(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) || + thd->in_sub_stmt); trx = check_trx_exists(thd); @@ -2496,6 +2519,12 @@ ha_innobase::open( DBUG_RETURN(0); } +uint +ha_innobase::max_supported_key_part_length() const +{ + return(DICT_MAX_INDEX_COL_LEN - 1); +} + /********************************************************************** Closes a handle to an InnoDB table. */ @@ -2757,6 +2786,7 @@ get_innobase_type_from_mysql_type( return(DATA_DOUBLE); case FIELD_TYPE_DECIMAL: return(DATA_DECIMAL); + case FIELD_TYPE_GEOMETRY: case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_BLOB: @@ -3007,8 +3037,8 @@ ha_innobase::store_key_val_for_row( if (key_part->length > 0 && cs->mbmaxlen > 1) { len = (ulint) cs->cset->well_formed_len(cs, - src_start, - src_start + key_part->length, + (const char *) src_start, + (const char *) src_start + key_part->length, key_part->length / cs->mbmaxlen, &error); } else { @@ -4651,6 +4681,9 @@ create_index( 0, prefix_len); } + /* Even though we've defined max_supported_key_part_length, we + still do our own checking using field_lengths to be absolutely + sure we don't create too long indexes. */ error = row_create_index_for_mysql(index, trx, field_lengths); error = convert_error_code_to_mysql(error, NULL); @@ -5709,6 +5742,7 @@ ha_innobase::update_table_comment( uint length = (uint) strlen(comment); char* str; row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; + long flen; /* We do not know if MySQL can call this function before calling external_lock(). To be safe, update the thd of the current table @@ -5728,43 +5762,43 @@ ha_innobase::update_table_comment( trx_search_latch_release_if_reserved(prebuilt->trx); str = NULL; - if (FILE* file = os_file_create_tmpfile()) { - long flen; + /* output the data to a temporary file */ + + mutex_enter_noninline(&srv_dict_tmpfile_mutex); + rewind(srv_dict_tmpfile); - /* output the data to a temporary file */ - fprintf(file, "InnoDB free: %lu kB", + fprintf(srv_dict_tmpfile, "InnoDB free: %lu kB", (ulong) fsp_get_available_space_in_free_extents( prebuilt->table->space)); - dict_print_info_on_foreign_keys(FALSE, file, + dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile, prebuilt->trx, prebuilt->table); - flen = ftell(file); - if (flen < 0) { - flen = 0; - } else if (length + flen + 3 > 64000) { - flen = 64000 - 3 - length; - } + flen = ftell(srv_dict_tmpfile); + if (flen < 0) { + flen = 0; + } else if (length + flen + 3 > 64000) { + flen = 64000 - 3 - length; + } - /* allocate buffer for the full string, and - read the contents of the temporary file */ + /* allocate buffer for the full string, and + read the contents of the temporary file */ - str = my_malloc(length + flen + 3, MYF(0)); + str = my_malloc(length + flen + 3, MYF(0)); - if (str) { - char* pos = str + length; - if (length) { - memcpy(str, comment, length); - *pos++ = ';'; - *pos++ = ' '; - } - rewind(file); - flen = (uint) fread(pos, 1, flen, file); - pos[flen] = 0; + if (str) { + char* pos = str + length; + if (length) { + memcpy(str, comment, length); + *pos++ = ';'; + *pos++ = ' '; } - - fclose(file); + rewind(srv_dict_tmpfile); + flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile); + pos[flen] = 0; } + mutex_exit_noninline(&srv_dict_tmpfile_mutex); + prebuilt->trx->op_info = (char*)""; return(str ? str : (char*) comment); @@ -5782,6 +5816,7 @@ ha_innobase::get_foreign_key_create_info(void) { row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; char* str = 0; + long flen; ut_a(prebuilt != NULL); @@ -5791,47 +5826,42 @@ ha_innobase::get_foreign_key_create_info(void) update_thd(current_thd); - if (FILE* file = os_file_create_tmpfile()) { - long flen; + prebuilt->trx->op_info = (char*)"getting info on foreign keys"; - prebuilt->trx->op_info = (char*)"getting info on foreign keys"; + /* In case MySQL calls this in the middle of a SELECT query, + release possible adaptive hash latch to avoid + deadlocks of threads */ - /* In case MySQL calls this in the middle of a SELECT query, - release possible adaptive hash latch to avoid - deadlocks of threads */ + trx_search_latch_release_if_reserved(prebuilt->trx); - trx_search_latch_release_if_reserved(prebuilt->trx); + mutex_enter_noninline(&srv_dict_tmpfile_mutex); + rewind(srv_dict_tmpfile); - /* output the data to a temporary file */ - dict_print_info_on_foreign_keys(TRUE, file, + /* output the data to a temporary file */ + dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile, prebuilt->trx, prebuilt->table); - prebuilt->trx->op_info = (char*)""; - - flen = ftell(file); - if (flen < 0) { - flen = 0; - } else if (flen > 64000 - 1) { - flen = 64000 - 1; - } + prebuilt->trx->op_info = (char*)""; - /* allocate buffer for the string, and - read the contents of the temporary file */ + flen = ftell(srv_dict_tmpfile); + if (flen < 0) { + flen = 0; + } else if (flen > 64000 - 1) { + flen = 64000 - 1; + } - str = my_malloc(flen + 1, MYF(0)); + /* allocate buffer for the string, and + read the contents of the temporary file */ - if (str) { - rewind(file); - flen = (uint) fread(str, 1, flen, file); - str[flen] = 0; - } + str = my_malloc(flen + 1, MYF(0)); - fclose(file); - } else { - /* unable to create temporary file */ - str = my_strdup( -"/* Error: cannot display foreign key constraints */", MYF(0)); + if (str) { + rewind(srv_dict_tmpfile); + flen = (uint) fread(str, 1, flen, srv_dict_tmpfile); + str[flen] = 0; } + mutex_exit_noninline(&srv_dict_tmpfile_mutex); + return(str); } diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 78cd0f927e9..58051624f89 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -110,7 +110,7 @@ class ha_innobase: public handler but currently MySQL does not work with keys whose size is > MAX_KEY_LENGTH */ uint max_supported_key_length() const { return 3500; } - uint max_supported_key_part_length() const { return 3500; } + uint max_supported_key_part_length() const; const key_map *keys_to_use_for_scanning() { return &key_map_full; } bool has_transactions() { return 1;} @@ -206,8 +206,9 @@ extern ulong innobase_large_page_size; extern char *innobase_home, *innobase_tmpdir, *innobase_logdir; extern long innobase_lock_scan_time; extern long innobase_mirrored_log_groups, innobase_log_files_in_group; -extern long innobase_log_file_size, innobase_log_buffer_size; -extern long innobase_buffer_pool_size, innobase_additional_mem_pool_size; +extern longlong innobase_buffer_pool_size, innobase_log_file_size; +extern long innobase_log_buffer_size; +extern long innobase_additional_mem_pool_size; extern long innobase_buffer_pool_awe_mem_mb; extern long innobase_file_io_threads, innobase_lock_wait_timeout; extern long innobase_force_recovery; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 70137ff2b16..08fd2d9a8e3 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -40,7 +40,7 @@ TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"", myisam_recover_names, NULL}; const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal", - NullS}; + "nulls_ignored", NullS}; TYPELIB myisam_stats_method_typelib= { array_elements(myisam_stats_method_names) - 1, "", myisam_stats_method_names, NULL}; @@ -985,11 +985,16 @@ int ha_myisam::enable_indexes(uint mode) { sql_print_warning("Warning: Enabling keys got errno %d, retrying", my_errno); - thd->clear_error(); + /* Repairing by sort failed. Now try standard repair method. */ param.testflag&= ~(T_REP_BY_SORT | T_QUICK); error= (repair(thd,param,0) != HA_ADMIN_OK); - if (!error && thd->net.report_error) - error= HA_ERR_CRASHED; + /* + If the standard repair succeeded, clear all error messages which + might have been set by the first repair. They can still be seen + with SHOW WARNINGS then. + */ + if (! error) + thd->clear_error(); } info(HA_STATUS_CONST); thd->proc_info=save_proc_info; diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 5911d6c0fbc..da4136def68 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -490,10 +490,10 @@ void ha_myisammrg::append_create_info(String *packet) if (file->merge_insert_method != MERGE_INSERT_DISABLED) { - packet->append(" INSERT_METHOD=",15); + packet->append(STRING_WITH_LEN(" INSERT_METHOD=")); packet->append(get_type(&merge_insert_method,file->merge_insert_method-1)); } - packet->append(" UNION=(",8); + packet->append(STRING_WITH_LEN(" UNION=(")); MYRG_TABLE *open_table,*first; current_db= table->s->db; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index b3d5d86dc52..699b3f05a70 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -78,6 +78,8 @@ handlerton ndbcluster_hton = { #define NDB_FAILED_AUTO_INCREMENT ~(Uint64)0 #define NDB_AUTO_INCREMENT_RETRIES 10 +#define NDB_INVALID_SCHEMA_OBJECT 241 + #define ERR_PRINT(err) \ DBUG_PRINT("error", ("%d message: %s", err.code, err.message)) @@ -296,8 +298,23 @@ Thd_ndb::Thd_ndb() Thd_ndb::~Thd_ndb() { if (ndb) + { +#ifndef DBUG_OFF + Ndb::Free_list_usage tmp; + tmp.m_name= 0; + while (ndb->get_free_list_usage(&tmp)) + { + uint leaked= (uint) tmp.m_created - tmp.m_free; + if (leaked) + fprintf(stderr, "NDB: Found %u %s%s that %s not been released\n", + leaked, tmp.m_name, + (leaked == 1)?"":"'s", + (leaked == 1)?"has":"have"); + } +#endif delete ndb; - ndb= NULL; + ndb= NULL; + } changed_tables.empty(); } @@ -588,9 +605,9 @@ static bool ndb_supported_type(enum_field_types type) case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: case MYSQL_TYPE_BIT: + case MYSQL_TYPE_GEOMETRY: return TRUE; case MYSQL_TYPE_NULL: - case MYSQL_TYPE_GEOMETRY: break; } return FALSE; @@ -2796,8 +2813,26 @@ void ha_ndbcluster::position(const byte *record) } *buff++= 0; } - memcpy(buff, record + key_part->offset, key_part->length); - buff += key_part->length; + + size_t len = key_part->length; + const byte * ptr = record + key_part->offset; + Field *field = key_part->field; + if ((field->type() == MYSQL_TYPE_VARCHAR) && + ((Field_varstring*)field)->length_bytes == 1) + { + /** + * Keys always use 2 bytes length + */ + buff[0] = ptr[0]; + buff[1] = 0; + memcpy(buff+2, ptr + 1, len); + len += 2; + } + else + { + memcpy(buff, ptr, len); + } + buff += len; } } else @@ -3318,14 +3353,20 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion())); } - if (m_table != (void *)tab || m_table_version < tab->getObjectVersion()) + if (m_table_version < tab->getObjectVersion()) { /* - The table has been altered, refresh the index list + The table has been altered, caller has to retry */ - build_index_list(ndb, table, ILBP_OPEN); + NdbError err= ndb->getNdbError(NDB_INVALID_SCHEMA_OBJECT); + DBUG_RETURN(ndb_to_mysql_error(&err)); + } + if (m_table != (void *)tab) + { m_table= (void *)tab; m_table_version = tab->getObjectVersion(); + if (!(my_errno= build_index_list(ndb, table, ILBP_OPEN))) + DBUG_RETURN(my_errno); } m_table_info= tab_info; } @@ -3716,6 +3757,7 @@ static int create_ndb_column(NDBCOL &col, col.setStripeSize(0); break; //mysql_type_blob: + case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_BLOB: if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin) col.setType(NDBCOL::Blob); @@ -3781,7 +3823,6 @@ static int create_ndb_column(NDBCOL &col, break; } case MYSQL_TYPE_NULL: - case MYSQL_TYPE_GEOMETRY: goto mysql_type_unsupported; mysql_type_unsupported: default: @@ -3863,8 +3904,8 @@ int ha_ndbcluster::create(const char *name, uint pack_length, length, i, pk_length= 0; const void *data, *pack_data; char name2[FN_HEADLEN]; - bool create_from_engine= (info->table_options & HA_CREATE_FROM_ENGINE); - + bool create_from_engine= (info->table_options & HA_OPTION_CREATE_FROM_ENGINE); + DBUG_ENTER("ha_ndbcluster::create"); DBUG_PRINT("enter", ("name: %s", name)); fn_format(name2, name, "", "",2); // Remove the .frm extension @@ -3933,6 +3974,7 @@ int ha_ndbcluster::create(const char *name, * 5 - from extra words added by tup/dict?? */ switch (form->field[i]->real_type()) { + case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: @@ -4208,6 +4250,7 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg): HA_AUTO_PART_KEY | HA_NO_PREFIX_CHAR_KEYS | HA_NEED_READ_RANGE_BUFFER | + HA_CAN_GEOMETRY | HA_CAN_BIT_FIELD), m_share(0), m_use_write(FALSE), @@ -4861,10 +4904,24 @@ bool ndbcluster_end() (void) pthread_mutex_unlock(&LOCK_ndb_util_thread); if (g_ndb) + { +#ifndef DBUG_OFF + Ndb::Free_list_usage tmp; + tmp.m_name= 0; + while (g_ndb->get_free_list_usage(&tmp)) + { + uint leaked= (uint) tmp.m_created - tmp.m_free; + if (leaked) + fprintf(stderr, "NDB: Found %u %s%s that %s not been released\n", + leaked, tmp.m_name, + (leaked == 1)?"":"'s", + (leaked == 1)?"has":"have"); + } +#endif delete g_ndb; - g_ndb= NULL; - if (g_ndb_cluster_connection) - delete g_ndb_cluster_connection; + g_ndb= NULL; + } + delete g_ndb_cluster_connection; g_ndb_cluster_connection= NULL; hash_free(&ndbcluster_open_tables); @@ -7409,7 +7466,8 @@ ndbcluster_show_status(THD* thd) if (have_ndbcluster != SHOW_OPTION_YES) { my_message(ER_NOT_SUPPORTED_YET, - "Cannot call SHOW NDBCLUSTER STATUS because skip-ndbcluster is defined", + "Cannot call SHOW NDBCLUSTER STATUS because skip-ndbcluster is " + "defined", MYF(0)); DBUG_RETURN(TRUE); } @@ -7420,13 +7478,15 @@ ndbcluster_show_status(THD* thd) field_list.push_back(new Item_return_int("free", 10,MYSQL_TYPE_LONG)); field_list.push_back(new Item_return_int("sizeof", 10,MYSQL_TYPE_LONG)); - if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + if (protocol->send_fields(&field_list, + Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); if (get_thd_ndb(thd) && get_thd_ndb(thd)->ndb) { Ndb* ndb= (get_thd_ndb(thd))->ndb; - Ndb::Free_list_usage tmp; tmp.m_name= 0; + Ndb::Free_list_usage tmp; + tmp.m_name= 0; while (ndb->get_free_list_usage(&tmp)) { protocol->prepare_for_resend(); diff --git a/sql/handler.cc b/sql/handler.cc index 416455c9bb9..4e128eb5938 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -60,7 +60,7 @@ handlerton example_hton = { "EXAMPLE", SHOW_OPTION_NO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, HTON_NO_FLAGS }; #endif -#ifdef HAVE_ARCHIVE_DB +#if defined(HAVE_ARCHIVE_DB) #include "ha_archive.h" extern handlerton archive_hton; #else @@ -293,61 +293,76 @@ enum db_type ha_checktype(THD *thd, enum db_type database_type, } /* ha_checktype */ -handler *get_new_handler(TABLE *table, enum db_type db_type) +handler *get_new_handler(TABLE *table, MEM_ROOT *alloc, enum db_type db_type) { switch (db_type) { #ifndef NO_HASH case DB_TYPE_HASH: - return new ha_hash(table); + return new (alloc) ha_hash(table); #endif + case DB_TYPE_MRG_MYISAM: case DB_TYPE_MRG_ISAM: - return new ha_myisammrg(table); + return new (alloc) ha_myisammrg(table); #ifdef HAVE_BERKELEY_DB case DB_TYPE_BERKELEY_DB: - return new ha_berkeley(table); + if (have_berkeley_db == SHOW_OPTION_YES) + return new (alloc) ha_berkeley(table); + return NULL; #endif #ifdef HAVE_INNOBASE_DB case DB_TYPE_INNODB: - return new ha_innobase(table); + if (have_innodb == SHOW_OPTION_YES) + return new (alloc) ha_innobase(table); + return NULL; #endif #ifdef HAVE_EXAMPLE_DB case DB_TYPE_EXAMPLE_DB: - return new ha_example(table); + if (have_example_db == SHOW_OPTION_YES) + return new (alloc) ha_example(table); + return NULL; #endif -#ifdef HAVE_ARCHIVE_DB +#if defined(HAVE_ARCHIVE_DB) case DB_TYPE_ARCHIVE_DB: - return new ha_archive(table); + if (have_archive_db == SHOW_OPTION_YES) + return new (alloc) ha_archive(table); + return NULL; #endif #ifdef HAVE_BLACKHOLE_DB case DB_TYPE_BLACKHOLE_DB: - return new ha_blackhole(table); + if (have_blackhole_db == SHOW_OPTION_YES) + return new (alloc) ha_blackhole(table); + return NULL; #endif #ifdef HAVE_FEDERATED_DB case DB_TYPE_FEDERATED_DB: - return new ha_federated(table); + if (have_federated_db == SHOW_OPTION_YES) + return new (alloc) ha_federated(table); + return NULL; #endif #ifdef HAVE_CSV_DB case DB_TYPE_CSV_DB: - return new ha_tina(table); + if (have_csv_db == SHOW_OPTION_YES) + return new (alloc) ha_tina(table); + return NULL; #endif #ifdef HAVE_NDBCLUSTER_DB case DB_TYPE_NDBCLUSTER: - return new ha_ndbcluster(table); + if (have_ndbcluster == SHOW_OPTION_YES) + return new (alloc) ha_ndbcluster(table); + return NULL; #endif case DB_TYPE_HEAP: - return new ha_heap(table); + return new (alloc) ha_heap(table); default: // should never happen { enum db_type def=(enum db_type) current_thd->variables.table_type; /* Try first with 'default table type' */ if (db_type != def) - return get_new_handler(table, def); + return get_new_handler(table, alloc, def); } /* Fall back to MyISAM */ case DB_TYPE_MYISAM: - return new ha_myisam(table); - case DB_TYPE_MRG_MYISAM: - return new ha_myisammrg(table); + return new (alloc) ha_myisam(table); } } @@ -513,7 +528,7 @@ int ha_panic(enum ha_panic_function flag) if (have_federated_db == SHOW_OPTION_YES) error|= federated_db_end(); #endif -#ifdef HAVE_ARCHIVE_DB +#if defined(HAVE_ARCHIVE_DB) if (have_archive_db == SHOW_OPTION_YES) error|= archive_db_end(); #endif @@ -1145,10 +1160,10 @@ int ha_update_statistics() int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) { int error=0; - THD_TRANS *trans=&thd->transaction.all; + THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt : + &thd->transaction.all); handlerton **ht=trans->ht, **end_ht; DBUG_ENTER("ha_rollback_to_savepoint"); - DBUG_ASSERT(thd->transaction.stmt.ht[0] == 0); trans->nht=sv->nht; trans->no_2pc=0; @@ -1176,7 +1191,7 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) for (; *ht ; ht++) { int err; - if ((err= (*(*ht)->rollback)(thd, 1))) + if ((err= (*(*ht)->rollback)(thd, !thd->in_sub_stmt))) { // cannot happen my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err); error=1; @@ -1196,10 +1211,10 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) int ha_savepoint(THD *thd, SAVEPOINT *sv) { int error=0; - THD_TRANS *trans=&thd->transaction.all; + THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt : + &thd->transaction.all); handlerton **ht=trans->ht; DBUG_ENTER("ha_savepoint"); - DBUG_ASSERT(thd->transaction.stmt.ht[0] == 0); #ifdef USING_TRANSACTIONS for (; *ht; ht++) { @@ -1225,9 +1240,10 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv) int ha_release_savepoint(THD *thd, SAVEPOINT *sv) { int error=0; - handlerton **ht=thd->transaction.all.ht, **end_ht; + THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt : + &thd->transaction.all); + handlerton **ht=trans->ht, **end_ht; DBUG_ENTER("ha_release_savepoint"); - DBUG_ASSERT(thd->transaction.stmt.ht[0] == 0); end_ht=ht+sv->nht; for (; ht < end_ht; ht++) @@ -1300,7 +1316,7 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path, /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */ if (table_type == DB_TYPE_UNKNOWN || - ! (file=get_new_handler(&dummy_table, table_type))) + ! (file=get_new_handler(&dummy_table, thd->mem_root, table_type))) DBUG_RETURN(ENOENT); if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED)) @@ -1684,7 +1700,7 @@ void handler::print_error(int error, myf errflag) if (str.length() >= max_length) { str.length(max_length-4); - str.append("..."); + str.append(STRING_WITH_LEN("...")); } my_error(ER_DUP_ENTRY, MYF(0), str.c_ptr(), key_nr+1); DBUG_VOID_RETURN; @@ -2017,7 +2033,7 @@ int ha_create_table_from_engine(THD* thd, DBUG_RETURN(3); update_create_info_from_table(&create_info, &table); - create_info.table_options|= HA_CREATE_FROM_ENGINE; + create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE; if (lower_case_table_names == 2 && !(table.file->table_flags() & HA_FILE_BASED)) @@ -2470,6 +2486,7 @@ int handler::index_read_idx(byte * buf, uint index, const byte * key, TYPELIB *ha_known_exts(void) { + MEM_ROOT *mem_root= current_thd->mem_root; if (!known_extensions.type_names || mysys_usage_id != known_extensions_id) { handlerton **types; @@ -2484,7 +2501,8 @@ TYPELIB *ha_known_exts(void) { if ((*types)->state == SHOW_OPTION_YES) { - handler *file= get_new_handler(0,(enum db_type) (*types)->db_type); + handler *file= get_new_handler(0, mem_root, + (enum db_type) (*types)->db_type); for (ext= file->bas_ext(); *ext; ext++) { while ((old_ext= it++)) diff --git a/sql/handler.h b/sql/handler.h index af80f021e75..91c5be9ba39 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -45,6 +45,7 @@ #define HA_ADMIN_REJECT -6 #define HA_ADMIN_TRY_ALTER -7 #define HA_ADMIN_WRONG_CHECKSUM -8 +#define HA_ADMIN_NOT_BASE_TABLE -9 /* Bits in table_flags() to show what database can do */ @@ -400,8 +401,9 @@ struct show_table_alias_st { /* Possible flags of a handlerton */ #define HTON_NO_FLAGS 0 #define HTON_CLOSE_CURSORS_AT_COMMIT (1 << 0) -#define HTON_ALTER_NOT_SUPPORTED (1 << 1) -#define HTON_CAN_RECREATE (1 << 2) +#define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter +#define HTON_CAN_RECREATE (1 << 2) //Delete all is used fro truncate +#define HTON_HIDDEN (1 << 3) //Engine does not appear in lists typedef struct st_thd_trans { @@ -670,7 +672,7 @@ public: key_range *max_key) { return (ha_rows) 10; } virtual void position(const byte *record)=0; - virtual void info(uint)=0; + virtual void info(uint)=0; // see my_base.h for full description virtual int extra(enum ha_extra_function operation) { return 0; } virtual int extra_opt(enum ha_extra_function operation, ulong cache_size) @@ -874,7 +876,7 @@ extern ulong total_ha, total_ha_2pc; /* lookups */ enum db_type ha_resolve_by_name(const char *name, uint namelen); const char *ha_get_storage_engine(enum db_type db_type); -handler *get_new_handler(TABLE *table, enum db_type db_type); +handler *get_new_handler(TABLE *table, MEM_ROOT *alloc, enum db_type db_type); enum db_type ha_checktype(THD *thd, enum db_type database_type, bool no_substitute, bool report_error); bool ha_check_storage_engine_flag(enum db_type db_type, uint32 flag); diff --git a/sql/item.cc b/sql/item.cc index b2aca750475..34dc450b924 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -296,23 +296,6 @@ longlong Item::val_int_from_decimal() } -void *Item::operator new(size_t size, Item *reuse, uint *rsize) -{ - if (reuse && size <= reuse->rsize) - { - if (rsize) - (*rsize)= reuse->rsize; - reuse->cleanup(); - delete reuse; - TRASH((void *)reuse, size); - return (void *)reuse; - } - if (rsize) - (*rsize)= (uint) size; - return (void *)sql_alloc((uint)size); -} - - Item::Item(): rsize(0), name(0), orig_name(0), name_length(0), fixed(0), is_autogenerated_name(TRUE), @@ -383,7 +366,7 @@ void Item::print_item_w_name(String *str) if (name) { THD *thd= current_thd; - str->append(" AS ", 4); + str->append(STRING_WITH_LEN(" AS ")); append_identifier(thd, str, name, (uint) strlen(name)); } } @@ -601,16 +584,8 @@ bool Item::eq(const Item *item, bool binary_cmp) const Item *Item::safe_charset_converter(CHARSET_INFO *tocs) { - /* - Allow conversion from and to "binary". - Don't allow automatic conversion to non-Unicode charsets, - as it potentially loses data. - */ - if (collation.collation != &my_charset_bin && - tocs != &my_charset_bin && - !(tocs->state & MY_CS_UNICODE)) - return NULL; // safe conversion is not possible - return new Item_func_conv_charset(this, tocs); + Item_func_conv_charset *conv= new Item_func_conv_charset(this, tocs, 1); + return conv->safe ? conv : NULL; } @@ -700,23 +675,15 @@ Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs) { if (const_item()) { - Item_string *conv; uint cnv_errors; - char buf[MAX_FIELD_WIDTH]; - String tmp(buf, sizeof(buf), &my_charset_bin); - String cstr, *ostr= val_str(&tmp); - /* - As safe_charset_converter is not executed for - a parameter bound to NULL, ostr should never be 0. - */ - cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &cnv_errors); - if (cnv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(), - cstr.charset(), - collation.derivation))) - return NULL; - conv->str_value.copy(); - conv->str_value.mark_as_const(); - return conv; + String *ostr= val_str(&cnvstr); + cnvitem->str_value.copy(ostr->ptr(), ostr->length(), + ostr->charset(), tocs, &cnv_errors); + if (cnv_errors) + return NULL; + cnvitem->str_value.mark_as_const(); + cnvitem->max_length= cnvitem->str_value.numchars() * tocs->mbmaxlen; + return cnvitem; } return NULL; } @@ -755,7 +722,8 @@ bool Item_string::eq(const Item *item, bool binary_cmp) const { if (binary_cmp) return !stringcmp(&str_value, &item->str_value); - return !sortcmp(&str_value, &item->str_value, collation.collation); + return (collation.collation == item->collation.collation && + !sortcmp(&str_value, &item->str_value, collation.collation)); } return 0; } @@ -817,9 +785,41 @@ int Item::save_in_field_no_warnings(Field *field, bool no_conversions) /***************************************************************************** - Item_splocal methods + Item_sp_variable methods *****************************************************************************/ -double Item_splocal::val_real() + +Item_sp_variable::Item_sp_variable(char *sp_var_name_str, + uint sp_var_name_length) + :m_thd(0) +#ifndef DBUG_OFF + , m_sp(0) +#endif +{ + m_name.str= sp_var_name_str; + m_name.length= sp_var_name_length; +} + + +bool Item_sp_variable::fix_fields(THD *thd, Item **) +{ + Item *it; + + m_thd= thd; /* NOTE: this must be set before any this_xxx() */ + it= this_item(); + + DBUG_ASSERT(it->fixed); + + max_length= it->max_length; + decimals= it->decimals; + unsigned_flag= it->unsigned_flag; + fixed= 1; + collation.set(it->collation.collation, it->collation.derivation); + + return FALSE; +} + + +double Item_sp_variable::val_real() { DBUG_ASSERT(fixed); Item *it= this_item(); @@ -829,7 +829,7 @@ double Item_splocal::val_real() } -longlong Item_splocal::val_int() +longlong Item_sp_variable::val_int() { DBUG_ASSERT(fixed); Item *it= this_item(); @@ -839,13 +839,14 @@ longlong Item_splocal::val_int() } -String *Item_splocal::val_str(String *sp) +String *Item_sp_variable::val_str(String *sp) { DBUG_ASSERT(fixed); Item *it= this_item(); String *res= it->val_str(sp); null_value= it->null_value; + if (!res) return NULL; @@ -869,11 +870,12 @@ String *Item_splocal::val_str(String *sp) str_value.set(res->ptr(), res->length(), res->charset()); else res->mark_as_const(); + return &str_value; } -my_decimal *Item_splocal::val_decimal(my_decimal *decimal_value) +my_decimal *Item_sp_variable::val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed); Item *it= this_item(); @@ -883,67 +885,108 @@ my_decimal *Item_splocal::val_decimal(my_decimal *decimal_value) } -bool Item_splocal::is_null() +bool Item_sp_variable::is_null() { - Item *it= this_item(); - return it->is_null(); + return this_item()->is_null(); +} + + +/***************************************************************************** + Item_splocal methods +*****************************************************************************/ + +Item_splocal::Item_splocal(const LEX_STRING &sp_var_name, + uint sp_var_idx, + enum_field_types sp_var_type, + uint pos_in_q) + :Item_sp_variable(sp_var_name.str, sp_var_name.length), + m_var_idx(sp_var_idx), pos_in_query(pos_in_q) +{ + maybe_null= TRUE; + + m_type= sp_map_item_type(sp_var_type); + m_result_type= sp_map_result_type(sp_var_type); } Item * Item_splocal::this_item() { - return thd->spcont->get_item(m_offset); + DBUG_ASSERT(m_sp == m_thd->spcont->sp); + + return m_thd->spcont->get_item(m_var_idx); +} + +const Item * +Item_splocal::this_item() const +{ + DBUG_ASSERT(m_sp == m_thd->spcont->sp); + + return m_thd->spcont->get_item(m_var_idx); } Item ** -Item_splocal::this_item_addr(THD *thd, Item **addr) +Item_splocal::this_item_addr(THD *thd, Item **) { - return thd->spcont->get_item_addr(m_offset); + DBUG_ASSERT(m_sp == thd->spcont->sp); + + return thd->spcont->get_item_addr(m_var_idx); } -Item * -Item_splocal::this_const_item() const + +void Item_splocal::print(String *str) +{ + str->reserve(m_name.length+8); + str->append(m_name.str, m_name.length); + str->append('@'); + str->qs_append(m_var_idx); +} + + +/***************************************************************************** + Item_case_expr methods +*****************************************************************************/ + +Item_case_expr::Item_case_expr(int case_expr_id) + :Item_sp_variable((char *) STRING_WITH_LEN("case_expr")), + m_case_expr_id(case_expr_id) { - return thd->spcont->get_item(m_offset); } -Item::Type -Item_splocal::type() const + +Item * +Item_case_expr::this_item() { - if (thd && thd->spcont) - return thd->spcont->get_item(m_offset)->type(); - return NULL_ITEM; // Anything but SUBSELECT_ITEM + DBUG_ASSERT(m_sp == m_thd->spcont->sp); + + return m_thd->spcont->get_case_expr(m_case_expr_id); } -bool Item_splocal::fix_fields(THD *thd_arg, Item **ref) + +const Item * +Item_case_expr::this_item() const { - Item *it; - thd= thd_arg; // Must be set before this_item() - it= this_item(); - DBUG_ASSERT(it->fixed); - max_length= it->max_length; - decimals= it->decimals; - unsigned_flag= it->unsigned_flag; - fixed= 1; - return FALSE; + DBUG_ASSERT(m_sp == m_thd->spcont->sp); + + return m_thd->spcont->get_case_expr(m_case_expr_id); } -void Item_splocal::cleanup() +Item ** +Item_case_expr::this_item_addr(THD *thd, Item **) { - fixed= 0; + DBUG_ASSERT(m_sp == thd->spcont->sp); + + return thd->spcont->get_case_expr_addr(m_case_expr_id); } -void Item_splocal::print(String *str) +void Item_case_expr::print(String *str) { - str->reserve(m_name.length+8); - str->append(m_name.str, m_name.length); - str->append('@'); - str->qs_append(m_offset); + str->append(STRING_WITH_LEN("case_expr@")); + str->qs_append(m_case_expr_id); } @@ -1022,15 +1065,9 @@ bool Item_name_const::fix_fields(THD *thd, Item **ref) } -void Item_name_const::cleanup() -{ - fixed= 0; -} - - void Item_name_const::print(String *str) { - str->append("NAME_CONST("); + str->append(STRING_WITH_LEN("NAME_CONST(")); name_item->print(str); str->append(','); value_item->print(str); @@ -1047,6 +1084,7 @@ void Item_name_const::print(String *str) ref_pointer_array Pointer to array of reference fields fields All fields in select ref Pointer to item + skip_registered <=> function be must skipped for registered SUM items NOTES This is from split_sum_func2() for items that should be split @@ -1059,8 +1097,13 @@ void Item_name_const::print(String *str) void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, - List<Item> &fields, Item **ref) + List<Item> &fields, Item **ref, + bool skip_registered) { + /* An item of type Item_sum is registered <=> ref_by != 0 */ + if (type() == SUM_FUNC_ITEM && skip_registered && + ((Item_sum *) this)->ref_by) + return; if (type() != SUM_FUNC_ITEM && with_sum_func) { /* Will split complicated items and ignore simple ones */ @@ -2097,6 +2140,8 @@ Item_param::Item_param(unsigned pos_in_query_arg) : value is set. */ maybe_null= 1; + cnvitem= new Item_string("", 0, &my_charset_bin, DERIVATION_COERCIBLE); + cnvstr.set(cnvbuf, sizeof(cnvbuf), &my_charset_bin); } @@ -2466,7 +2511,7 @@ longlong Item_param::val_int() { switch (state) { case REAL_VALUE: - return (longlong) (value.real + (value.real > 0 ? 0.5 : -0.5)); + return (longlong) rint(value.real); case INT_VALUE: return value.integer; case DECIMAL_VALUE: @@ -3192,14 +3237,8 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) { for each outer query Q_k beginning from the inner-most one { - if - Q_k is not a group query AND - - Q_k is not inside an aggregate function - OR - - Q_(k-1) is not in a HAVING or SELECT clause of Q_k - { - search for a column or derived column named col_ref_i - [in table T_j] in the FROM clause of Q_k; - } + search for a column or derived column named col_ref_i + [in table T_j] in the FROM clause of Q_k; if such a column is not found Search for a column or derived column named col_ref_i @@ -3234,8 +3273,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference) context->last_name_resolution_table, reference, IGNORE_EXCEPT_NON_UNIQUE, - !any_privileges && - context->check_privileges, + !any_privileges, TRUE)) == not_found_field) { @@ -3248,7 +3286,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference) Item** res= find_item_in_list(this, thd->lex->current_select->item_list, &counter, REPORT_EXCEPT_NOT_FOUND, ¬_used); - if (res != not_found_item && (*res)->type() == Item::FIELD_ITEM) + if (res != (Item **)not_found_item && (*res)->type() == Item::FIELD_ITEM) { set_field((*((Item_field**)res))->field); return 0; @@ -3279,27 +3317,18 @@ bool Item_field::fix_fields(THD *thd, Item **reference) place= prev_subselect_item->parsing_place; /* - Check table fields only if the subquery is used somewhere out of - HAVING, or the outer SELECT does not use grouping (i.e. tables are - accessible). - In case of a view, find_field_in_tables() writes the pointer to the found view field into '*reference', in other words, it substitutes this Item_field with the found expression. */ - if ((place != IN_HAVING || - (!select->with_sum_func && - select->group_list.elements == 0)) && - (from_field= find_field_in_tables(thd, this, + if ((from_field= find_field_in_tables(thd, this, outer_context-> first_name_resolution_table, outer_context-> last_name_resolution_table, reference, IGNORE_EXCEPT_NON_UNIQUE, - outer_context-> - check_privileges, - TRUE)) != + TRUE, TRUE)) != not_found_field) { if (from_field) @@ -3308,6 +3337,21 @@ bool Item_field::fix_fields(THD *thd, Item **reference) { prev_subselect_item->used_tables_cache|= from_field->table->map; prev_subselect_item->const_item_cache= 0; + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level == + thd->lex->current_select->nest_level) + { + Item::Type type= (*reference)->type(); + set_if_bigger(thd->lex->in_sum_func->max_arg_level, + select->nest_level); + set_field(from_field); + fixed= 1; + mark_as_dependent(thd, last_checked_context->select_lex, + context->select_lex, this, + ((type == REF_ITEM || type == FIELD_ITEM) ? + (Item_ident*) (*reference) : 0)); + return FALSE; + } } else { @@ -3374,7 +3418,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference) context->last_name_resolution_table, reference, REPORT_ALL_ERRORS, !any_privileges && - context->check_privileges, TRUE); + TRUE, TRUE); } goto error; } @@ -3449,7 +3493,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference) We can leave expression substituted from view for next PS/SP rexecution (i.e. do not register this substitution for reverting on cleupup() (register_item_tree_changing())), because this subtree will be - fix_field'ed during setup_tables()->setup_ancestor() (i.e. before + fix_field'ed during setup_tables()->setup_underlying() (i.e. before all other expressions of query, and references on tables which do not present in query will not make problems. @@ -3459,6 +3503,11 @@ bool Item_field::fix_fields(THD *thd, Item **reference) return FALSE; set_field(from_field); + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level == + thd->lex->current_select->nest_level) + set_if_bigger(thd->lex->in_sum_func->max_arg_level, + thd->lex->current_select->nest_level); } else if (thd->set_query_id && field->query_id != thd->query_id) { @@ -3921,6 +3970,9 @@ int Item::save_in_field(Field *field, bool no_conversions) str_value.set_quick(0, 0, cs); return set_field_to_null_with_conversions(field, no_conversions); } + + /* NOTE: If null_value == FALSE, "result" must be not NULL. */ + field->set_notnull(); error=field->store(result->ptr(),result->length(),cs); str_value.set_quick(0, 0, cs); @@ -4544,8 +4596,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) last_name_resolution_table, reference, IGNORE_EXCEPT_NON_UNIQUE, - outer_context->check_privileges, - TRUE); + TRUE, TRUE); if (! from_field) goto error; if (from_field == view_ref_found) @@ -4615,9 +4666,8 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) aggregate function. */ if (((*ref)->with_sum_func && name && - (depended_from || - !(current_sel->linkage != GLOBAL_OPTIONS_TYPE && - current_sel->having_fix_field))) || + !(current_sel->linkage != GLOBAL_OPTIONS_TYPE && + current_sel->having_fix_field)) || !(*ref)->fixed) { my_error(ER_ILLEGAL_REFERENCE, MYF(0), @@ -4840,6 +4890,12 @@ int Item_ref::save_in_field(Field *to, bool no_conversions) } +void Item_ref::save_org_in_field(Field *field) +{ + (*ref)->save_org_in_field(field); +} + + void Item_ref::make_field(Send_field *field) { (*ref)->make_field(field); @@ -4855,7 +4911,7 @@ void Item_ref::make_field(Send_field *field) void Item_ref_null_helper::print(String *str) { - str->append("<ref_null_helper>(", 18); + str->append(STRING_WITH_LEN("<ref_null_helper>(")); if (ref) (*ref)->print(str); else @@ -4941,8 +4997,7 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) } /* - Compare view field's name with item's name before call to referenced - item's eq() + Compare two view column references for equality. SYNOPSIS Item_direct_view_ref::eq() @@ -4950,12 +5005,13 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) binary_cmp make binary comparison DESCRIPTION - Consider queries: - create view v1 as select t1.f1 as f2, t1.f2 as f1 from t1; - select * from v1 order by f1; - In order to choose right field for sorting we need to compare - given item's name (f1) to view field's name prior to calling - referenced item's eq(). + A view column reference is considered equal to another column + reference if the second one is a view column and if both column + references point to the same field. For views 'same field' means + the same Item_field object in the view translation table, where + the view translation table contains all result columns of the + view. This definition ensures that view columns are resolved + in the same manner as table columns. RETURN TRUE Referenced item is equal to given item @@ -4965,14 +5021,23 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) bool Item_direct_view_ref::eq(const Item *item, bool binary_cmp) const { - Item *it= ((Item *) item)->real_item(); - return (!it->name || !my_strcasecmp(system_charset_info, it->name, - field_name)) && ref && (*ref)->real_item()->eq(it, binary_cmp); + if (item->type() == REF_ITEM) + { + Item_ref *item_ref= (Item_ref*) item; + if (item_ref->ref_type() == VIEW_REF) + { + Item *item_ref_ref= *(item_ref->ref); + DBUG_ASSERT((*ref)->type() == FIELD_ITEM && + (item_ref_ref->type() == FIELD_ITEM)); + return (*ref == item_ref_ref); + } + } + return FALSE; } void Item_null_helper::print(String *str) { - str->append("<null_helper>(", 14); + str->append(STRING_WITH_LEN("<null_helper>(")); store->print(str); str->append(')'); } @@ -5032,10 +5097,10 @@ void Item_default_value::print(String *str) { if (!arg) { - str->append("default", 7); + str->append(STRING_WITH_LEN("default")); return; } - str->append("default(", 8); + str->append(STRING_WITH_LEN("default(")); arg->print(str); str->append(')'); } @@ -5084,19 +5149,36 @@ bool Item_insert_value::eq(const Item *item, bool binary_cmp) const bool Item_insert_value::fix_fields(THD *thd, Item **items) { DBUG_ASSERT(fixed == 0); - if (!arg->fixed && arg->fix_fields(thd, &arg)) - return TRUE; + /* We should only check that arg is in first table */ + if (!arg->fixed) + { + bool res; + st_table_list *orig_next_table= context->last_name_resolution_table; + context->last_name_resolution_table= context->first_name_resolution_table; + res= arg->fix_fields(thd, &arg); + context->last_name_resolution_table= orig_next_table; + if (res) + return TRUE; + } if (arg->type() == REF_ITEM) { Item_ref *ref= (Item_ref *)arg; if (ref->ref[0]->type() != FIELD_ITEM) { + my_error(ER_BAD_FIELD_ERROR, MYF(0), "", "VALUES() function"); return TRUE; } arg= ref->ref[0]; } + /* + According to our SQL grammar, VALUES() function can reference + only to a column. + */ + DBUG_ASSERT(arg->type() == FIELD_ITEM); + Item_field *field_arg= (Item_field *)arg; + if (field_arg->field->table->insert_values) { Field *def_field= (Field*) sql_alloc(field_arg->field->size_of()); @@ -5119,7 +5201,7 @@ bool Item_insert_value::fix_fields(THD *thd, Item **items) void Item_insert_value::print(String *str) { - str->append("values(", 7); + str->append(STRING_WITH_LEN("values(")); arg->print(str); str->append(')'); } @@ -5157,7 +5239,7 @@ void Item_trigger_field::setup_field(THD *thd, TABLE *table) set field_idx properly. */ (void)find_field_in_table(thd, table, field_name, (uint) strlen(field_name), - 0, 0, &field_idx); + 0, &field_idx); thd->set_query_id= save_set_query_id; triggers= table->triggers; } @@ -5238,7 +5320,7 @@ Item_result item_cmp_type(Item_result a,Item_result b) void resolve_const_item(THD *thd, Item **ref, Item *comp_item) { Item *item= *ref; - Item *new_item; + Item *new_item= NULL; if (item->basic_const_item()) return; // Can't be better Item_result res_type=item_cmp_type(comp_item->result_type(), @@ -5271,7 +5353,16 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) break; } case ROW_RESULT: + if (item->type() == Item::ROW_ITEM && comp_item->type() == Item::ROW_ITEM) { + /* + Substitute constants only in Item_rows. Don't affect other Items + with ROW_RESULT (eg Item_singlerow_subselect). + + For such Items more optimal is to detect if it is constant and replace + it with Item_row. This would optimize queries like this: + SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1); + */ Item_row *item_row= (Item_row*) item; Item_row *comp_item_row= (Item_row*) comp_item; uint col; @@ -5289,6 +5380,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) resolve_const_item(thd, item_row->addr(col), comp_item_row->el(col)); break; } + /* Fallthrough */ case REAL_RESULT: { // It must REAL_RESULT double result= item->val_real(); @@ -5380,7 +5472,7 @@ Item_cache* Item_cache::get_cache(Item_result type) void Item_cache::print(String *str) { - str->append("<cache>(", 8); + str->append(STRING_WITH_LEN("<cache>(")); if (example) example->print(str); else @@ -5423,7 +5515,7 @@ void Item_cache_real::store(Item *item) longlong Item_cache_real::val_int() { DBUG_ASSERT(fixed == 1); - return (longlong) (value+(value > 0 ? 0.5 : -0.5)); + return (longlong) rint(value); } @@ -5794,8 +5886,11 @@ bool Item_type_holder::join_types(THD *thd, Item *item) { int delta1= max_length_orig - decimals_orig; int delta2= item->max_length - item->decimals; - max_length= min(max(delta1, delta2) + decimals, - (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7); + if (fld_type == MYSQL_TYPE_DECIMAL) + max_length= max(delta1, delta2) + decimals; + else + max_length= min(max(delta1, delta2) + decimals, + (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7); } else max_length= (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7; diff --git a/sql/item.h b/sql/item.h index 3e52cbe5fd7..eee9bc5b284 100644 --- a/sql/item.h +++ b/sql/item.h @@ -159,7 +159,7 @@ struct Hybrid_type_traits { val->real/= ulonglong2double(u); } virtual longlong val_int(Hybrid_type *val, bool unsigned_flag) const - { return (longlong) val->real; } + { return (longlong) rint(val->real); } virtual double val_real(Hybrid_type *val) const { return val->real; } virtual my_decimal *val_decimal(Hybrid_type *val, my_decimal *buf) const; virtual String *val_str(Hybrid_type *val, String *buf, uint8 decimals) const; @@ -294,15 +294,15 @@ struct Name_resolution_context: Sql_alloc bool resolve_in_select_list; /* - When FALSE we do not check columns right of resolving items, used to - prevent rights check on underlying tables of view + Security context of this name resolution context. It's used for views + and is non-zero only if the view is defined with SQL SECURITY DEFINER. */ - bool check_privileges; + Security_context *security_ctx; Name_resolution_context() :outer_context(0), table_list(0), select_lex(0), error_processor_data(0), - check_privileges(TRUE) + security_ctx(0) {} void init() @@ -326,6 +326,48 @@ struct Name_resolution_context: Sql_alloc }; +/* + Store and restore the current state of a name resolution context. +*/ + +class Name_resolution_context_state +{ +private: + TABLE_LIST *save_table_list; + TABLE_LIST *save_first_name_resolution_table; + TABLE_LIST *save_next_name_resolution_table; + bool save_resolve_in_select_list; + +public: + TABLE_LIST *save_next_local; + +public: + /* Save the state of a name resolution context. */ + void save_state(Name_resolution_context *context, TABLE_LIST *table_list) + { + save_table_list= context->table_list; + save_first_name_resolution_table= context->first_name_resolution_table; + save_next_name_resolution_table= (context->first_name_resolution_table) ? + context->first_name_resolution_table-> + next_name_resolution_table : + NULL; + save_resolve_in_select_list= context->resolve_in_select_list; + save_next_local= table_list->next_local; + } + + /* Restore a name resolution context from saved state. */ + void restore_state(Name_resolution_context *context, TABLE_LIST *table_list) + { + table_list->next_local= save_next_local; + context->table_list= save_table_list; + context->first_name_resolution_table= save_first_name_resolution_table; + if (context->first_name_resolution_table) + context->first_name_resolution_table-> + next_name_resolution_table= save_next_name_resolution_table; + context->resolve_in_select_list= save_resolve_in_select_list; + } +}; + /*************************************************************************/ typedef bool (Item::*Item_processor)(byte *arg); @@ -341,8 +383,6 @@ public: { return (void*) sql_alloc((uint) size); } static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } - /* Special for SP local variable assignment - reusing slots */ - static void *operator new(size_t size, Item *reuse, uint *rsize); static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} @@ -526,6 +566,7 @@ public: double val_real_from_decimal(); virtual Field *get_tmp_table_field() { return 0; } + /* This is also used to create fields in CREATE ... SELECT: */ virtual Field *tmp_table_field(TABLE *t_arg) { return 0; } virtual const char *full_name() const { return name ? name : "???"; } @@ -599,7 +640,7 @@ public: List<Item> &fields) {} /* Called for items that really have to be split */ void split_sum_func2(THD *thd, Item **ref_pointer_array, List<Item> &fields, - Item **ref); + Item **ref, bool skip_registered); virtual bool get_date(TIME *ltime,uint fuzzydate); virtual bool get_time(TIME *ltime); virtual bool get_date_result(TIME *ltime,uint fuzzydate) @@ -670,13 +711,13 @@ public: current value and pointer to current Item otherwise. */ virtual Item *this_item() { return this; } + virtual const Item *this_item() const { return this; } + /* For SP local variable returns address of pointer to Item representing its current value and pointer passed via parameter otherwise. */ virtual Item **this_item_addr(THD *thd, Item **addr) { return addr; } - /* For SPs mostly. */ - virtual Item *this_const_item() const { return const_cast<Item*>(this); } // Row emulation virtual uint cols() { return 1; } @@ -703,26 +744,109 @@ public: }; -/* - A reference to local SP variable (incl. reference to SP parameter), used in - runtime. - - NOTE - This item has a "value" item, defined as - this_item() = thd->spcont->get_item(m_offset) - and it delegates everything to that item (if !this_item() then this item - poses as Item_null) except for name, which is the name of SP local - variable. -*/ +class sp_head; + -class Item_splocal : public Item +/***************************************************************************** + The class is a base class for representation of stored routine variables in + the Item-hierarchy. There are the following kinds of SP-vars: + - local variables (Item_splocal); + - CASE expression (Item_case_expr); +*****************************************************************************/ + +class Item_sp_variable :public Item { - uint m_offset; +protected: + /* + THD, which is stored in fix_fields() and is used in this_item() to avoid + current_thd use. + */ + THD *m_thd; public: LEX_STRING m_name; - THD *thd; + /* + Buffer, pointing to the string value of the item. We need it to + protect internal buffer from changes. See comment to analogous + member in Item_param for more details. + */ + String str_value_ptr; + +public: +#ifndef DBUG_OFF + /* + Routine to which this Item_splocal belongs. Used for checking if correct + runtime context is used for variable handling. + */ + sp_head *m_sp; +#endif + +public: + Item_sp_variable(char *sp_var_name_str, uint sp_var_name_length); + +public: + bool fix_fields(THD *thd, Item **); + + double val_real(); + longlong val_int(); + String *val_str(String *sp); + my_decimal *val_decimal(my_decimal *decimal_value); + bool is_null(); + +public: + inline void make_field(Send_field *field); + + inline bool const_item() const; + + inline int save_in_field(Field *field, bool no_conversions); + inline bool send(Protocol *protocol, String *str); +}; + +/***************************************************************************** + Item_sp_variable inline implementation. +*****************************************************************************/ + +inline void Item_sp_variable::make_field(Send_field *field) +{ + Item *it= this_item(); + + if (name) + it->set_name(name, (uint) strlen(name), system_charset_info); + else + it->set_name(m_name.str, m_name.length, system_charset_info); + it->make_field(field); +} + +inline bool Item_sp_variable::const_item() const +{ + return TRUE; +} + +inline int Item_sp_variable::save_in_field(Field *field, bool no_conversions) +{ + return this_item()->save_in_field(field, no_conversions); +} + +inline bool Item_sp_variable::send(Protocol *protocol, String *str) +{ + return this_item()->send(protocol, str); +} + + +/***************************************************************************** + A reference to local SP variable (incl. reference to SP parameter), used in + runtime. +*****************************************************************************/ + +class Item_splocal :public Item_sp_variable +{ + uint m_var_idx; + + Type m_type; + Item_result m_result_type; + +public: /* Position of this reference to SP variable in the statement (the statement itself is in sp_instr_stmt::m_query). @@ -735,78 +859,94 @@ public: */ uint pos_in_query; - Item_splocal(LEX_STRING name, uint offset, uint pos_in_q=0) - : m_offset(offset), m_name(name), thd(0), pos_in_query(pos_in_q) - { - maybe_null= TRUE; - } - - /* For error printing */ - inline LEX_STRING *my_name(LEX_STRING *get_name) - { - if (!get_name) - return &m_name; - (*get_name)= m_name; - return get_name; - } + Item_splocal(const LEX_STRING &sp_var_name, uint sp_var_idx, + enum_field_types sp_var_type, uint pos_in_q= 0); bool is_splocal() { return 1; } /* Needed for error checking */ Item *this_item(); + const Item *this_item() const; Item **this_item_addr(THD *thd, Item **); - Item *this_const_item() const; - bool fix_fields(THD *, Item **); - void cleanup(); + void print(String *str); - inline uint get_offset() - { - return m_offset; - } +public: + inline const LEX_STRING *my_name() const; - // Abstract methods inherited from Item. Just defer the call to - // the item in the frame - enum Type type() const; + inline uint get_var_idx() const; - double val_real(); - longlong val_int(); - String *val_str(String *sp); - my_decimal *val_decimal(my_decimal *); - bool is_null(); - void print(String *str); + inline enum Type type() const; + inline Item_result result_type() const; +}; - void make_field(Send_field *field) - { - Item *it= this_item(); +/***************************************************************************** + Item_splocal inline implementation. +*****************************************************************************/ - if (name) - it->set_name(name, (uint) strlen(name), system_charset_info); - else - it->set_name(m_name.str, m_name.length, system_charset_info); - it->make_field(field); - } +inline const LEX_STRING *Item_splocal::my_name() const +{ + return &m_name; +} - Item_result result_type() const - { - return this_const_item()->result_type(); - } +inline uint Item_splocal::get_var_idx() const +{ + return m_var_idx; +} - bool const_item() const - { - return TRUE; - } +inline enum Item::Type Item_splocal::type() const +{ + return m_type; +} - int save_in_field(Field *field, bool no_conversions) - { - return this_item()->save_in_field(field, no_conversions); - } +inline Item_result Item_splocal::result_type() const +{ + return m_result_type; +} - bool send(Protocol *protocol, String *str) - { - return this_item()->send(protocol, str); - } + +/***************************************************************************** + A reference to case expression in SP, used in runtime. +*****************************************************************************/ + +class Item_case_expr :public Item_sp_variable +{ +public: + Item_case_expr(int case_expr_id); + +public: + Item *this_item(); + const Item *this_item() const; + Item **this_item_addr(THD *thd, Item **); + + inline enum Type type() const; + inline Item_result result_type() const; + +public: + /* + NOTE: print() is intended to be used from views and for debug. + Item_case_expr can not occur in views, so here it is only for debug + purposes. + */ + void print(String *str); + +private: + int m_case_expr_id; }; +/***************************************************************************** + Item_case_expr inline implementation. +*****************************************************************************/ + +inline enum Item::Type Item_case_expr::type() const +{ + return this_item()->type(); +} + +inline Item_result Item_case_expr::result_type() const +{ + return this_item()->result_type(); +} + /* NAME_CONST(given_name, const_value). @@ -833,7 +973,6 @@ public: } bool fix_fields(THD *, Item **); - void cleanup(); enum Type type() const; double val_real(); @@ -1054,7 +1193,7 @@ public: bool basic_const_item() const { return 1; } Item *new_item() { return new Item_null(name); } bool is_null() { return 1; } - void print(String *str) { str->append("NULL", 4); } + void print(String *str) { str->append(STRING_WITH_LEN("NULL")); } Item *safe_charset_converter(CHARSET_INFO *tocs); }; @@ -1074,7 +1213,11 @@ public: class Item_param :public Item { + char cnvbuf[MAX_FIELD_WIDTH]; + String cnvstr; + Item *cnvitem; public: + enum enum_item_param_state { NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE, @@ -1340,7 +1483,7 @@ public: { return LONGLONG_MAX; } - return (longlong) (value+(value > 0 ? 0.5 : -0.5)); + return (longlong) rint(value); } String *val_str(String*); my_decimal *val_decimal(my_decimal *); @@ -1602,7 +1745,7 @@ public: void make_field(Send_field *field); bool fix_fields(THD *, Item **); int save_in_field(Field *field, bool no_conversions); - void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } + void save_org_in_field(Field *field); enum Item_result result_type () const { return (*ref)->result_type(); } enum_field_types field_type() const { return (*ref)->field_type(); } Field *get_tmp_table_field() @@ -1749,6 +1892,7 @@ public: return ref->save_in_field(field, no_conversions); } Item *new_item(); + virtual Item *real_item() { return ref; } }; @@ -1908,6 +2052,16 @@ public: } }; +/* + Item_insert_value -- an implementation of VALUES() function. + You can use the VALUES(col_name) function in the UPDATE clause + to refer to column values from the INSERT portion of the INSERT + ... UPDATE statement. In other words, VALUES(col_name) in the + UPDATE clause refers to the value of col_name that would be + inserted, had no duplicate-key conflict occurred. + In all other places this function returns NULL. +*/ + class Item_insert_value : public Item_field { public: diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 761d15c8a3e..15614a32c39 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -25,6 +25,8 @@ #include <m_ctype.h> #include "sql_select.h" +static bool convert_constant_item(THD *thd, Field *field, Item **item); + static Item_result item_store_type(Item_result a,Item_result b) { if (a == STRING_RESULT || b == STRING_RESULT) @@ -45,14 +47,37 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) type[0]= item_store_type(type[0], items[i]->result_type()); } -static void agg_cmp_type(Item_result *type, Item **items, uint nitems) + +static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) { uint i; + Field *field= NULL; + bool all_constant= TRUE; + + /* If the first argument is a FIELD_ITEM, pull out the field. */ + if (items[0]->type() == Item::FIELD_ITEM) + field=((Item_field *)items[0])->field; + /* But if it can't be compared as a longlong, we don't really care. */ + if (field && !field->can_be_compared_as_longlong()) + field= NULL; + type[0]= items[0]->result_type(); - for (i=1 ; i < nitems ; i++) + for (i= 1; i < nitems; i++) + { type[0]= item_cmp_type(type[0], items[i]->result_type()); + if (field && !convert_constant_item(thd, field, &items[i])) + all_constant= FALSE; + } + + /* + If we had a field that can be compared as a longlong, and all constant + items, then the aggregate result will be an INT_RESULT. + */ + if (field && all_constant) + type[0]= INT_RESULT; } + static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) { @@ -186,13 +211,18 @@ static bool convert_constant_item(THD *thd, Field *field, Item **item) { if ((*item)->const_item()) { + /* For comparison purposes allow invalid dates like 2000-01-32 */ + ulong orig_sql_mode= field->table->in_use->variables.sql_mode; + field->table->in_use->variables.sql_mode|= MODE_INVALID_DATES; if (!(*item)->save_in_field(field, 1) && !((*item)->null_value)) { Item *tmp=new Item_int_with_ref(field->val_int(), *item); + field->table->in_use->variables.sql_mode= orig_sql_mode; if (tmp) thd->change_item_tree(item, tmp); return 1; // Item was replaced } + field->table->in_use->variables.sql_mode= orig_sql_mode; } return 0; } @@ -1046,32 +1076,11 @@ void Item_func_between::fix_length_and_dec() */ if (!args[0] || !args[1] || !args[2]) return; - agg_cmp_type(&cmp_type, args, 3); + agg_cmp_type(thd, &cmp_type, args, 3); + if (cmp_type == STRING_RESULT && agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV)) return; - - /* - Make a special ease of compare with date/time and longlong fields. - They are compared as integers, so for const item this time-consuming - conversion can be done only once, not for every single comparison - */ - if (args[0]->type() == FIELD_ITEM) - { - Field *field=((Item_field*) args[0])->field; - if (!thd->is_context_analysis_only() && - field->can_be_compared_as_longlong()) - { - /* - The following can't be recoded with || as convert_constant_item - changes the argument - */ - if (convert_constant_item(thd, field,&args[1])) - cmp_type=INT_RESULT; // Works for all types. - if (convert_constant_item(thd, field,&args[2])) - cmp_type=INT_RESULT; // Works for all types. - } - } } @@ -1170,10 +1179,10 @@ void Item_func_between::print(String *str) str->append('('); args[0]->print(str); if (negated) - str->append(" not", 4); - str->append(" between ", 9); + str->append(STRING_WITH_LEN(" not")); + str->append(STRING_WITH_LEN(" between ")); args[1]->print(str); - str->append(" and ", 5); + str->append(STRING_WITH_LEN(" and ")); args[2]->print(str); str->append(')'); } @@ -1717,6 +1726,7 @@ void Item_func_case::fix_length_and_dec() { Item **agg; uint nagg; + THD *thd= current_thd; if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1)))) return; @@ -1748,7 +1758,7 @@ void Item_func_case::fix_length_and_dec() for (nagg= 0; nagg < ncases/2 ; nagg++) agg[nagg+1]= args[nagg*2]; nagg++; - agg_cmp_type(&cmp_type, agg, nagg); + agg_cmp_type(thd, &cmp_type, agg, nagg); if ((cmp_type == STRING_RESULT) && agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV)) return; @@ -1788,7 +1798,7 @@ uint Item_func_case::decimal_precision() const void Item_func_case::print(String *str) { - str->append("(case ", 6); + str->append(STRING_WITH_LEN("(case ")); if (first_expr_num != -1) { args[first_expr_num]->print(str); @@ -1796,19 +1806,19 @@ void Item_func_case::print(String *str) } for (uint i=0 ; i < ncases ; i+=2) { - str->append("when ", 5); + str->append(STRING_WITH_LEN("when ")); args[i]->print(str); - str->append(" then ", 6); + str->append(STRING_WITH_LEN(" then ")); args[i+1]->print(str); str->append(' '); } if (else_expr_num != -1) { - str->append("else ", 5); + str->append(STRING_WITH_LEN("else ")); args[else_expr_num]->print(str); str->append(' '); } - str->append("end)", 4); + str->append(STRING_WITH_LEN("end)")); } /* @@ -2341,7 +2351,7 @@ void Item_func_in::fix_length_and_dec() uint const_itm= 1; THD *thd= current_thd; - agg_cmp_type(&cmp_type, args, arg_count); + agg_cmp_type(thd, &cmp_type, args, arg_count); if (cmp_type == STRING_RESULT && agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV)) @@ -2414,10 +2424,10 @@ void Item_func_in::print(String *str) str->append('('); args[0]->print(str); if (negated) - str->append(" not", 4); - str->append(" in (", 5); + str->append(STRING_WITH_LEN(" not")); + str->append(STRING_WITH_LEN(" in (")); print_args(str, 1); - str->append("))", 2); + str->append(STRING_WITH_LEN("))")); } @@ -2666,7 +2676,7 @@ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array, List_iterator<Item> li(list); Item *item; while ((item= li++)) - item->split_sum_func2(thd, ref_pointer_array, fields, li.ref()); + item->split_sum_func2(thd, ref_pointer_array, fields, li.ref(), TRUE); } @@ -2889,7 +2899,7 @@ void Item_func_isnotnull::print(String *str) { str->append('('); args[0]->print(str); - str->append(" is not null)", 13); + str->append(STRING_WITH_LEN(" is not null)")); } @@ -3657,7 +3667,7 @@ void Item_equal::merge(Item_equal *item) the multiple equality already contains a constant and its value is not equal to the value of c. */ - add(const_item); + add(c); } cond_false|= item->cond_false; } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index bfd32223d4c..b4064fb45b8 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -723,9 +723,9 @@ public: { char buff[STRING_BUFFER_USUAL_SIZE]; String tmp(buff, sizeof(buff), cmp_charset), *res; - if (!(res= arg->val_str(&tmp))) - return 1; /* Can't be right */ - return sortcmp(value_res, res, cmp_charset); + res= arg->val_str(&tmp); + return (value_res ? (res ? sortcmp(value_res, res, cmp_charset) : 1) : + (res ? -1 : 0)); } int compare(cmp_item *c) { diff --git a/sql/item_func.cc b/sql/item_func.cc index 92d57d826a5..272e77a4318 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -280,7 +280,7 @@ void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array, { Item **arg, **arg_end; for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++) - (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg); + (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE); } @@ -735,7 +735,7 @@ longlong Item_func_numhybrid::val_int() case INT_RESULT: return int_op(); case REAL_RESULT: - return (longlong)real_op(); + return (longlong) rint(real_op()); case STRING_RESULT: { int err_not_used; @@ -794,9 +794,9 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value) void Item_func_signed::print(String *str) { - str->append("cast(", 5); + str->append(STRING_WITH_LEN("cast(")); args[0]->print(str); - str->append(" as signed)", 11); + str->append(STRING_WITH_LEN(" as signed)")); } @@ -855,9 +855,9 @@ longlong Item_func_signed::val_int() void Item_func_unsigned::print(String *str) { - str->append("cast(", 5); + str->append(STRING_WITH_LEN("cast(")); args[0]->print(str); - str->append(" as unsigned)", 13); + str->append(STRING_WITH_LEN(" as unsigned)")); } @@ -927,9 +927,9 @@ my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec) void Item_decimal_typecast::print(String *str) { - str->append("cast(", 5); + str->append(STRING_WITH_LEN("cast(")); args[0]->print(str); - str->append(" as decimal)", 12); + str->append(STRING_WITH_LEN(" as decimal)")); } @@ -972,8 +972,8 @@ my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value) return 0; val2= args[1]->val_decimal(&value2); if (!(null_value= (args[1]->null_value || - my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1, - val2) > 1))) + (my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1, + val2) > 3)))) return decimal_value; return 0; } @@ -1045,8 +1045,8 @@ my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value) return 0; val2= args[1]->val_decimal(&value2); if (!(null_value= (args[1]->null_value || - my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1, - val2) > 1))) + (my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1, + val2) > 3)))) return decimal_value; return 0; } @@ -1083,8 +1083,8 @@ my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value) return 0; val2= args[1]->val_decimal(&value2); if (!(null_value= (args[1]->null_value || - my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1, - val2) > 1))) + (my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1, + val2) > 3)))) return decimal_value; return 0; } @@ -1124,6 +1124,7 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value) { my_decimal value1, *val1; my_decimal value2, *val2; + int err; val1= args[0]->val_decimal(&value1); if ((null_value= args[0]->null_value)) @@ -1131,17 +1132,15 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value) val2= args[1]->val_decimal(&value2); if ((null_value= args[1]->null_value)) return 0; - switch (my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value, - val1, val2, prec_increment)) { - case E_DEC_TRUNCATED: - case E_DEC_OK: - return decimal_value; - case E_DEC_DIV_ZERO: - signal_divide_by_null(); - default: - null_value= 1; // Safety + if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value, + val1, val2, prec_increment)) > 3) + { + if (err == E_DEC_DIV_ZERO) + signal_divide_by_null(); + null_value= 1; return 0; } + return decimal_value; } @@ -1386,9 +1385,9 @@ double Item_func_ln::val_real() { DBUG_ASSERT(fixed == 1); double value= args[0]->val_real(); - if ((null_value=args[0]->null_value)) + if ((null_value= args[0]->null_value)) return 0.0; - if ((null_value= value <=0.0)) + if (value <= 0.0) { signal_divide_by_null(); return 0.0; @@ -1405,9 +1404,9 @@ double Item_func_log::val_real() { DBUG_ASSERT(fixed == 1); double value= args[0]->val_real(); - if ((null_value=args[0]->null_value)) + if ((null_value= args[0]->null_value)) return 0.0; - if ((null_value= value <=0.0)) + if (value <= 0.0) { signal_divide_by_null(); return 0.0; @@ -1415,9 +1414,9 @@ double Item_func_log::val_real() if (arg_count == 2) { double value2= args[1]->val_real(); - if ((null_value=args[1]->null_value)) + if ((null_value= args[1]->null_value)) return 0.0; - if ((null_value= value2 <=0.0) || (value == 1.0)) + if (value2 <= 0.0 || value == 1.0) { signal_divide_by_null(); return 0.0; @@ -1434,7 +1433,7 @@ double Item_func_log2::val_real() if ((null_value=args[0]->null_value)) return 0.0; - if ((null_value= value <=0.0)) + if (value <= 0.0) { signal_divide_by_null(); return 0.0; @@ -1446,9 +1445,9 @@ double Item_func_log10::val_real() { DBUG_ASSERT(fixed == 1); double value= args[0]->val_real(); - if ((null_value=args[0]->null_value)) + if ((null_value= args[0]->null_value)) return 0.0; - if ((null_value= value <=0.0)) + if (value <= 0.0) { signal_divide_by_null(); return 0.0; @@ -2235,7 +2234,7 @@ longlong Item_func_locate::val_int() void Item_func_locate::print(String *str) { - str->append("locate(", 7); + str->append(STRING_WITH_LEN("locate(")); args[1]->print(str); str->append(','); args[0]->print(str); @@ -3298,7 +3297,7 @@ longlong Item_func_benchmark::val_int() void Item_func_benchmark::print(String *str) { - str->append("benchmark(", 10); + str->append(STRING_WITH_LEN("benchmark(")); char buffer[20]; // my_charset_bin is good enough for numbers String st(buffer, sizeof(buffer), &my_charset_bin); @@ -3812,9 +3811,9 @@ my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val) void Item_func_set_user_var::print(String *str) { - str->append("(@", 2); + str->append(STRING_WITH_LEN("(@")); str->append(name.str, name.length); - str->append(":=", 2); + str->append(STRING_WITH_LEN(":=")); args[0]->print(str); str->append(')'); } @@ -3822,9 +3821,9 @@ void Item_func_set_user_var::print(String *str) void Item_func_set_user_var::print_as_stmt(String *str) { - str->append("set @", 5); + str->append(STRING_WITH_LEN("set @")); str->append(name.str, name.length); - str->append(":=", 2); + str->append(STRING_WITH_LEN(":=")); args[0]->print(str); str->append(')'); } @@ -4055,7 +4054,7 @@ enum Item_result Item_func_get_user_var::result_type() const void Item_func_get_user_var::print(String *str) { - str->append("(@", 2); + str->append(STRING_WITH_LEN("(@")); str->append(name.str,name.length); str->append(')'); } @@ -4480,15 +4479,15 @@ double Item_func_match::val_real() void Item_func_match::print(String *str) { - str->append("(match ", 7); + str->append(STRING_WITH_LEN("(match ")); print_args(str, 1); - str->append(" against (", 10); + str->append(STRING_WITH_LEN(" against (")); args[0]->print(str); if (flags & FT_BOOL) - str->append(" in boolean mode", 16); + str->append(STRING_WITH_LEN(" in boolean mode")); else if (flags & FT_EXPAND) - str->append(" with query expansion", 21); - str->append("))", 2); + str->append(STRING_WITH_LEN(" with query expansion")); + str->append(STRING_WITH_LEN("))")); } longlong Item_func_bit_xor::val_int() @@ -4691,10 +4690,16 @@ Item_func_sp::sp_result_field(void) const { Field *field; DBUG_ENTER("Item_func_sp::sp_result_field"); + DBUG_PRINT("info", ("sp: %s, flags: %x, level: %lu", + (m_sp ? "YES" : "NO"), + (m_sp ? m_sp->m_flags : (uint)0), + (m_sp ? m_sp->m_recursion_level : (ulong)0))); if (!m_sp) { - if (!(m_sp= sp_find_function(current_thd, m_name, TRUE))) + THD *thd= current_thd; + if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name, + &thd->sp_func_cache, TRUE))) { my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str); DBUG_RETURN(0); @@ -4711,7 +4716,7 @@ Item_func_sp::sp_result_field(void) const share->table_cache_key = empty_name; share->table_name = empty_name; } - field= m_sp->make_field(max_length, name, dummy_table); + field= m_sp->create_result_field(max_length, name, dummy_table); DBUG_RETURN(field); } @@ -4724,16 +4729,17 @@ Item_func_sp::sp_result_field(void) const 1 value = NULL or error */ -int +bool Item_func_sp::execute(Field **flp) { - Item *it; + THD *thd= current_thd; Field *f; - if (execute(&it)) - { - null_value= 1; - return 1; - } + + /* + Get field in virtual tmp table to store result. Create the field if + invoked first time. + */ + if (!(f= *flp)) { *flp= f= sp_result_field(); @@ -4742,21 +4748,41 @@ Item_func_sp::execute(Field **flp) f->null_ptr= (uchar *)&null_value; f->null_bit= 1; } - it->save_in_field(f, 1); - return null_value= f->is_null(); + + /* Execute function and store the return value in the field. */ + + if (execute_impl(thd, f)) + { + null_value= 1; + context->process_error(thd); + return TRUE; + } + + /* Check that the field (the value) is not NULL. */ + + null_value= f->is_null(); + + return null_value; } -int -Item_func_sp::execute(Item **itp) +bool +Item_func_sp::execute_impl(THD *thd, Field *return_value_fld) { - DBUG_ENTER("Item_func_sp::execute"); - THD *thd= current_thd; - int res= -1; + bool err_status= TRUE; Sub_statement_state statement_state; - Security_context *save_ctx; + Security_context *save_security_ctx= thd->security_ctx, *save_ctx_func; + + DBUG_ENTER("Item_func_sp::execute_impl"); - if (find_and_check_access(thd, EXECUTE_ACL, &save_ctx)) +#ifndef NO_EMBEDDED_ACCESS_CHECKS + if (context->security_ctx) + { + /* Set view definer security context */ + thd->security_ctx= context->security_ctx; + } +#endif + if (find_and_check_access(thd, EXECUTE_ACL, &save_ctx_func)) goto error; /* @@ -4765,19 +4791,17 @@ Item_func_sp::execute(Item **itp) function call into binlog. */ thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION); - res= m_sp->execute_function(thd, args, arg_count, itp); + err_status= m_sp->execute_function(thd, args, arg_count, return_value_fld); thd->restore_sub_statement_state(&statement_state); - if (res && mysql_bin_log.is_open() && - (m_sp->m_chistics->daccess == SP_CONTAINS_SQL || - m_sp->m_chistics->daccess == SP_MODIFIES_SQL_DATA)) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_FAILED_ROUTINE_BREAK_BINLOG, - ER(ER_FAILED_ROUTINE_BREAK_BINLOG)); - - sp_restore_security_context(thd, save_ctx); +#ifndef NO_EMBEDDED_ACCESS_CHECKS + sp_restore_security_context(thd, save_ctx_func); error: - DBUG_RETURN(res); + thd->security_ctx= save_security_ctx; +#else +error: +#endif + DBUG_RETURN(err_status); } @@ -4873,7 +4897,7 @@ Item_func_sp::tmp_table_field(TABLE *t_arg) DBUG_ENTER("Item_func_sp::tmp_table_field"); if (m_sp) - res= m_sp->make_field(max_length, (const char *)name, t_arg); + res= m_sp->create_result_field(max_length, (const char*) name, t_arg); if (!res) res= Item_func::tmp_table_field(t_arg); @@ -4883,7 +4907,7 @@ Item_func_sp::tmp_table_field(TABLE *t_arg) /* - Find the function and chack access rigths to the function + Find the function and check access rights to the function SYNOPSIS find_and_check_access() @@ -4914,7 +4938,8 @@ Item_func_sp::find_and_check_access(THD *thd, ulong want_access, bool res= TRUE; *save= 0; // Safety if error - if (! m_sp && ! (m_sp= sp_find_function(thd, m_name, TRUE))) + if (! m_sp && ! (m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name, + &thd->sp_func_cache, TRUE))) { my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str); goto error; @@ -4957,8 +4982,20 @@ Item_func_sp::fix_fields(THD *thd, Item **ref) bool res; DBUG_ASSERT(fixed == 0); res= Item_func::fix_fields(thd, ref); - if (!res) + if (!res && thd->lex->view_prepare_mode) { + /* + Here we check privileges of the stored routine only during view + creation, in order to validate the view. A runtime check is perfomed + in Item_func_sp::execute(), and this method is not called during + context analysis. We do not need to restore the security context + changed in find_and_check_access because all view structures created + in CREATE VIEW are not used for execution. Notice, that during view + creation we do not infer into stored routine bodies and do not check + privileges of its statements, which would probably be a good idea + especially if the view has SQL SECURITY DEFINER and the used stored + procedure has SQL SECURITY DEFINER + */ Security_context *save_ctx; if (!(res= find_and_check_access(thd, EXECUTE_ACL, &save_ctx))) sp_restore_security_context(thd, save_ctx); diff --git a/sql/item_func.h b/sql/item_func.h index 223144a5d51..d81eb5f6ebf 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -199,7 +199,7 @@ public: String *val_str(String*str); my_decimal *val_decimal(my_decimal *decimal_value); longlong val_int() - { DBUG_ASSERT(fixed == 1); return (longlong) val_real(); } + { DBUG_ASSERT(fixed == 1); return (longlong) rint(val_real()); } enum Item_result result_type () const { return REAL_RESULT; } void fix_length_and_dec() { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } @@ -943,7 +943,7 @@ class Item_func_udf_float :public Item_udf_func longlong val_int() { DBUG_ASSERT(fixed == 1); - return (longlong) Item_func_udf_float::val_real(); + return (longlong) rint(Item_func_udf_float::val_real()); } my_decimal *val_decimal(my_decimal *dec_buf) { @@ -1129,7 +1129,6 @@ class user_var_entry; class Item_func_set_user_var :public Item_func { enum Item_result cached_result_type; - LEX_STRING name; user_var_entry *entry; char buffer[MAX_FIELD_WIDTH]; String value; @@ -1146,6 +1145,7 @@ class Item_func_set_user_var :public Item_func public: + LEX_STRING name; // keep it public Item_func_set_user_var(LEX_STRING a,Item *b) :Item_func(b), cached_result_type(INT_RESULT), name(a) {} @@ -1168,10 +1168,10 @@ public: class Item_func_get_user_var :public Item_func { - LEX_STRING name; user_var_entry *var_entry; public: + LEX_STRING name; // keep it public Item_func_get_user_var(LEX_STRING a): Item_func(), name(a) {} enum Functype functype() const { return GUSERVAR_FUNC; } @@ -1374,8 +1374,8 @@ private: Field *result_field; char result_buf[64]; - int execute(Item **itp); - int execute(Field **flp); + bool execute(Field **flp); + bool execute_impl(THD *thd, Field *return_value_fld); Field *sp_result_field(void) const; public: diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 4a6ceb4bf7d..2b92e72e728 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -81,8 +81,7 @@ String *Item_func_geometry_from_wkb::val_str(String *str) str->q_append(srid); if ((null_value= (args[0]->null_value || - !Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length()) || - str->append(*wkb)))) + !Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length(), str)))) return 0; return str; } @@ -99,8 +98,7 @@ String *Item_func_as_wkt::val_str(String *str) if ((null_value= (args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE))))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))) return 0; str->length(0); @@ -126,8 +124,7 @@ String *Item_func_as_wkb::val_str(String *str) if ((null_value= (args[0]->null_value || - !(Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE))))) + !(Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))) return 0; str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE, @@ -145,8 +142,7 @@ String *Item_func_geometry_type::val_str(String *str) if ((null_value= (args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE))))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))) return 0; /* String will not move */ str->copy(geom->get_class_info()->m_name.str, @@ -167,8 +163,7 @@ String *Item_func_envelope::val_str(String *str) if ((null_value= args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))) return 0; srid= uint4korr(swkb->ptr()); @@ -191,8 +186,7 @@ String *Item_func_centroid::val_str(String *str) uint32 srid; if ((null_value= args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))) return 0; str->set_charset(&my_charset_bin); @@ -221,8 +215,7 @@ String *Item_func_spatial_decomp::val_str(String *str) if ((null_value= (args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE))))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))) return 0; srid= uint4korr(swkb->ptr()); @@ -270,8 +263,7 @@ String *Item_func_spatial_decomp_n::val_str(String *str) if ((null_value= (args[0]->null_value || args[1]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE))))) + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))) return 0; str->set_charset(&my_charset_bin); @@ -478,10 +470,8 @@ longlong Item_func_spatial_rel::val_int() if ((null_value= (args[0]->null_value || args[1]->null_value || - !(g1= Geometry::create_from_wkb(&buffer1, res1->ptr() + SRID_SIZE, - res1->length() - SRID_SIZE)) || - !(g2= Geometry::create_from_wkb(&buffer2, res2->ptr() + SRID_SIZE, - res2->length() - SRID_SIZE)) || + !(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) || + !(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) || g1->get_mbr(&mbr1, &dummy) || g2->get_mbr(&mbr2, &dummy)))) return 0; @@ -546,8 +536,7 @@ longlong Item_func_isclosed::val_int() null_value= (!swkb || args[0]->null_value || !(geom= - Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + Geometry::construct(&buffer, swkb->ptr(), swkb->length())) || geom->is_closed(&isclosed)); return (longlong) isclosed; @@ -569,9 +558,7 @@ longlong Item_func_dimension::val_int() null_value= (!swkb || args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) || geom->dimension(&dim, &dummy)); return (longlong) dim; } @@ -586,9 +573,8 @@ longlong Item_func_numinteriorring::val_int() Geometry *geom; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->num_interior_ring(&num)); return (longlong) num; } @@ -603,9 +589,8 @@ longlong Item_func_numgeometries::val_int() Geometry *geom; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->num_geometries(&num)); return (longlong) num; } @@ -621,9 +606,8 @@ longlong Item_func_numpoints::val_int() null_value= (!swkb || args[0]->null_value || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->num_points(&num)); return (longlong) num; } @@ -638,9 +622,8 @@ double Item_func_x::val_real() Geometry *geom; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->get_x(&res)); return res; } @@ -655,9 +638,8 @@ double Item_func_y::val_real() Geometry *geom; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->get_y(&res)); return res; } @@ -673,9 +655,8 @@ double Item_func_area::val_real() const char *dummy; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->area(&res, &dummy)); return res; } @@ -689,9 +670,8 @@ double Item_func_glength::val_real() Geometry *geom; null_value= (!swkb || - !(geom= Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)) || + !(geom= Geometry::construct(&buffer, + swkb->ptr(), swkb->length())) || geom->length(&res)); return res; } @@ -703,9 +683,8 @@ longlong Item_func_srid::val_int() Geometry_buffer buffer; null_value= (!swkb || - !Geometry::create_from_wkb(&buffer, - swkb->ptr() + SRID_SIZE, - swkb->length() - SRID_SIZE)); + !Geometry::construct(&buffer, + swkb->ptr(), swkb->length())); if (null_value) return 0; diff --git a/sql/item_row.cc b/sql/item_row.cc index 9362518e6ef..75c3f8a2922 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -90,7 +90,7 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array, { Item **arg, **arg_end; for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++) - (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg); + (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1e8fe2e695f..8056e00e0cf 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -48,6 +48,38 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, } +String *Item_str_func::check_well_formed_result(String *str) +{ + /* Check whether we got a well-formed string */ + CHARSET_INFO *cs= str->charset(); + int well_formed_error; + uint wlen= cs->cset->well_formed_len(cs, + str->ptr(), str->ptr() + str->length(), + str->length(), &well_formed_error); + if (wlen < str->length()) + { + THD *thd= current_thd; + char hexbuf[7]; + enum MYSQL_ERROR::enum_warning_level level; + uint diff= str->length() - wlen; + set_if_smaller(diff, 3); + octet2hex(hexbuf, str->ptr() + wlen, diff); + if (thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)) + { + level= MYSQL_ERROR::WARN_LEVEL_ERROR; + null_value= 1; + str= 0; + } + else + level= MYSQL_ERROR::WARN_LEVEL_WARN; + push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING, + ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); + } + return str; +} + + double Item_str_func::val_real() { DBUG_ASSERT(fixed == 1); @@ -1790,7 +1822,7 @@ String *Item_func_format::val_str(String *str) void Item_func_format::print(String *str) { - str->append("format(", 7); + str->append(STRING_WITH_LEN("format(")); args[0]->print(str); str->append(','); // my_charset_bin is good enough for numbers @@ -1864,7 +1896,7 @@ String *Item_func_elt::val_str(String *str) void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields) { - item->split_sum_func2(thd, ref_pointer_array, fields, &item); + item->split_sum_func2(thd, ref_pointer_array, fields, &item, TRUE); Item_str_func::split_sum_func(thd, ref_pointer_array, fields); } @@ -1950,7 +1982,7 @@ String *Item_func_make_set::val_str(String *str) void Item_func_make_set::print(String *str) { - str->append("make_set(", 9); + str->append(STRING_WITH_LEN("make_set(")); item->print(str); if (arg_count) { @@ -1984,34 +2016,7 @@ String *Item_func_char::val_str(String *str) } str->set_charset(collation.collation); str->realloc(str->length()); // Add end 0 (for Purify) - - /* Check whether we got a well-formed string */ - CHARSET_INFO *cs= collation.collation; - int well_formed_error; - uint wlen= cs->cset->well_formed_len(cs, - str->ptr(), str->ptr() + str->length(), - str->length(), &well_formed_error); - if (wlen < str->length()) - { - THD *thd= current_thd; - char hexbuf[7]; - enum MYSQL_ERROR::enum_warning_level level; - uint diff= str->length() - wlen; - set_if_smaller(diff, 3); - octet2hex(hexbuf, str->ptr() + wlen, diff); - if (thd->variables.sql_mode & - (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)) - { - level= MYSQL_ERROR::WARN_LEVEL_ERROR; - null_value= 1; - str= 0; - } - else - level= MYSQL_ERROR::WARN_LEVEL_WARN; - push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING, - ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); - } - return str; + return check_well_formed_result(str); } @@ -2311,6 +2316,8 @@ String *Item_func_conv::val_str(String *str) String *Item_func_conv_charset::val_str(String *str) { DBUG_ASSERT(fixed == 1); + if (use_cached_value) + return null_value ? 0 : &str_value; String *arg= args[0]->val_str(str); uint dummy_errors; if (!arg) @@ -2320,7 +2327,7 @@ String *Item_func_conv_charset::val_str(String *str) } null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(), conv_charset, &dummy_errors); - return null_value ? 0 : &str_value; + return null_value ? 0 : check_well_formed_result(&str_value); } void Item_func_conv_charset::fix_length_and_dec() @@ -2331,9 +2338,9 @@ void Item_func_conv_charset::fix_length_and_dec() void Item_func_conv_charset::print(String *str) { - str->append("convert(", 8); + str->append(STRING_WITH_LEN("convert(")); args[0]->print(str); - str->append(" using ", 7); + str->append(STRING_WITH_LEN(" using ")); str->append(conv_charset->csname); str->append(')'); } @@ -2403,7 +2410,7 @@ void Item_func_set_collation::print(String *str) { str->append('('); args[0]->print(str); - str->append(" collate ", 9); + str->append(STRING_WITH_LEN(" collate ")); DBUG_ASSERT(args[1]->basic_const_item() && args[1]->type() == Item::STRING_ITEM); args[1]->str_value.print(str); @@ -2523,9 +2530,9 @@ String *Item_func_unhex::val_str(String *str) void Item_func_binary::print(String *str) { - str->append("cast(", 5); + str->append(STRING_WITH_LEN("cast(")); args[0]->print(str); - str->append(" as binary)", 11); + str->append(STRING_WITH_LEN(" as binary)")); } @@ -2630,7 +2637,7 @@ String* Item_func_export_set::val_str(String* str) } break; case 3: - sep_buf.set(",", 1, default_charset()); + sep_buf.set(STRING_WITH_LEN(","), default_charset()); sep = &sep_buf; break; default: @@ -2745,7 +2752,8 @@ String *Item_func_quote::val_str(String *str) uint arg_length, new_length; if (!arg) // Null argument { - str->copy("NULL", 4, collation.collation); // Return the string 'NULL' + /* Return the string 'NULL' */ + str->copy(STRING_WITH_LEN("NULL"), collation.collation); null_value= 0; return str; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 5889821293d..50ec0b36ce8 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -35,6 +35,7 @@ public: double val_real(); enum Item_result result_type () const { return STRING_RESULT; } void left_right_max_length(); + String *check_well_formed_result(String *str); }; class Item_func_md5 :public Item_str_func @@ -651,10 +652,40 @@ public: class Item_func_conv_charset :public Item_str_func { - CHARSET_INFO *conv_charset; + bool use_cached_value; public: - Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a) - { conv_charset=cs; } + bool safe; + CHARSET_INFO *conv_charset; // keep it public + Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a) + { conv_charset= cs; use_cached_value= 0; safe= 0; } + Item_func_conv_charset(Item *a, CHARSET_INFO *cs, bool cache_if_const) + :Item_str_func(a) + { + DBUG_ASSERT(args[0]->fixed); + conv_charset= cs; + if (cache_if_const && args[0]->const_item()) + { + uint errors= 0; + String tmp, *str= args[0]->val_str(&tmp); + if (!str || str_value.copy(str->ptr(), str->length(), + str->charset(), conv_charset, &errors)) + null_value= 1; + use_cached_value= 1; + safe= (errors == 0); + } + else + { + use_cached_value= 0; + /* + Conversion from and to "binary" is safe. + Conversion to Unicode is safe. + Other kind of conversions are potentially lossy. + */ + safe= (args[0]->collation.collation == &my_charset_bin || + cs == &my_charset_bin || + (cs->state & MY_CS_UNICODE)); + } + } String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "convert"; } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 8afc885e59b..88620634354 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -533,7 +533,7 @@ Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex): void Item_exists_subselect::print(String *str) { - str->append("exists", 6); + str->append(STRING_WITH_LEN("exists")); Item_subselect::print(str); } @@ -803,6 +803,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, !(select_lex->next_select())) { Item_sum_hybrid *item; + nesting_map save_allow_sum_func; if (func->l_op()) { /* @@ -828,6 +829,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, it.replace(item); } + save_allow_sum_func= thd->lex->allow_sum_func; + thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; /* Item_sum_(max|min) can't substitute other item => we can use 0 as reference, also Item_sum_(max|min) can't be fixed after creation, so @@ -835,6 +838,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, */ if (item->fix_fields(thd, 0)) DBUG_RETURN(RES_ERROR); + thd->lex->allow_sum_func= save_allow_sum_func; /* we added aggregate function => we have to change statistic */ count_field_types(&join->tmp_table_param, join->all_fields, 0); @@ -1339,11 +1343,11 @@ err: void Item_in_subselect::print(String *str) { if (transformed) - str->append("<exists>", 8); + str->append(STRING_WITH_LEN("<exists>")); else { left_expr->print(str); - str->append(" in ", 4); + str->append(STRING_WITH_LEN(" in ")); } Item_subselect::print(str); } @@ -1362,7 +1366,7 @@ Item_allany_subselect::select_transformer(JOIN *join) void Item_allany_subselect::print(String *str) { if (transformed) - str->append("<exists>", 8); + str->append(STRING_WITH_LEN("<exists>")); else { left_expr->print(str); @@ -1794,16 +1798,16 @@ void subselect_union_engine::print(String *str) void subselect_uniquesubquery_engine::print(String *str) { - str->append("<primary_index_lookup>(", 23); + str->append(STRING_WITH_LEN("<primary_index_lookup>(")); tab->ref.items[0]->print(str); - str->append(" in ", 4); + str->append(STRING_WITH_LEN(" in ")); str->append(tab->table->s->table_name); KEY *key_info= tab->table->key_info+ tab->ref.key; - str->append(" on ", 4); + str->append(STRING_WITH_LEN(" on ")); str->append(key_info->name); if (cond) { - str->append(" where ", 7); + str->append(STRING_WITH_LEN(" where ")); cond->print(str); } str->append(')'); @@ -1812,18 +1816,18 @@ void subselect_uniquesubquery_engine::print(String *str) void subselect_indexsubquery_engine::print(String *str) { - str->append("<index_lookup>(", 15); + str->append(STRING_WITH_LEN("<index_lookup>(")); tab->ref.items[0]->print(str); - str->append(" in ", 4); + str->append(STRING_WITH_LEN(" in ")); str->append(tab->table->s->table_name); KEY *key_info= tab->table->key_info+ tab->ref.key; - str->append(" on ", 4); + str->append(STRING_WITH_LEN(" on ")); str->append(key_info->name); if (check_null) - str->append(" checking NULL", 14); + str->append(STRING_WITH_LEN(" checking NULL")); if (cond) { - str->append(" where ", 7); + str->append(STRING_WITH_LEN(" where ")); cond->print(str); } str->append(')'); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index b56d99cf245..a3a25ec8d6f 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -24,6 +24,234 @@ #include "mysql_priv.h" #include "sql_select.h" +/* + Prepare an aggregate function item for checking context conditions + + SYNOPSIS + init_sum_func_check() + thd reference to the thread context info + + DESCRIPTION + The function initializes the members of the Item_sum object created + for a set function that are used to check validity of the set function + occurrence. + If the set function is not allowed in any subquery where it occurs + an error is reported immediately. + + NOTES + This function is to be called for any item created for a set function + object when the traversal of trees built for expressions used in the query + is performed at the phase of context analysis. This function is to + be invoked at the descent of this traversal. + + RETURN + TRUE if an error is reported + FALSE otherwise +*/ + +bool Item_sum::init_sum_func_check(THD *thd) +{ + if (!thd->lex->allow_sum_func) + { + my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE), + MYF(0)); + return TRUE; + } + /* Set a reference to the nesting set function if there is any */ + in_sum_func= thd->lex->in_sum_func; + /* Save a pointer to object to be used in items for nested set functions */ + thd->lex->in_sum_func= this; + nest_level= thd->lex->current_select->nest_level; + ref_by= 0; + aggr_level= -1; + max_arg_level= -1; + max_sum_func_level= -1; + return FALSE; +} + +/* + Check constraints imposed on a usage of a set function + + SYNOPSIS + check_sum_func() + thd reference to the thread context info + ref location of the pointer to this item in the embedding expression + + DESCRIPTION + The method verifies whether context conditions imposed on a usage + of any set function are met for this occurrence. + It checks whether the set function occurs in the position where it + can be aggregated and, when it happens to occur in argument of another + set function, the method checks that these two functions are aggregated in + different subqueries. + If the context conditions are not met the method reports an error. + If the set function is aggregated in some outer subquery the method + adds it to the chain of items for such set functions that is attached + to the the st_select_lex structure for this subquery. + + NOTES + This function is to be called for any item created for a set function + object when the traversal of trees built for expressions used in the query + is performed at the phase of context analysis. This function is to + be invoked at the ascent of this traversal. + + IMPLEMENTATION + A number of designated members of the object are used to check the + conditions. They are specified in the comment before the Item_sum + class declaration. + Additionally a bitmap variable called allow_sum_func is employed. + It is included into the thd->lex structure. + The bitmap contains 1 at n-th position if the set function happens + to occur under a construct of the n-th level subquery where usage + of set functions are allowed (i.e either in the SELECT list or + in the HAVING clause of the corresponding subquery) + Consider the query: + SELECT SUM(t1.b) FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 WHERE AVG(t1.b) > 20) AND + t1.a > (SELECT MIN(t2.d) FROM t2); + allow_sum_func will contain: + for SUM(t1.b) - 1 at the first position + for AVG(t1.b) - 1 at the first position, 0 at the second position + for MIN(t2.d) - 1 at the first position, 1 at the second position. + + RETURN + TRUE if an error is reported + FALSE otherwise +*/ + +bool Item_sum::check_sum_func(THD *thd, Item **ref) +{ + bool invalid= FALSE; + nesting_map allow_sum_func= thd->lex->allow_sum_func; + /* + The value of max_arg_level is updated if an argument of the set function + contains a column reference resolved against a subquery whose level is + greater than the current value of max_arg_level. + max_arg_level cannot be greater than nest level. + nest level is always >= 0 + */ + if (nest_level == max_arg_level) + { + /* + The function must be aggregated in the current subquery, + If it is there under a construct where it is not allowed + we report an error. + */ + invalid= !(allow_sum_func & (1 << max_arg_level)); + } + else if (max_arg_level >= 0 || !(allow_sum_func & (1 << nest_level))) + { + /* + The set function can be aggregated only in outer subqueries. + Try to find a subquery where it can be aggregated; + If we fail to find such a subquery report an error. + */ + if (register_sum_func(thd, ref)) + return TRUE; + invalid= aggr_level < 0 && !(allow_sum_func & (1 << nest_level)); + } + if (!invalid && aggr_level < 0) + aggr_level= nest_level; + /* + By this moment we either found a subquery where the set function is + to be aggregated and assigned a value that is >= 0 to aggr_level, + or set the value of 'invalid' to TRUE to report later an error. + */ + /* + Additionally we have to check whether possible nested set functions + are acceptable here: they are not, if the level of aggregation of + some of them is less than aggr_level. + */ + invalid= aggr_level <= max_sum_func_level; + if (invalid) + { + my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE), + MYF(0)); + return TRUE; + } + if (in_sum_func && in_sum_func->nest_level == nest_level) + { + /* + If the set function is nested adjust the value of + max_sum_func_level for the nesting set function. + */ + set_if_bigger(in_sum_func->max_sum_func_level, aggr_level); + } + thd->lex->in_sum_func= in_sum_func; + return FALSE; +} + +/* + Attach a set function to the subquery where it must be aggregated + + SYNOPSIS + register_sum_func() + thd reference to the thread context info + ref location of the pointer to this item in the embedding expression + + DESCRIPTION + The function looks for an outer subquery where the set function must be + aggregated. If it finds such a subquery then aggr_level is set to + the nest level of this subquery and the item for the set function + is added to the list of set functions used in nested subqueries + inner_sum_func_list defined for each subquery. When the item is placed + there the field 'ref_by' is set to ref. + + NOTES. + Now we 'register' only set functions that are aggregated in outer + subqueries. Actually it makes sense to link all set function for + a subquery in one chain. It would simplify the process of 'splitting' + for set functions. + + RETURN + FALSE if the executes without failures (currently always) + TRUE otherwise +*/ + +bool Item_sum::register_sum_func(THD *thd, Item **ref) +{ + SELECT_LEX *sl; + SELECT_LEX *aggr_sl= NULL; + nesting_map allow_sum_func= thd->lex->allow_sum_func; + for (sl= thd->lex->current_select->master_unit()->outer_select() ; + sl && sl->nest_level > max_arg_level; + sl= sl->master_unit()->outer_select() ) + { + if (aggr_level < 0 && (allow_sum_func & (1 << sl->nest_level))) + { + /* Found the most nested subquery where the function can be aggregated */ + aggr_level= sl->nest_level; + aggr_sl= sl; + } + } + if (sl && (allow_sum_func & (1 << sl->nest_level))) + { + /* + We reached the subquery of level max_arg_level and checked + that the function can be aggregated here. + The set function will be aggregated in this subquery. + */ + aggr_level= sl->nest_level; + aggr_sl= sl; + } + if (aggr_level >= 0) + { + ref_by= ref; + /* Add the object to the list of registered objects assigned to aggr_sl */ + if (!aggr_sl->inner_sum_func_list) + next= this; + else + { + next= aggr_sl->inner_sum_func_list->next; + aggr_sl->inner_sum_func_list->next= this; + } + aggr_sl->inner_sum_func_list= this; + + } + return FALSE; +} + + Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements) { @@ -197,13 +425,9 @@ Item_sum_num::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); - if (!thd->allow_sum_func) - { - my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE), - MYF(0)); + if (init_sum_func_check(thd)) return TRUE; - } - thd->allow_sum_func=0; // No included group funcs + decimals=0; maybe_null=0; for (uint i=0 ; i < arg_count ; i++) @@ -217,7 +441,10 @@ Item_sum_num::fix_fields(THD *thd, Item **ref) max_length=float_length(decimals); null_value=1; fix_length_and_dec(); - thd->allow_sum_func=1; // Allow group functions + + if (check_sum_func(thd, ref)) + return TRUE; + fixed= 1; return FALSE; } @@ -258,13 +485,9 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) DBUG_ASSERT(fixed == 0); Item *item= args[0]; - if (!thd->allow_sum_func) - { - my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE), - MYF(0)); + + if (init_sum_func_check(thd)) return TRUE; - } - thd->allow_sum_func=0; // No included group funcs // 'item' can be changed during fix_fields if (!item->fixed && @@ -300,11 +523,14 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) result_field=0; null_value=1; fix_length_and_dec(); - thd->allow_sum_func=1; // Allow group functions if (item->type() == Item::FIELD_ITEM) hybrid_field_type= ((Item_field*) item)->field->type(); else hybrid_field_type= Item::field_type(); + + if (check_sum_func(thd, ref)) + return TRUE; + fixed= 1; return FALSE; } @@ -452,7 +678,7 @@ longlong Item_sum_sum::val_int() &result); return result; } - return (longlong) val_real(); + return (longlong) rint(val_real()); } @@ -1285,7 +1511,7 @@ longlong Item_sum_hybrid::val_int() return sum_int; } default: - return (longlong) Item_sum_hybrid::val_real(); + return (longlong) rint(Item_sum_hybrid::val_real()); } } @@ -2001,7 +2227,7 @@ double Item_avg_field::val_real() longlong Item_avg_field::val_int() { - return (longlong) val_real(); + return (longlong) rint(val_real()); } @@ -2979,14 +3205,9 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) uint i; /* for loop variable */ DBUG_ASSERT(fixed == 0); - if (!thd->allow_sum_func) - { - my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE), - MYF(0)); + if (init_sum_func_check(thd)) return TRUE; - } - thd->allow_sum_func= 0; maybe_null= 1; /* @@ -3008,8 +3229,11 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) result.set_charset(collation.collation); result_field= 0; null_value= 1; - thd->allow_sum_func= 1; max_length= thd->variables.group_concat_max_len; + + if (check_sum_func(thd, ref)) + return TRUE; + fixed= 1; return FALSE; } @@ -3156,9 +3380,9 @@ String* Item_func_group_concat::val_str(String* str) void Item_func_group_concat::print(String *str) { - str->append("group_concat(", 13); + str->append(STRING_WITH_LEN("group_concat(")); if (distinct) - str->append("distinct ", 9); + str->append(STRING_WITH_LEN("distinct ")); for (uint i= 0; i < arg_count_field; i++) { if (i) @@ -3167,15 +3391,19 @@ void Item_func_group_concat::print(String *str) } if (arg_count_order) { - str->append(" order by ", 10); + str->append(STRING_WITH_LEN(" order by ")); for (uint i= 0 ; i < arg_count_order ; i++) { if (i) str->append(','); (*order[i]->item)->print(str); + if (order[i]->asc) + str->append(STRING_WITH_LEN(" ASC")); + else + str->append(STRING_WITH_LEN(" DESC")); } } - str->append(" separator \'", 12); + str->append(STRING_WITH_LEN(" separator \'")); str->append(*separator); - str->append("\')", 2); + str->append(STRING_WITH_LEN("\')")); } diff --git a/sql/item_sum.h b/sql/item_sum.h index 87cc248e5e4..a8242d76287 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -23,6 +23,201 @@ #include <my_tree.h> +/* + Class Item_sum is the base class used for special expressions that SQL calls + 'set functions'. These expressions are formed with the help of aggregate + functions such as SUM, MAX, GROUP_CONCAT etc. + + GENERAL NOTES + + A set function cannot be used in certain positions where expressions are + accepted. There are some quite explicable restrictions for the usage of + set functions. + + In the query: + SELECT AVG(b) FROM t1 WHERE SUM(b) > 20 GROUP by a + the usage of the set function AVG(b) is legal, while the usage of SUM(b) + is illegal. A WHERE condition must contain expressions that can be + evaluated for each row of the table. Yet the expression SUM(b) can be + evaluated only for each group of rows with the same value of column a. + In the query: + SELECT AVG(b) FROM t1 WHERE c > 30 GROUP BY a HAVING SUM(b) > 20 + both set function expressions AVG(b) and SUM(b) are legal. + + We can say that in a query without nested selects an occurrence of a + set function in an expression of the SELECT list or/and in the HAVING + clause is legal, while in the WHERE clause it's illegal. + + The general rule to detect whether a set function is legal in a query with + nested subqueries is much more complicated. + + Consider the the following query: + SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL (SELECT t2.c FROM t2 WHERE SUM(t1.b) < t2.c). + The set function SUM(b) is used here in the WHERE clause of the subquery. + Nevertheless it is legal since it is under the HAVING clause of the query + to which this function relates. The expression SUM(t1.b) is evaluated + for each group defined in the main query, not for groups of the subquery. + + The problem of finding the query where to aggregate a particular + set function is not so simple as it seems to be. + + In the query: + SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.c FROM t2 GROUP BY t2.c + HAVING SUM(t1.a) < t2.c) + the set function can be evaluated for both outer and inner selects. + If we evaluate SUM(t1.a) for the outer query then we get the value of t1.a + multiplied by the cardinality of a group in table t1. In this case + in each correlated subquery SUM(t1.a) is used as a constant. But we also + can evaluate SUM(t1.a) for the inner query. In this case t1.a will be a + constant for each correlated subquery and summation is performed + for each group of table t2. + (Here it makes sense to remind that the query + SELECT c FROM t GROUP BY a HAVING SUM(1) < a + is quite legal in our SQL). + + So depending on what query we assign the set function to we + can get different result sets. + + The general rule to detect the query where a set function is to be + evaluated can be formulated as follows. + Consider a set function S(E) where E is an expression with occurrences + of column references C1, ..., CN. Resolve these column references against + subqueries that contain the set function S(E). Let Q be the innermost + subquery of those subqueries. (It should be noted here that S(E) + in no way can be evaluated in the subquery embedding the subquery Q, + otherwise S(E) would refer to at least one unbound column reference) + If S(E) is used in a construct of Q where set functions are allowed then + we evaluate S(E) in Q. + Otherwise we look for a innermost subquery containing S(E) of those where + usage of S(E) is allowed. + + Let's demonstrate how this rule is applied to the following queries. + + 1. SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.b FROM t2 GROUP BY t2.b + HAVING t2.b > ALL(SELECT t3.c FROM t3 GROUP BY t3.c + HAVING SUM(t1.a+t2.b) < t3.c)) + For this query the set function SUM(t1.a+t2.b) depends on t1.a and t2.b + with t1.a defined in the outermost query, and t2.b defined for its + subquery. The set function is in the HAVING clause of the subquery and can + be evaluated in this subquery. + + 2. SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.b FROM t2 + WHERE t2.b > ALL (SELECT t3.c FROM t3 GROUP BY t3.c + HAVING SUM(t1.a+t2.b) < t3.c)) + Here the set function SUM(t1.a+t2.b)is in the WHERE clause of the second + subquery - the most upper subquery where t1.a and t2.b are defined. + If we evaluate the function in this subquery we violate the context rules. + So we evaluate the function in the third subquery (over table t3) where it + is used under the HAVING clause. + + 3. SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.b FROM t2 + WHERE t2.b > ALL (SELECT t3.c FROM t3 + WHERE SUM(t1.a+t2.b) < t3.c)) + In this query evaluation of SUM(t1.a+t2.b) is not legal neither in the second + nor in the third subqueries. So this query is invalid. + + Mostly set functions cannot be nested. In the query + SELECT t1.a from t1 GROUP BY t1.a HAVING AVG(SUM(t1.b)) > 20 + the expression SUM(b) is not acceptable, though it is under a HAVING clause. + Yet it is acceptable in the query: + SELECT t.1 FROM t1 GROUP BY t1.a HAVING SUM(t1.b) > 20. + + An argument of a set function does not have to be a reference to a table + column as we saw it in examples above. This can be a more complex expression + SELECT t1.a FROM t1 GROUP BY t1.a HAVING SUM(t1.b+1) > 20. + The expression SUM(t1.b+1) has a very clear semantics in this context: + we sum up the values of t1.b+1 where t1.b varies for all values within a + group of rows that contain the same t1.a value. + + A set function for an outer query yields a constant within a subquery. So + the semantics of the query + SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c + HAVING AVG(t2.c+SUM(t1.b)) > 20) + is still clear. For a group of the rows with the same t1.a values we + calculate the value of SUM(t1.b). This value 's' is substituted in the + the subquery: + SELECT t2.c FROM t2 GROUP BY t2.c HAVING AVG(t2.c+s) + than returns some result set. + + By the same reason the following query with a subquery + SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c + HAVING AVG(SUM(t1.b)) > 20) + is also acceptable. + + IMPLEMENTATION NOTES + + Three methods were added to the class to check the constraints specified + in the previous section. These methods utilize several new members. + + The field 'nest_level' contains the number of the level for the subquery + containing the set function. The main SELECT is of level 0, its subqueries + are of levels 1, the subqueries of the latter are of level 2 and so on. + + The field 'aggr_level' is to contain the nest level of the subquery + where the set function is aggregated. + + The field 'max_arg_level' is for the maximun of the nest levels of the + unbound column references occurred in the set function. A column reference + is unbound within a set function if it is not bound by any subquery + used as a subexpression in this function. A column reference is bound by + a subquery if it is a reference to the column by which the aggregation + of some set function that is used in the subquery is calculated. + For the set function used in the query + SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.b FROM t2 GROUP BY t2.b + HAVING t2.b > ALL(SELECT t3.c FROM t3 GROUP BY t3.c + HAVING SUM(t1.a+t2.b) < t3.c)) + the value of max_arg_level is equal to 1 since t1.a is bound in the main + query, and t2.b is bound by the first subquery whose nest level is 1. + Obviously a set function cannot be aggregated in the subquery whose + nest level is less than max_arg_level. (Yet it can be aggregated in the + subqueries whose nest level is greater than max_arg_level.) + In the query + SELECT t.a FROM t1 HAVING AVG(t1.a+(SELECT MIN(t2.c) FROM t2)) + the value of the max_arg_level for the AVG set function is 0 since + the reference t2.c is bound in the subquery. + + The field 'max_sum_func_level' is to contain the maximum of the + nest levels of the set functions that are used as subexpressions of + the arguments of the given set function, but not aggregated in any + subquery within this set function. A nested set function s1 can be + used within set function s0 only if s1.max_sum_func_level < + s0.max_sum_func_level. Set function s1 is considered as nested + for set function s0 if s1 is not calculated in any subquery + within s0. + + A set function that is used as a subexpression in an argument of another + set function refers to the latter via the field 'in_sum_func'. + + The condition imposed on the usage of set functions are checked when + we traverse query subexpressions with the help of the recursive method + fix_fields. When we apply this method to an object of the class + Item_sum, first, on the descent, we call the method init_sum_func_check + that initialize members used at checking. Then, on the ascent, we + call the method check_sum_func that validates the set function usage + and reports an error if it is illegal. + The method register_sum_func serves to link the items for the set functions + that are aggregated in the embedding (sub)queries. Circular chains of such + functions are attached to the corresponding st_select_lex structures + through the field inner_sum_func_list. + + Exploiting the fact that the members mentioned above are used in one + recursive function we could have allocated them on the thread stack. + Yet we don't do it now. + + We assume that the nesting level of subquries does not exceed 127. + TODO: to catch queries where the limit is exceeded to make the + code clean here. + +*/ + class Item_sum :public Item_result_field { public: @@ -33,7 +228,14 @@ public: }; Item **args, *tmp_args[2]; + Item **ref_by; /* pointer to a ref to the object used to register it */ + Item_sum *next; /* next in the circular chain of registered objects */ uint arg_count; + Item_sum *in_sum_func; /* embedding set function if any */ + int8 nest_level; /* number of the nesting level of the set function */ + int8 aggr_level; /* nesting level of the aggregating subquery */ + int8 max_arg_level; /* max level of unbound column references */ + int8 max_sum_func_level;/* max level of aggregation for embedded functions */ bool quick_group; /* If incremental update of fields */ void mark_as_sum_func(); @@ -111,6 +313,9 @@ public: virtual Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); bool walk (Item_processor processor, byte *argument); + bool init_sum_func_check(THD *thd); + bool check_sum_func(THD *thd, Item **ref); + bool register_sum_func(THD *thd, Item **ref); }; @@ -126,7 +331,7 @@ public: longlong val_int() { DBUG_ASSERT(fixed == 1); - return (longlong) val_real(); /* Real as default */ + return (longlong) rint(val_real()); /* Real as default */ } String *val_str(String*str); my_decimal *val_decimal(my_decimal *); @@ -392,7 +597,7 @@ public: bool add(); double val_real(); // In SPs we might force the "wrong" type with select into a declare variable - longlong val_int() { return (longlong)val_real(); } + longlong val_int() { return (longlong) rint(val_real()); } my_decimal *val_decimal(my_decimal *); String *val_str(String *str); void reset_field(); @@ -421,7 +626,7 @@ public: enum Type type() const {return FIELD_VARIANCE_ITEM; } double val_real(); longlong val_int() - { /* can't be fix_fields()ed */ return (longlong) val_real(); } + { /* can't be fix_fields()ed */ return (longlong) rint(val_real()); } String *val_str(String*); my_decimal *val_decimal(my_decimal *); bool is_null() { (void) val_int(); return null_value; } @@ -699,7 +904,7 @@ class Item_sum_udf_float :public Item_udf_sum longlong val_int() { DBUG_ASSERT(fixed == 1); - return (longlong) Item_sum_udf_float::val_real(); + return (longlong) rint(Item_sum_udf_float::val_real()); } double val_real(); String *val_str(String*str); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 459b5a22cb1..61449d3c671 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -506,7 +506,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, str->set_charset(&my_charset_bin); if (l_time->neg) - str->append("-", 1); + str->append('-'); end= (ptr= format->format.str) + format->format.length; for (; ptr != end ; ptr++) @@ -546,21 +546,21 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, 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", 2); + str->append(STRING_WITH_LEN("th")); else { switch (l_time->day %10) { case 1: - str->append("st",2); + str->append(STRING_WITH_LEN("st")); break; case 2: - str->append("nd",2); + str->append(STRING_WITH_LEN("nd")); break; case 3: - str->append("rd",2); + str->append(STRING_WITH_LEN("rd")); break; default: - str->append("th",2); + str->append(STRING_WITH_LEN("th")); break; } } @@ -1610,6 +1610,7 @@ void Item_func_date_format::fix_length_and_dec() if (args[1]->type() == STRING_ITEM) { // Optimize the normal case fixed_length=1; + /* The result is a binary string (no reason to use collation->mbmaxlen This is becasue make_date_time() only returns binary strings @@ -1627,6 +1628,30 @@ void Item_func_date_format::fix_length_and_dec() } +bool Item_func_date_format::eq(const Item *item, bool binary_cmp) const +{ + Item_func_date_format *item_func; + if (item->type() != FUNC_ITEM) + return 0; + if (func_name() != ((Item_func*) item)->func_name()) + return 0; + if (this == item) + return 1; + item_func= (Item_func_date_format*) item; + if (!args[0]->eq(item_func->args[0], binary_cmp)) + return 0; + /* + We must compare format string case sensitive. + This needed because format modifiers with different case, + for example %m and %M, have different meaning. + */ + if (!args[1]->eq(item_func->args[1], 1)) + return 0; + return 1; +} + + + uint Item_func_date_format::format_length(const String *format) { uint size=0; @@ -2117,9 +2142,9 @@ void Item_date_add_interval::print(String *str) void Item_extract::print(String *str) { - str->append("extract(", 8); + str->append(STRING_WITH_LEN("extract(")); str->append(interval_names[int_type]); - str->append(" from ", 6); + str->append(STRING_WITH_LEN(" from ")); args[0]->print(str); str->append(')'); } @@ -2261,9 +2286,9 @@ bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const void Item_typecast::print(String *str) { - str->append("cast(", 5); + str->append(STRING_WITH_LEN("cast(")); args[0]->print(str); - str->append(" as ", 4); + str->append(STRING_WITH_LEN(" as ")); str->append(cast_type()); str->append(')'); } @@ -2271,9 +2296,9 @@ void Item_typecast::print(String *str) void Item_char_typecast::print(String *str) { - str->append("cast(", 5); + str->append(STRING_WITH_LEN("cast(")); args[0]->print(str); - str->append(" as char", 8); + str->append(STRING_WITH_LEN(" as char")); if (cast_length >= 0) { str->append('('); @@ -2286,7 +2311,7 @@ void Item_char_typecast::print(String *str) } if (cast_cs) { - str->append(" charset ", 9); + str->append(STRING_WITH_LEN(" charset ")); str->append(cast_cs->csname); } str->append(')'); @@ -2327,22 +2352,37 @@ String *Item_char_typecast::val_str(String *str) and the result is longer than cast length, e.g. CAST('string' AS CHAR(1)) */ - if (cast_length >= 0 && - (res->length() > (length= (uint32) res->charpos(cast_length)))) - { // Safe even if const arg - char char_type[40]; - my_snprintf(char_type, sizeof(char_type), "CHAR(%lu)", length); - - if (!res->alloced_length()) - { // Don't change const str - str_value= *res; // Not malloced string - res= &str_value; + if (cast_length >= 0) + { + if (res->length() > (length= (uint32) res->charpos(cast_length))) + { // Safe even if const arg + char char_type[40]; + my_snprintf(char_type, sizeof(char_type), "%s(%lu)", + cast_cs == &my_charset_bin ? "BINARY" : "CHAR", length); + + if (!res->alloced_length()) + { // Don't change const str + str_value= *res; // Not malloced string + res= &str_value; + } + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), char_type, + res->c_ptr_safe()); + res->length((uint) length); + } + else if (cast_cs == &my_charset_bin && res->length() < (uint) cast_length) + { + if (res->alloced_length() < (uint) cast_length) + { + str->alloc(cast_length); + str->copy(*res); + res= str; + } + bzero((char*) res->ptr() + res->length(), + (uint) cast_length - res->length()); + res->length(cast_length); } - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_TRUNCATED_WRONG_VALUE, - ER(ER_TRUNCATED_WRONG_VALUE), char_type, - res->c_ptr_safe()); - res->length((uint) length); } null_value= 0; return res; @@ -2479,6 +2519,7 @@ void Item_func_add_time::fix_length_and_dec() enum_field_types arg0_field_type; decimals=0; max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; + maybe_null= 1; /* The field type for the result of an Item_func_add_time function is defined @@ -2583,14 +2624,14 @@ void Item_func_add_time::print(String *str) if (is_date) { DBUG_ASSERT(sign > 0); - str->append("timestamp(", 10); + str->append(STRING_WITH_LEN("timestamp(")); } else { if (sign > 0) - str->append("addtime(", 8); + str->append(STRING_WITH_LEN("addtime(")); else - str->append("subtime(", 8); + str->append(STRING_WITH_LEN("subtime(")); } args[0]->print(str); str->append(','); @@ -2799,31 +2840,31 @@ void Item_func_timestamp_diff::print(String *str) switch (int_type) { case INTERVAL_YEAR: - str->append("YEAR"); + str->append(STRING_WITH_LEN("YEAR")); break; case INTERVAL_QUARTER: - str->append("QUARTER"); + str->append(STRING_WITH_LEN("QUARTER")); break; case INTERVAL_MONTH: - str->append("MONTH"); + str->append(STRING_WITH_LEN("MONTH")); break; case INTERVAL_WEEK: - str->append("WEEK"); + str->append(STRING_WITH_LEN("WEEK")); break; case INTERVAL_DAY: - str->append("DAY"); + str->append(STRING_WITH_LEN("DAY")); break; case INTERVAL_HOUR: - str->append("HOUR"); + str->append(STRING_WITH_LEN("HOUR")); break; case INTERVAL_MINUTE: - str->append("MINUTE"); + str->append(STRING_WITH_LEN("MINUTE")); break; case INTERVAL_SECOND: - str->append("SECOND"); + str->append(STRING_WITH_LEN("SECOND")); break; case INTERVAL_MICROSECOND: - str->append("SECOND_FRAC"); + str->append(STRING_WITH_LEN("SECOND_FRAC")); break; default: break; @@ -2879,13 +2920,13 @@ void Item_func_get_format::print(String *str) switch (type) { case MYSQL_TIMESTAMP_DATE: - str->append("DATE, "); + str->append(STRING_WITH_LEN("DATE, ")); break; case MYSQL_TIMESTAMP_DATETIME: - str->append("DATETIME, "); + str->append(STRING_WITH_LEN("DATETIME, ")); break; case MYSQL_TIMESTAMP_TIME: - str->append("TIME, "); + str->append(STRING_WITH_LEN("TIME, ")); break; default: DBUG_ASSERT(0); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 8e15acbc1fc..71f595184ec 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -537,6 +537,7 @@ public: { return is_time_format ? "time_format" : "date_format"; } void fix_length_and_dec(); uint format_length(const String *format); + bool eq(const Item *item, bool binary_cmp) const; }; @@ -640,12 +641,12 @@ enum interval_type class Item_date_add_interval :public Item_date_func { - const interval_type int_type; String value; - const bool date_sub_interval; enum_field_types cached_field_type; public: + const interval_type int_type; // keep it public + const bool date_sub_interval; // keep it public Item_date_add_interval(Item *a,Item *b,interval_type type_arg,bool neg_arg) :Item_date_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {} String *val_str(String *); @@ -661,10 +662,10 @@ public: class Item_extract :public Item_int_func { - const interval_type int_type; String value; bool date_value; public: + const interval_type int_type; // keep it public Item_extract(interval_type type_arg, Item *a) :Item_int_func(a), int_type(type_arg) {} longlong val_int(); @@ -844,6 +845,7 @@ public: { decimals=0; max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; + maybe_null= 1; } Field *tmp_table_field(TABLE *t_arg) { @@ -908,8 +910,8 @@ enum date_time_format class Item_func_get_format :public Item_str_func { - const timestamp_type type; public: + const timestamp_type type; // keep it public Item_func_get_format(timestamp_type type_arg, Item *a) :Item_str_func(a), type(type_arg) {} diff --git a/sql/item_uniq.h b/sql/item_uniq.h index c884c454dac..a0aa0b96cc6 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -29,7 +29,7 @@ public: :Item_real_func(list) {} double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; } void fix_length_and_dec() { decimals=0; max_length=6; } - void print(String *str) { str->append("0.0", 3); } + void print(String *str) { str->append(STRING_WITH_LEN("0.0")); } const char *func_name() const { return "unique_users"; } }; @@ -57,7 +57,7 @@ public: { return new Item_sum_unique_users(thd, this); } - void print(String *str) { str->append("0.0", 3); } + void print(String *str) { str->append(STRING_WITH_LEN("0.0")); } Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); const char *func_name() const { return "sum_unique_users"; } }; diff --git a/sql/key.cc b/sql/key.cc index 4bd71d2fa47..9d86095f33e 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -322,7 +322,7 @@ void key_unpack(String *to,TABLE *table,uint idx) { if (table->record[0][key_part->null_offset] & key_part->null_bit) { - to->append("NULL", 4); + to->append(STRING_WITH_LEN("NULL")); continue; } } @@ -334,7 +334,7 @@ void key_unpack(String *to,TABLE *table,uint idx) to->append(tmp); } else - to->append("???", 3); + to->append(STRING_WITH_LEN("???")); } DBUG_VOID_RETURN; } diff --git a/sql/lex.h b/sql/lex.h index a5366742fd9..efcb9b84f81 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -110,6 +110,7 @@ static SYMBOL symbols[] = { { "CIPHER", SYM(CIPHER_SYM)}, { "CLIENT", SYM(CLIENT_SYM)}, { "CLOSE", SYM(CLOSE_SYM)}, + { "CODE", SYM(CODE_SYM)}, { "COLLATE", SYM(COLLATE_SYM)}, { "COLLATION", SYM(COLLATION_SYM)}, { "COLUMN", SYM(COLUMN_SYM)}, diff --git a/sql/lock.cc b/sql/lock.cc index f4c4a781e45..d0bfcfd7272 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -423,6 +423,127 @@ MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b) } +/* + Find duplicate lock in tables. + + SYNOPSIS + mysql_lock_have_duplicate() + thd The current thread. + needle The table to check for duplicate lock. + haystack The list of tables to search for the dup lock. + + NOTE + This is mainly meant for MERGE tables in INSERT ... SELECT + situations. The 'real', underlying tables can be found only after + the table is opened. The easier way is to check this after the + tables are locked. + + RETURN + 1 A table from 'tables' matches a lock on 'table'. + 0 No duplicate lock is present. + -1 Error. +*/ + +TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle, + TABLE_LIST *haystack) +{ + uint count; + uint dup_pos; + TABLE *write_lock_used; /* dummy */ + TABLE **tables1; + TABLE **tables2; + TABLE **table_ptr; + TABLE_LIST *tlist_ptr; + MYSQL_LOCK *sql_lock1; + MYSQL_LOCK *sql_lock2; + THR_LOCK_DATA **lock_data1; + THR_LOCK_DATA **end_data1; + THR_LOCK_DATA **lock_data2; + THR_LOCK_DATA **end_data2; + THR_LOCK *lock1; + DBUG_ENTER("mysql_lock_have_duplicate"); + + /* Table may not be defined for derived or view tables. */ + if (! needle->table) + DBUG_RETURN(NULL); + + /* Get lock(s) for needle. */ + tables1= &needle->table; + if (! (sql_lock1= get_lock_data(thd, tables1, 1, 1, &write_lock_used))) + goto err0; + + /* Count real tables in list. */ + count=0; + for (tlist_ptr = haystack; tlist_ptr; tlist_ptr= tlist_ptr->next_global) + if (! tlist_ptr->placeholder() && ! tlist_ptr->schema_table) + count++; + /* Allocate a table array. */ + if (! (tables2= (TABLE**) sql_alloc(sizeof(TABLE*) * count))) + goto err1; + table_ptr= tables2; + /* Assign table pointers. */ + for (tlist_ptr = haystack; tlist_ptr; tlist_ptr= tlist_ptr->next_global) + if (! tlist_ptr->placeholder() && ! tlist_ptr->schema_table) + *(table_ptr++)= tlist_ptr->table; + /* Get lock(s) for haystack. */ + if (! (sql_lock2= get_lock_data(thd, tables2, count, 1, &write_lock_used))) + goto err1; + + /* Initialize duplicate position to an impossible value. */ + dup_pos= UINT_MAX; + /* + Find a duplicate lock. + In case of merge tables, sql_lock1 can have more than 1 lock. + */ + for (lock_data1= sql_lock1->locks, + end_data1= lock_data1 + sql_lock1->lock_count; + lock_data1 < end_data1; + lock_data1++) + { + lock1= (*lock_data1)->lock; + for (lock_data2= sql_lock2->locks, + end_data2= lock_data2 + sql_lock2->lock_count; + lock_data2 < end_data2; + lock_data2++) + { + if ((*lock_data2)->lock == lock1) + { + DBUG_PRINT("ingo", ("duplicate lock found")); + /* Change duplicate position to the real value. */ + dup_pos= lock_data2 - sql_lock2->locks; + goto end; + } + } + } + + end: + tlist_ptr= NULL; /* In case that no duplicate was found. */ + if (dup_pos != UINT_MAX) + { + /* Duplicate found. Search the matching TABLE_LIST object. */ + count= 0; + for (tlist_ptr = haystack; tlist_ptr; tlist_ptr= tlist_ptr->next_global) + { + if (! tlist_ptr->placeholder() && ! tlist_ptr->schema_table) + { + count+= tlist_ptr->table->file->lock_count(); + if (count > dup_pos) + break; + } + } + } + my_free((gptr) sql_lock2, MYF(0)); + my_free((gptr) sql_lock1, MYF(0)); + DBUG_RETURN(tlist_ptr); + + err1: + my_free((gptr) sql_lock1, MYF(0)); + err0: + /* This non-null but special value indicates error, if caller cares. */ + DBUG_RETURN(needle); +} + + /* unlock a set of external */ static int unlock_external(THD *thd, TABLE **table,uint count) @@ -460,6 +581,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, MYSQL_LOCK *sql_lock; THR_LOCK_DATA **locks; TABLE **to; + DBUG_ENTER("get_lock_data"); *write_lock_used=0; for (i=tables=lock_count=0 ; i < count ; i++) @@ -488,7 +610,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, my_malloc(sizeof(*sql_lock)+ sizeof(THR_LOCK_DATA*)*tables+sizeof(table_ptr)*lock_count, MYF(0)))) - return 0; + DBUG_RETURN(0); locks=sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1); to=sql_lock->table=(TABLE**) (locks+tables); sql_lock->table_count=lock_count; @@ -508,7 +630,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, { my_error(ER_OPEN_AS_READONLY, MYF(0), table->alias); my_free((gptr) sql_lock,MYF(0)); - return 0; + DBUG_RETURN(0); } } THR_LOCK_DATA **org_locks = locks; @@ -518,7 +640,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, for ( ; org_locks != locks ; org_locks++) (*org_locks)->debug_print_param= (void *) table; } - return sql_lock; + DBUG_RETURN(sql_lock); } @@ -601,6 +723,7 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) char key[MAX_DBKEY_LENGTH]; char *db= table_list->db; uint key_length; + HASH_SEARCH_STATE state; DBUG_ENTER("lock_table_name"); DBUG_PRINT("enter",("db: %s name: %s", db, table_list->table_name)); @@ -611,9 +734,9 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) /* Only insert the table if we haven't insert it already */ - for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; + for (table=(TABLE*) hash_first(&open_cache, (byte*)key, key_length, &state); table ; - table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + table = (TABLE*) hash_next(&open_cache, (byte*)key, key_length, &state)) if (table->in_use == thd) DBUG_RETURN(0); @@ -815,10 +938,13 @@ static void print_lock_error(int error, const char *table) access to them is protected with a mutex LOCK_global_read_lock - (XXX: one should never take LOCK_open if LOCK_global_read_lock is taken, - otherwise a deadlock may occur - see mysql_rm_table. Other mutexes could - be a problem too - grep the code for global_read_lock if you want to use - any other mutex here) + (XXX: one should never take LOCK_open if LOCK_global_read_lock is + taken, otherwise a deadlock may occur. Other mutexes could be a + problem too - grep the code for global_read_lock if you want to use + any other mutex here) Also one must not hold LOCK_open when calling + wait_if_global_read_lock(). When the thread with the global read lock + tries to close its tables, it needs to take LOCK_open in + close_thread_table(). How blocking of threads by global read lock is achieved: that's advisory. Any piece of code which should be blocked by global read lock must @@ -937,6 +1063,13 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, DBUG_ENTER("wait_if_global_read_lock"); LINT_INIT(old_message); + /* + Assert that we do not own LOCK_open. If we would own it, other + threads could not close their tables. This would make a pretty + deadlock. + */ + safe_mutex_assert_not_owner(&LOCK_open); + (void) pthread_mutex_lock(&LOCK_global_read_lock); if ((need_exit_cond= must_wait)) { diff --git a/sql/log.cc b/sql/log.cc index a881602d510..6c37cb04c61 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -67,7 +67,7 @@ handlerton binlog_hton = { NULL, /* create_cursor_read_view */ NULL, /* set_cursor_read_view */ NULL, /* close_cursor_read_view */ - HTON_NO_FLAGS + HTON_HIDDEN }; /* @@ -131,7 +131,7 @@ static int binlog_commit(THD *thd, bool all) // we're here because trans_log was flushed in MYSQL_LOG::log() DBUG_RETURN(0); } - Query_log_event qev(thd, "COMMIT", 6, TRUE, FALSE); + Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE); DBUG_RETURN(binlog_end_trans(thd, trans_log, &qev)); } @@ -155,7 +155,7 @@ static int binlog_rollback(THD *thd, bool all) */ if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE)) { - Query_log_event qev(thd, "ROLLBACK", 8, TRUE, FALSE); + Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE); error= binlog_end_trans(thd, trans_log, &qev); } else @@ -356,9 +356,9 @@ static int find_uniq_filename(char *name) MYSQL_LOG::MYSQL_LOG() :bytes_written(0), last_time(0), query_start(0), name(0), - file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0), inited(0), - need_start_event(1), prepared_xids(0), description_event_for_exec(0), - description_event_for_queue(0), readers_count(0), reset_pending(false) + prepared_xids(0), log_type(LOG_CLOSED), file_id(1), open_count(1), + write_error(FALSE), inited(FALSE), need_start_event(TRUE), + description_event_for_exec(0), description_event_for_queue(0) { /* We don't want to initialize LOCK_Log here as such initialization depends on @@ -384,9 +384,7 @@ void MYSQL_LOG::cleanup() delete description_event_for_exec; (void) pthread_mutex_destroy(&LOCK_log); (void) pthread_mutex_destroy(&LOCK_index); - (void) pthread_mutex_destroy(&LOCK_readers); (void) pthread_cond_destroy(&update_cond); - (void) pthread_cond_destroy(&reset_cond); } DBUG_VOID_RETURN; } @@ -431,9 +429,7 @@ void MYSQL_LOG::init_pthread_objects() inited= 1; (void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW); (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW); - (void) pthread_mutex_init(&LOCK_readers, MY_MUTEX_INIT_SLOW); (void) pthread_cond_init(&update_cond, 0); - (void) pthread_cond_init(&reset_cond, 0); } const char *MYSQL_LOG::generate_name(const char *log_name, @@ -937,12 +933,6 @@ bool MYSQL_LOG::reset_logs(THD* thd) pthread_mutex_lock(&LOCK_log); pthread_mutex_lock(&LOCK_index); - /* - we need one more lock to block attempts to open a log while - we are waiting untill all log files will be closed - */ - pthread_mutex_lock(&LOCK_readers); - /* The following mutex is needed to ensure that no threads call 'delete thd' as we would then risk missing a 'rollback' from this @@ -965,19 +955,6 @@ bool MYSQL_LOG::reset_logs(THD* thd) goto err; } - reset_pending= true; - /* - send update signal just in case so that all reader threads waiting - for log update will leave wait condition - */ - signal_update(); - /* - if there are active readers wait until all of them will - release opened files - */ - if (readers_count) - pthread_cond_wait(&reset_cond, &LOCK_log); - for (;;) { my_delete(linfo.log_file_name, MYF(MY_WME)); @@ -996,10 +973,7 @@ bool MYSQL_LOG::reset_logs(THD* thd) my_free((gptr) save_name, MYF(0)); err: - reset_pending= false; - (void) pthread_mutex_unlock(&LOCK_thread_count); - pthread_mutex_unlock(&LOCK_readers); pthread_mutex_unlock(&LOCK_index); pthread_mutex_unlock(&LOCK_log); DBUG_RETURN(error); @@ -1847,7 +1821,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event) */ if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { - Query_log_event qinfo(thd, "BEGIN", 5, TRUE, FALSE); + Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE); /* Imagine this is rollback due to net timeout, after all statements of the transaction succeeded. Then we want a zero-error code in BEGIN. @@ -2072,9 +2046,6 @@ void MYSQL_LOG::wait_for_update(THD* thd, bool is_slave) { const char *old_msg; DBUG_ENTER("wait_for_update"); - - if (reset_pending) - DBUG_VOID_RETURN; old_msg= thd->enter_cond(&update_cond, &LOCK_log, is_slave ? @@ -2326,33 +2297,6 @@ void MYSQL_LOG::signal_update() DBUG_VOID_RETURN; } -void MYSQL_LOG::readers_addref() -{ - /* - There is no necessity for reference counting on *nix, since it allows to - delete opened files, however it is more clean way to wait - untill all files will be closed on *nix as well. - */ - DBUG_ENTER("MYSQL_LOG::reader_addref"); - pthread_mutex_lock(&LOCK_log); - pthread_mutex_lock(&LOCK_readers); - readers_count++; - pthread_mutex_unlock(&LOCK_readers); - pthread_mutex_unlock(&LOCK_log); - DBUG_VOID_RETURN; -} - -void MYSQL_LOG::readers_release() -{ - DBUG_ENTER("MYSQL_LOG::reader_release"); - pthread_mutex_lock(&LOCK_log); - readers_count--; - if (!readers_count) - pthread_cond_broadcast(&reset_cond); - pthread_mutex_unlock(&LOCK_log); - DBUG_VOID_RETURN; -} - #ifdef __NT__ void print_buffer_to_nt_eventlog(enum loglevel level, char *buff, uint length, int buffLen) diff --git a/sql/log_event.cc b/sql/log_event.cc index 2390ebd4214..519b077b17b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -114,13 +114,24 @@ static char *pretty_print_str(char *packet, char *str, int len) /* - slave_load_file_stem() + Creates a temporary name for load data infile: + + SYNOPSIS + slave_load_file_stem() + buf Store new filename here + file_id File_id (part of file name) + event_server_id Event_id (part of file name) + ext Extension for file name + + RETURN + Pointer to start of extension */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -static inline char* slave_load_file_stem(char*buf, uint file_id, - int event_server_id) +static char *slave_load_file_stem(char *buf, uint file_id, + int event_server_id, const char *ext) { + char *res; fn_format(buf,"SQL_LOAD-",slave_load_tmpdir, "", MY_UNPACK_FILENAME); to_unix_path(buf); @@ -129,7 +140,9 @@ static inline char* slave_load_file_stem(char*buf, uint file_id, *buf++ = '-'; buf = int10_to_str(event_server_id, buf, 10); *buf++ = '-'; - return int10_to_str(file_id, buf, 10); + res= int10_to_str(file_id, buf, 10); + strmov(res, ext); // Add extension last + return res; // Pointer to extension } #endif @@ -160,7 +173,7 @@ static void cleanup_load_tmpdir() we cannot meet Start_log event in the middle of events from one LOAD DATA. */ - p= strmake(prefbuf,"SQL_LOAD-",9); + p= strmake(prefbuf, STRING_WITH_LEN("SQL_LOAD-")); p= int10_to_str(::server_id, p, 10); *(p++)= '-'; *p= 0; @@ -906,9 +919,10 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info) fprintf(file, "# %8.8lx %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x\n", - hexdump_from, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], - ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], - ptr[12], ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]); + (unsigned long) hexdump_from, + ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], + ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], + ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]); ptr += LOG_EVENT_MINIMAL_HEADER_LEN; hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN; } @@ -926,7 +940,8 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info) if (i % 16 == 15) { fprintf(file, "# %8.8lx %-48.48s |%16s|\n", - hexdump_from + (i & 0xfffffff0), hex_string, char_string); + (unsigned long) (hexdump_from + (i & 0xfffffff0)), + hex_string, char_string); hex_string[0]= 0; char_string[0]= 0; c= char_string; @@ -937,10 +952,10 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info) *c= '\0'; /* Non-full last line */ - if (hex_string[0]) { - printf("# %8.8lx %-48.48s |%s|\n# ", - hexdump_from + (i & 0xfffffff0), hex_string, char_string); - } + if (hex_string[0]) + fprintf(file, "# %8.8lx %-48.48s |%s|\n# ", + (unsigned long) (hexdump_from + (i & 0xfffffff0)), + hex_string, char_string); } } @@ -2991,7 +3006,7 @@ void Rotate_log_event::pack_info(Protocol *protocol) String tmp(buf1, sizeof(buf1), log_cs); tmp.length(0); tmp.append(new_log_ident, ident_len); - tmp.append(";pos="); + tmp.append(STRING_WITH_LEN(";pos=")); tmp.append(llstr(pos,buf)); protocol->store(tmp.ptr(), tmp.length(), &my_charset_bin); } @@ -4154,16 +4169,15 @@ void Create_file_log_event::pack_info(Protocol *protocol) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) int Create_file_log_event::exec_event(struct st_relay_log_info* rli) { - char proc_info[17+FN_REFLEN+10], *fname_buf= proc_info+17; - char *p; + char proc_info[17+FN_REFLEN+10], *fname_buf; + char *ext; int fd = -1; IO_CACHE file; int error = 1; bzero((char*)&file, sizeof(file)); - p = slave_load_file_stem(fname_buf, file_id, server_id); - strmov(p, ".info"); // strmov takes less code than memcpy - strnmov(proc_info, "Making temp file ", 17); // no end 0 + fname_buf= strmov(proc_info, "Making temp file "); + ext= slave_load_file_stem(fname_buf, file_id, server_id, ".info"); thd->proc_info= proc_info; my_delete(fname_buf, MYF(0)); // old copy may exist already if ((fd= my_create(fname_buf, CREATE_MODE, @@ -4172,19 +4186,21 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli) init_io_cache(&file, fd, IO_SIZE, WRITE_CACHE, (my_off_t)0, 0, MYF(MY_WME|MY_NABP))) { - slave_print_error(rli,my_errno, "Error in Create_file event: could not open file '%s'", fname_buf); + slave_print_error(rli,my_errno, + "Error in Create_file event: could not open file '%s'", + fname_buf); goto err; } // a trick to avoid allocating another buffer - strmov(p, ".data"); - fname = fname_buf; - fname_len = (uint)(p-fname) + 5; + fname= fname_buf; + fname_len= (uint) (strmov(ext, ".data") - fname); if (write_base(&file)) { - strmov(p, ".info"); // to have it right in the error message + strmov(ext, ".info"); // to have it right in the error message slave_print_error(rli,my_errno, - "Error in Create_file event: could not write to file '%s'", + "Error in Create_file event: could not write to file " + "'%s'", fname_buf); goto err; } @@ -4197,12 +4213,16 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli) O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, MYF(MY_WME))) < 0) { - slave_print_error(rli,my_errno, "Error in Create_file event: could not open file '%s'", fname_buf); + slave_print_error(rli,my_errno, + "Error in Create_file event: could not open file '%s'", + fname_buf); goto err; } if (my_write(fd, (byte*) block, block_len, MYF(MY_WME+MY_NABP))) { - slave_print_error(rli,my_errno, "Error in Create_file event: write to '%s' failed", fname_buf); + slave_print_error(rli,my_errno, + "Error in Create_file event: write to '%s' failed", + fname_buf); goto err; } error=0; // Everything is ok @@ -4326,13 +4346,12 @@ int Append_block_log_event::get_create_or_append() const int Append_block_log_event::exec_event(struct st_relay_log_info* rli) { char proc_info[17+FN_REFLEN+10], *fname= proc_info+17; - char *p= slave_load_file_stem(fname, file_id, server_id); int fd; int error = 1; DBUG_ENTER("Append_block_log_event::exec_event"); - memcpy(p, ".data", 6); - strnmov(proc_info, "Making temp file ", 17); // no end 0 + fname= strmov(proc_info, "Making temp file "); + slave_load_file_stem(fname, file_id, server_id, ".data"); thd->proc_info= proc_info; if (get_create_or_append()) { @@ -4458,10 +4477,9 @@ void Delete_file_log_event::pack_info(Protocol *protocol) int Delete_file_log_event::exec_event(struct st_relay_log_info* rli) { char fname[FN_REFLEN+10]; - char *p= slave_load_file_stem(fname, file_id, server_id); - memcpy(p, ".data", 6); + char *ext= slave_load_file_stem(fname, file_id, server_id, ".data"); (void) my_delete(fname, MYF(MY_WME)); - memcpy(p, ".info", 6); + strmov(ext, ".info"); (void) my_delete(fname, MYF(MY_WME)); return Log_event::exec_event(rli); } @@ -4554,19 +4572,21 @@ void Execute_load_log_event::pack_info(Protocol *protocol) int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) { char fname[FN_REFLEN+10]; - char *p= slave_load_file_stem(fname, file_id, server_id); + char *ext; int fd; - int error = 1; + int error= 1; IO_CACHE file; - Load_log_event* lev = 0; + Load_log_event *lev= 0; - memcpy(p, ".info", 6); + ext= slave_load_file_stem(fname, file_id, server_id, ".info"); if ((fd = my_open(fname, O_RDONLY | O_BINARY | O_NOFOLLOW, MYF(MY_WME))) < 0 || init_io_cache(&file, fd, IO_SIZE, READ_CACHE, (my_off_t)0, 0, MYF(MY_WME|MY_NABP))) { - slave_print_error(rli,my_errno, "Error in Exec_load event: could not open file '%s'", fname); + slave_print_error(rli,my_errno, + "Error in Exec_load event: could not open file '%s'", + fname); goto err; } if (!(lev = (Load_log_event*)Log_event::read_log_event(&file, @@ -4574,7 +4594,9 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) rli->relay_log.description_event_for_exec)) || lev->get_type_code() != NEW_LOAD_EVENT) { - slave_print_error(rli,0, "Error in Exec_load event: file '%s' appears corrupted", fname); + slave_print_error(rli,0, + "Error in Exec_load event: file '%s' appears corrupted", + fname); goto err; } @@ -4619,7 +4641,7 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) fd= -1; } (void) my_delete(fname, MYF(MY_WME)); - memcpy(p, ".data", 6); + memcpy(ext, ".data", 6); (void) my_delete(fname, MYF(MY_WME)); error = 0; @@ -4816,23 +4838,22 @@ Execute_load_query_log_event::exec_event(struct st_relay_log_info* rli) p= buf; memcpy(p, query, fn_pos_start); p+= fn_pos_start; - fname= (p= strmake(p, " INFILE \'", 9)); - p= slave_load_file_stem(p, file_id, server_id); - fname_end= (p= strmake(p, ".data", 5)); + fname= (p= strmake(p, STRING_WITH_LEN(" INFILE \'"))); + p= slave_load_file_stem(p, file_id, server_id, ".data"); + fname_end= p= strend(p); // Safer than p=p+5 *(p++)='\''; - switch (dup_handling) - { + switch (dup_handling) { case LOAD_DUP_IGNORE: - p= strmake(p, " IGNORE", 7); + p= strmake(p, STRING_WITH_LEN(" IGNORE")); break; case LOAD_DUP_REPLACE: - p= strmake(p, " REPLACE", 8); + p= strmake(p, STRING_WITH_LEN(" REPLACE")); break; default: /* Ordinary load data */ break; } - p= strmake(p, " INTO", 5); + p= strmake(p, STRING_WITH_LEN(" INTO")); p= strmake(p, query+fn_pos_end, q_len-fn_pos_end); error= Query_log_event::exec_event(rli, buf, p-buf); diff --git a/sql/log_event.h b/sql/log_event.h index 8acdf015464..7783a97f03f 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -430,11 +430,10 @@ enum Log_event_type /* Add new events here - right above this comment! - And change the ENUM_END_EVENT_MARKER below. - Existing events should never change their numbers + Existing events (except ENUM_END_EVENT) should never change their numbers */ - ENUM_END_EVENT= 19 /* end marker */ + ENUM_END_EVENT /* end marker */ }; /* diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index f188d27ff78..1bd16940b47 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -185,7 +185,7 @@ int str2my_decimal(uint mask, const char *from, uint length, } } } - check_result(mask, err); + check_result_and_overflow(mask, err, decimal_value); return err; } diff --git a/sql/my_decimal.h b/sql/my_decimal.h index b65e6aedaa2..b02abacf0a3 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -126,6 +126,19 @@ inline int decimal_operation_results(int result) } #endif /*MYSQL_CLIENT*/ +inline +void max_my_decimal(my_decimal *to, int precision, int frac) +{ + DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&& + (frac <= DECIMAL_MAX_SCALE)); + max_decimal(precision, frac, (decimal_t*) to); +} + +inline void max_internal_decimal(my_decimal *to) +{ + max_my_decimal(to, DECIMAL_MAX_PRECISION, 0); +} + inline int check_result(uint mask, int result) { if (result & mask) @@ -133,6 +146,18 @@ inline int check_result(uint mask, int result) return result; } +inline int check_result_and_overflow(uint mask, int result, my_decimal *val) +{ + if (check_result(mask, result) & E_DEC_OVERFLOW) + { + bool sign= val->sign(); + val->fix_buffer_pointer(); + max_internal_decimal(val); + val->sign(sign); + } + return result; +} + inline uint my_decimal_length_to_precision(uint length, uint scale, bool unsigned_flag) { @@ -256,7 +281,8 @@ int my_decimal2double(uint mask, const my_decimal *d, double *result) inline int str2my_decimal(uint mask, const char *str, my_decimal *d, char **end) { - return check_result(mask, string2decimal(str, (decimal_t*) d, end)); + return check_result_and_overflow(mask, string2decimal(str,(decimal_t*)d,end), + d); } @@ -274,7 +300,7 @@ int string2my_decimal(uint mask, const String *str, my_decimal *d) inline int double2my_decimal(uint mask, double val, my_decimal *d) { - return check_result(mask, double2decimal(val, (decimal_t*) d)); + return check_result_and_overflow(mask, double2decimal(val, (decimal_t*)d), d); } @@ -303,7 +329,9 @@ inline int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_add((decimal_t*) a, (decimal_t*) b, res)); + return check_result_and_overflow(mask, + decimal_add((decimal_t*)a,(decimal_t*)b,res), + res); } @@ -311,7 +339,9 @@ inline int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_sub((decimal_t*) a, (decimal_t*) b, res)); + return check_result_and_overflow(mask, + decimal_sub((decimal_t*)a,(decimal_t*)b,res), + res); } @@ -319,7 +349,9 @@ inline int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_mul((decimal_t*) a, (decimal_t*) b, res)); + return check_result_and_overflow(mask, + decimal_mul((decimal_t*)a,(decimal_t*)b,res), + res); } @@ -327,8 +359,10 @@ inline int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b, int div_scale_inc) { - return check_result(mask, decimal_div((decimal_t*) a, (decimal_t*) b, res, - div_scale_inc)); + return check_result_and_overflow(mask, + decimal_div((decimal_t*)a,(decimal_t*)b,res, + div_scale_inc), + res); } @@ -336,7 +370,9 @@ inline int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_mod((decimal_t*) a, (decimal_t*) b, res)); + return check_result_and_overflow(mask, + decimal_mod((decimal_t*)a,(decimal_t*)b,res), + res); } @@ -347,13 +383,5 @@ int my_decimal_cmp(const my_decimal *a, const my_decimal *b) return decimal_cmp((decimal_t*) a, (decimal_t*) b); } -inline -void max_my_decimal(my_decimal *to, int precision, int frac) -{ - DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&& - (frac <= DECIMAL_MAX_SCALE)); - max_decimal(precision, frac, (decimal_t*) to); -} - #endif /*my_decimal_h*/ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index e33ac05e293..ca2cda0f7c6 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -42,8 +42,19 @@ /* TODO convert all these three maps to Bitmap classes */ typedef ulonglong table_map; /* Used for table bits in join */ -typedef Bitmap<64> key_map; /* Used for finding keys */ +#if MAX_INDEXES <= 64 +typedef Bitmap<64> key_map; /* Used for finding keys */ +#else +typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */ +#endif typedef ulong key_part_map; /* Used for finding key parts */ +typedef ulong nesting_map; /* Used for flags of nesting constructs */ +/* + Used to identify NESTED_JOIN structures within a join (applicable only to + structures that have not been simplified away and embed more the one + element) +*/ +typedef ulonglong nested_join_map; /* query_id */ typedef ulonglong query_id_t; @@ -95,6 +106,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; #define MAX_FIELDS_BEFORE_HASH 32 #define USER_VARS_HASH_SIZE 16 #define STACK_MIN_SIZE 8192 // Abort if less stack during eval. +#define STACK_MIN_SIZE_FOR_OPEN 1024*80 #define STACK_BUFF_ALLOC 256 // For stack overrun checks #ifndef MYSQLD_NET_RETRY_COUNT #define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int. @@ -516,8 +528,9 @@ bool delete_precheck(THD *thd, TABLE_LIST *tables); bool insert_precheck(THD *thd, TABLE_LIST *tables); bool create_table_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *create_table); -bool default_view_definer(Security_context *sctx, st_lex_user *definer); +bool get_default_definer(THD *thd, LEX_USER *definer); +LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name); enum enum_mysql_completiontype { ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7, @@ -652,6 +665,7 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list, bool mysql_preload_keys(THD* thd, TABLE_LIST* table_list); int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache, KEY_CACHE *dst_cache); +TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list); bool mysql_xa_recover(THD *thd); @@ -679,11 +693,11 @@ int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type, select_result *result); bool mysql_union(THD *thd, LEX *lex, select_result *result, SELECT_LEX_UNIT *unit, ulong setup_tables_done_option); -int mysql_handle_derived(LEX *lex, int (*processor)(THD *thd, - LEX *lex, - TABLE_LIST *table)); -int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *t); -int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t); +bool mysql_handle_derived(LEX *lex, bool (*processor)(THD *thd, + LEX *lex, + TABLE_LIST *table)); +bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *t); +bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, bool group, bool modify_item, @@ -783,17 +797,16 @@ find_field_in_tables(THD *thd, Item_ident *item, bool check_privileges, bool register_tree_change); Field * find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, - const char *name, const char *item_name, - const char *table_name, const char *db_name, - uint length, Item **ref, - bool check_grants_table, bool check_grants_view, - bool allow_rowid, + const char *name, uint length, + const char *item_name, const char *db_name, + const char *table_name, Item **ref, + bool check_privileges, bool allow_rowid, uint *cached_field_index_ptr, bool register_tree_change, TABLE_LIST **actual_table); Field * -find_field_in_table(THD *thd, TABLE *table, const char *name, - uint length, bool check_grants, bool allow_rowid, - uint *cached_field_index_ptr); +find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, + bool allow_rowid, uint *cached_field_index_ptr); + #ifdef HAVE_OPENSSL #include <openssl/des.h> struct st_des_keyblock @@ -839,6 +852,10 @@ bool mysqld_show_column_types(THD *thd); bool mysqld_help (THD *thd, const char *text); void calc_sum_of_all_status(STATUS_VAR *to); +void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user, + const LEX_STRING *definer_host); + + /* information schema */ extern LEX_STRING information_schema_name; LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str, @@ -877,7 +894,8 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen); bool mysql_ha_close(THD *thd, TABLE_LIST *tables); bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *, List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows); -int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags); +int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags, + bool is_locked); /* mysql_ha_flush mode_flags bits */ #define MYSQL_HA_CLOSE_FINAL 0x00 #define MYSQL_HA_REOPEN_ON_USAGE 0x01 @@ -903,8 +921,9 @@ create_field * new_create_field(THD *thd, char *field_name, enum_field_types typ uint uint_geom_type); void store_position_for_column(const char *name); bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc); -Name_resolution_context *make_join_on_context(THD *thd, TABLE_LIST *left_op, - TABLE_LIST *right_op); +bool push_new_name_resolution_context(THD *thd, + TABLE_LIST *left_op, + TABLE_LIST *right_op); void add_join_on(TABLE_LIST *b,Item *expr); void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields); bool add_proc_to_list(THD *thd, Item *item); @@ -967,7 +986,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, uint offset_to_list, const char *db_name, const char *table_name); -TABLE_LIST *unique_table(TABLE_LIST *table, TABLE_LIST *table_list); +TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list); TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name); bool close_temporary_table(THD *thd, const char *db, const char *table_name); void close_temporary(TABLE *table, bool delete_table); @@ -1086,8 +1105,8 @@ void unhex_type2(TYPELIB *lib); uint check_word(TYPELIB *lib, const char *val, const char *end, const char **end_of_word); -bool is_keyword(const char *name, uint len); +bool is_keyword(const char *name, uint len); #define MY_DB_OPT_FILE "db.opt" bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create); @@ -1172,7 +1191,7 @@ extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs; extern my_bool opt_secure_auth; extern my_bool opt_log_slow_admin_statements; extern my_bool sp_automatic_privileges, opt_noacl; -extern my_bool opt_old_style_user_limits, trust_routine_creators; +extern my_bool opt_old_style_user_limits, trust_function_creators; extern uint opt_crash_binlog_innodb; extern char *shared_memory_base_name, *mysqld_unix_port; extern my_bool opt_enable_shared_memory; @@ -1255,6 +1274,8 @@ void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table); void mysql_lock_abort(THD *thd, TABLE *table); bool mysql_lock_abort_for_thread(THD *thd, TABLE *table); MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b); +TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle, + TABLE_LIST *haystack); bool lock_global_read_lock(THD *thd); void unlock_global_read_lock(THD *thd); bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, @@ -1295,7 +1316,6 @@ int openfrm(THD *thd, const char *name,const char *alias,uint filestat, int readfrm(const char *name, const void** data, uint* length); int writefrm(const char* name, const void* data, uint len); int closefrm(TABLE *table); -db_type get_table_type(THD *thd, const char *name); int read_string(File file, gptr *to, uint length); void free_blobs(TABLE *table); int set_zone(int nr,int min_zone,int max_zone); @@ -1348,7 +1368,7 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week); uint calc_week(TIME *l_time, uint week_behaviour, uint *year); void find_date(char *pos,uint *vek,uint flag); TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end); -TYPELIB *typelib(List<String> &strings); +TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings); ulong get_form_pos(File file, uchar *head, TYPELIB *save_names); ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames, const char *newname); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1d1649edc94..1f32a8285d1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -371,7 +371,7 @@ my_bool opt_log_slow_admin_statements= 0; my_bool lower_case_file_system= 0; my_bool opt_large_pages= 0; uint opt_large_page_size= 0; -my_bool opt_old_style_user_limits= 0, trust_routine_creators= 0; +my_bool opt_old_style_user_limits= 0, trust_function_creators= 0; /* True if there is at least one per-hour limit for some user, so we should check them before each query (and possibly reset counters when hour is @@ -385,6 +385,7 @@ my_bool sp_automatic_privileges= 1; static bool calling_initgroups= FALSE; /* Used in SIGSEGV handler. */ #endif uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options; +uint mysqld_port_timeout; uint delay_key_write_options, protocol_version; uint lower_case_table_names; uint tc_heuristic_recover= 0; @@ -496,6 +497,8 @@ pthread_cond_t COND_refresh,COND_thread_count; pthread_t signal_thread; pthread_attr_t connection_attrib; +File_parser_dummy_hook file_parser_dummy_hook; + /* replication parameters, if master_host is not NULL, we are a slave */ uint master_port= MYSQL_PORT, master_connect_retry = 60; uint report_port= MYSQL_PORT; @@ -564,7 +567,7 @@ bool mysqld_embedded=1; static const char* default_dbug_option; #endif #ifdef HAVE_LIBWRAP -char *libwrapName= NULL; +const char *libwrapName= NULL; #endif #ifdef HAVE_QUERY_CACHE static ulong query_cache_limit= 0; @@ -1194,6 +1197,7 @@ static void clean_up_mutexes() (void) rwlock_destroy(&LOCK_sys_init_slave); (void) pthread_mutex_destroy(&LOCK_global_system_variables); (void) pthread_mutex_destroy(&LOCK_global_read_lock); + (void) pthread_mutex_destroy(&LOCK_uuid_generator); (void) pthread_cond_destroy(&COND_thread_count); (void) pthread_cond_destroy(&COND_refresh); (void) pthread_cond_destroy(&COND_thread_cache); @@ -1354,7 +1358,12 @@ static void network_init(void) struct sockaddr_un UNIXaddr; #endif int arg=1; + int ret; + uint waited; + uint this_wait; + uint retry; DBUG_ENTER("server_init"); + LINT_INIT(ret); set_ports(); @@ -1380,8 +1389,26 @@ static void network_init(void) */ (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg)); #endif /* __WIN__ */ - if (bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr), - sizeof(IPaddr)) < 0) + /* + Sometimes the port is not released fast enough when stopping and + restarting the server. This happens quite often with the test suite + on busy Linux systems. Retry to bind the address at these intervals: + Sleep intervals: 1, 2, 4, 6, 9, 13, 17, 22, ... + Retry at second: 1, 3, 7, 13, 22, 35, 52, 74, ... + Limit the sequence by mysqld_port_timeout (set --port-open-timeout=#). + */ + for (waited= 0, retry= 1; ; retry++, waited+= this_wait) + { + if (((ret= bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr), + sizeof(IPaddr))) >= 0) || + (socket_errno != SOCKET_EADDRINUSE) || + (waited >= mysqld_port_timeout)) + break; + sql_print_information("Retrying bind on TCP/IP port %u", mysqld_port); + this_wait= retry * retry / 3 + 1; + sleep(this_wait); + } + if (ret < 0) { DBUG_PRINT("error",("Got error: %d from bind",socket_errno)); sql_perror("Can't start server: Bind on TCP/IP port"); @@ -1586,6 +1613,7 @@ void end_thread(THD *thd, bool put_in_cache) wake_thread--; thd=thread_cache.get(); thd->real_id=pthread_self(); + thd->thread_stack= (char*) &thd; // For store_globals (void) thd->store_globals(); thd->thr_create_time= time(NULL); threads.append(thd); @@ -2860,7 +2888,14 @@ static void init_ssl() opt_ssl_cipher); DBUG_PRINT("info",("ssl_acceptor_fd: 0x%lx", (long) ssl_acceptor_fd)); if (!ssl_acceptor_fd) + { opt_use_ssl = 0; + have_openssl= SHOW_OPTION_DISABLED; + } + } + else + { + have_openssl= SHOW_OPTION_DISABLED; } if (des_key_file) load_des_key_file(des_key_file); @@ -3026,6 +3061,23 @@ server."); sql_print_error("Can't init databases"); unireg_abort(1); } + + /* + Check that the default storage engine is actually available. + */ + if (!ha_storage_engine_is_enabled((enum db_type) + global_system_variables.table_type)) + { + if (!opt_bootstrap) + { + sql_print_error("Default storage engine (%s) is not available", + ha_get_storage_engine((enum db_type) + global_system_variables.table_type)); + unireg_abort(1); + } + global_system_variables.table_type= DB_TYPE_MYISAM; + } + tc_log= (total_ha_2pc > 1 ? (opt_bin_log ? (TC_LOG *) &mysql_bin_log : (TC_LOG *) &tc_log_mmap) : @@ -4407,7 +4459,7 @@ enum options_mysqld OPT_INNODB_FAST_SHUTDOWN, OPT_INNODB_FILE_PER_TABLE, OPT_CRASH_BINLOG_INNODB, OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG, - OPT_LOG_BIN_TRUST_ROUTINE_CREATORS, + OPT_LOG_BIN_TRUST_FUNCTION_CREATORS, OPT_SAFE_SHOW_DB, OPT_INNODB_SAFE_BINLOG, OPT_INNODB, OPT_ISAM, OPT_ENGINE_CONDITION_PUSHDOWN, @@ -4518,12 +4570,14 @@ enum options_mysqld OPT_OPTIMIZER_PRUNE_LEVEL, OPT_UPDATABLE_VIEWS_WITH_LIMIT, OPT_SP_AUTOMATIC_PRIVILEGES, + OPT_MAX_SP_RECURSION_DEPTH, OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET, OPT_ENABLE_LARGE_PAGES, OPT_TIMED_MUTEXES, OPT_OLD_STYLE_USER_LIMITS, OPT_LOG_SLOW_ADMIN_STATEMENTS, - OPT_TABLE_LOCK_WAIT_TIMEOUT + OPT_TABLE_LOCK_WAIT_TIMEOUT, + OPT_PORT_OPEN_TIMEOUT }; @@ -4608,7 +4662,7 @@ Disable with --skip-bdb (will save memory).", {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-set-client-handshake", OPT_CHARACTER_SET_CLIENT_HANDSHAKE, - "Don't use client side character set value sent during handshake.", + "Don't ignore client side character set value sent during handshake.", (gptr*) &opt_character_set_client_handshake, (gptr*) &opt_character_set_client_handshake, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, @@ -4832,16 +4886,27 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, "File that holds the names for last binary log files.", (gptr*) &opt_binlog_index_name, (gptr*) &opt_binlog_index_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#ifndef TO_BE_REMOVED_IN_5_1_OR_6_0 + /* + In 5.0.6 we introduced the below option, then in 5.0.16 we renamed it to + log-bin-trust-function-creators but kept also the old name for + compatibility; the behaviour was also changed to apply only to functions + (and triggers). In a future release this old name could be removed. + */ + {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS, + "(deprecated) Use log-bin-trust-function-creators.", + (gptr*) &trust_function_creators, (gptr*) &trust_function_creators, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, +#endif /* This option starts with "log-bin" to emphasize that it is specific of - binary logging. Hopefully in 5.1 nobody will need it anymore, when we have - row-level binlog. + binary logging. */ - {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_ROUTINE_CREATORS, + {"log-bin-trust-function-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS, "If equal to 0 (the default), then when --log-bin is used, creation of " - "a routine is allowed only to users having the SUPER privilege and only" - "if this routine may not break binary logging", - (gptr*) &trust_routine_creators, (gptr*) &trust_routine_creators, 0, + "a function is allowed only to users having the SUPER privilege and only " + "if this function may not break binary logging.", + (gptr*) &trust_function_creators, (gptr*) &trust_function_creators, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-error", OPT_ERROR_LOG_FILE, "Error log file.", (gptr*) &log_error_file_ptr, (gptr*) &log_error_file_ptr, 0, GET_STR, @@ -5052,6 +5117,10 @@ Disable with --skip-ndbcluster (will save memory).", REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Port number to use for connection.", (gptr*) &mysqld_port, (gptr*) &mysqld_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"port-open-timeout", OPT_PORT_OPEN_TIMEOUT, + "Maximum time in seconds to wait for the port to become free. " + "(Default: no wait)", (gptr*) &mysqld_port_timeout, + (gptr*) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relay-log", OPT_RELAY_LOG, "The location and name to use for relay logs.", (gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0, @@ -5382,7 +5451,8 @@ log and this option does nothing anymore.", {"innodb_buffer_pool_size", OPT_INNODB_BUFFER_POOL_SIZE, "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", (gptr*) &innobase_buffer_pool_size, (gptr*) &innobase_buffer_pool_size, 0, - GET_LONG, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, ~0L, 0, 1024*1024L, 0}, + GET_LL, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 0, + 1024*1024L, 0}, {"innodb_concurrency_tickets", OPT_INNODB_CONCURRENCY_TICKETS, "Number of times a thread is allowed to enter InnoDB within the same \ SQL query after it has once got the ticket", @@ -5406,9 +5476,10 @@ log and this option does nothing anymore.", (gptr*) &innobase_log_buffer_size, (gptr*) &innobase_log_buffer_size, 0, GET_LONG, REQUIRED_ARG, 1024*1024L, 256*1024L, ~0L, 0, 1024, 0}, {"innodb_log_file_size", OPT_INNODB_LOG_FILE_SIZE, - "Size of each log file in a log group in megabytes.", + "Size of each log file in a log group.", (gptr*) &innobase_log_file_size, (gptr*) &innobase_log_file_size, 0, - GET_LONG, REQUIRED_ARG, 5*1024*1024L, 1*1024*1024L, ~0L, 0, 1024*1024L, 0}, + GET_LL, REQUIRED_ARG, 5*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 0, + 1024*1024L, 0}, {"innodb_log_files_in_group", OPT_INNODB_LOG_FILES_IN_GROUP, "Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.", (gptr*) &innobase_log_files_in_group, (gptr*) &innobase_log_files_in_group, @@ -5608,7 +5679,8 @@ The minimum value for this variable is 4096.", GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0}, {"myisam_stats_method", OPT_MYISAM_STATS_METHOD, "Specifies how MyISAM index statistics collection code should threat NULLs. " - "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), and \"nulls_equal\" (emulate 4.0 behavior).", + "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), " + "\"nulls_equal\" (emulate 4.0 behavior), and \"nulls_ignored\".", (gptr*) &myisam_stats_method_str, (gptr*) &myisam_stats_method_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, @@ -5699,7 +5771,7 @@ The minimum value for this variable is 4096.", (gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0}, {"read_only", OPT_READONLY, - "Make all tables readonly, with the exception for replication (slave) threads and users with the SUPER privilege", + "Make all non-temporary tables read-only, with the exception for replication (slave) threads and users with the SUPER privilege", (gptr*) &opt_readonly, (gptr*) &opt_readonly, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, @@ -5719,6 +5791,11 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.read_buff_size, (gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0}, + {"max_sp_recursion_depth", OPT_MAX_SP_RECURSION_DEPTH, + "Maximum stored procedure recursion depth. (discussed with docs).", + (gptr*) &global_system_variables.max_sp_recursion_depth, + (gptr*) &max_system_variables.max_sp_recursion_depth, 0, GET_ULONG, + OPT_ARG, 0, 0, 255, 0, 1, 0 }, #ifdef HAVE_REPLICATION {"relay_log_purge", OPT_RELAY_LOG_PURGE, "0 = do not purge relay logs. 1 = purge them as soon as they are no more needed.", @@ -5951,6 +6028,7 @@ struct show_var_st status_vars[]= { {"Com_xa_recover", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]),SHOW_LONG_STATUS}, {"Com_xa_rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),SHOW_LONG_STATUS}, {"Com_xa_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),SHOW_LONG_STATUS}, + {"Compression", (char*) 0, SHOW_NET_COMPRESSION}, {"Connections", (char*) &thread_id, SHOW_LONG_CONST}, {"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS}, {"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG}, @@ -6274,7 +6352,7 @@ static void mysql_init_variables(void) #else have_example_db= SHOW_OPTION_NO; #endif -#ifdef HAVE_ARCHIVE_DB +#if defined(HAVE_ARCHIVE_DB) have_archive_db= SHOW_OPTION_YES; #else have_archive_db= SHOW_OPTION_NO; @@ -6309,7 +6387,7 @@ static void mysql_init_variables(void) #else have_openssl=SHOW_OPTION_NO; #endif -#if !defined(HAVE_REALPATH) || defined(HAVE_BROKEN_REALPATH) +#ifdef HAVE_BROKEN_REALPATH have_symlink=SHOW_OPTION_NO; #else have_symlink=SHOW_OPTION_YES; @@ -6863,14 +6941,28 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } case OPT_MYISAM_STATS_METHOD: { - myisam_stats_method_str= argument; + ulong method_conv; int method; + LINT_INIT(method_conv); + + myisam_stats_method_str= argument; if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0) { fprintf(stderr, "Invalid value of myisam_stats_method: %s.\n", argument); exit(1); } - global_system_variables.myisam_stats_method= method-1; + switch (method-1) { + case 0: + method_conv= MI_STATS_METHOD_NULLS_EQUAL; + break; + case 1: + method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; + break; + case 2: + method_conv= MI_STATS_METHOD_IGNORE_NULLS; + break; + } + global_system_variables.myisam_stats_method= method_conv; break; } case OPT_SQL_MODE: @@ -6978,22 +7070,6 @@ static void get_options(int argc,char **argv) !opt_slow_log) sql_print_warning("options --log-slow-admin-statements and --log-queries-not-using-indexes have no effect if --log-slow-queries is not set"); - /* - Check that the default storage engine is actually available. - */ - if (!ha_storage_engine_is_enabled((enum db_type) - global_system_variables.table_type)) - { - if (!opt_bootstrap) - { - sql_print_error("Default storage engine (%s) is not available", - ha_get_storage_engine((enum db_type) - global_system_variables.table_type)); - exit(1); - } - global_system_variables.table_type= DB_TYPE_MYISAM; - } - if (argc > 0) { fprintf(stderr, "%s: Too many arguments (first extra is '%s').\nUse --help to get a list of available options\n", my_progname, *argv); @@ -7006,7 +7082,7 @@ static void get_options(int argc,char **argv) usage(); exit(0); } -#if !defined(HAVE_REALPATH) || defined(HAVE_BROKEN_REALPATH) +#if defined(HAVE_BROKEN_REALPATH) my_use_symdir=0; my_disable_symlinks=1; have_symlink=SHOW_OPTION_NO; @@ -7155,6 +7231,7 @@ static void fix_paths(void) CHARSET_DIR, NullS); } (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff); + convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS); charsets_dir=mysql_charsets_dir; if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ff2b14a27ee..7c5274eb5eb 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -931,7 +931,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler) } THD *thd= current_thd; - if (!(file= get_new_handler(head, head->s->db_type))) + if (!(file= get_new_handler(head, thd->mem_root, head->s->db_type))) goto failure; DBUG_PRINT("info", ("Allocated new handler %p", file)); if (file->ha_open(head->s->path, head->db_stat, HA_OPEN_IGNORE_IF_LOCKED)) @@ -3136,10 +3136,10 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, /* F=F-covered by first(I) */ bitmap_union(&covered_fields, &(*ror_scan_mark)->covered_fields); all_covered= bitmap_is_subset(¶m->needed_fields, &covered_fields); - } while (!all_covered && (++ror_scan_mark < ror_scans_end)); - - if (!all_covered) - DBUG_RETURN(NULL); /* should not happen actually */ + } while ((++ror_scan_mark < ror_scans_end) && !all_covered); + + if (!all_covered || (ror_scan_mark - tree->ror_scans) == 1) + DBUG_RETURN(NULL); /* Ok, [tree->ror_scans .. ror_scan) holds covering index_intersection with @@ -3172,6 +3172,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, trp->is_covering= TRUE; trp->read_cost= total_cost; trp->records= records; + trp->cpk_scan= NULL; DBUG_PRINT("info", ("Returning covering ROR-intersect plan: cost %g, records %lu", @@ -3776,6 +3777,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, SEL_ARG *tree= 0; MEM_ROOT *alloc= param->mem_root; char *str; + ulong orig_sql_mode; DBUG_ENTER("get_mm_leaf"); /* @@ -3921,13 +3923,20 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, value->result_type() != STRING_RESULT && field->cmp_type() != value->result_type()) goto end; - + /* For comparison purposes allow invalid dates like 2000-01-32 */ + orig_sql_mode= field->table->in_use->variables.sql_mode; + if (value->real_item()->type() == Item::STRING_ITEM && + (field->type() == FIELD_TYPE_DATE || + field->type() == FIELD_TYPE_DATETIME)) + field->table->in_use->variables.sql_mode|= MODE_INVALID_DATES; if (value->save_in_field_no_warnings(field, 1) < 0) { + field->table->in_use->variables.sql_mode= orig_sql_mode; /* This happens when we try to insert a NULL field in a not null column */ tree= &null_element; // cmp with NULL is never TRUE goto end; } + field->table->in_use->variables.sql_mode= orig_sql_mode; str= (char*) alloc_root(alloc, key_part->store_length+1); if (!str) goto end; @@ -5729,6 +5738,7 @@ bool QUICK_ROR_UNION_SELECT::check_if_keys_used(List<Item> *fields) /* Create quick select from ref/ref_or_null scan. + SYNOPSIS get_quick_select_for_ref() thd Thread handle @@ -5748,14 +5758,24 @@ bool QUICK_ROR_UNION_SELECT::check_if_keys_used(List<Item> *fields) QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref, ha_rows records) { - MEM_ROOT *old_root= thd->mem_root; - /* The following call may change thd->mem_root */ - QUICK_RANGE_SELECT *quick= new QUICK_RANGE_SELECT(thd, table, ref->key, 0); + MEM_ROOT *old_root, *alloc; + QUICK_RANGE_SELECT *quick; KEY *key_info = &table->key_info[ref->key]; KEY_PART *key_part; QUICK_RANGE *range; uint part; + old_root= thd->mem_root; + /* The following call may change thd->mem_root */ + quick= new QUICK_RANGE_SELECT(thd, table, ref->key, 0); + /* save mem_root set by QUICK_RANGE_SELECT constructor */ + alloc= thd->mem_root; + /* + return back default mem_root (thd->mem_root) changed by + QUICK_RANGE_SELECT constructor + */ + thd->mem_root= old_root; + if (!quick) return 0; /* no ranges found */ if (quick->init()) @@ -5766,7 +5786,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, quick->records= records; if (cp_buffer_from_ref(thd,ref) && thd->is_fatal_error || - !(range= new QUICK_RANGE())) + !(range= new(alloc) QUICK_RANGE())) goto err; // out of memory range->min_key=range->max_key=(char*) ref->key_buff; @@ -5801,20 +5821,20 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, QUICK_RANGE *null_range; *ref->null_ref_key= 1; // Set null byte then create a range - if (!(null_range= new QUICK_RANGE((char*)ref->key_buff, ref->key_length, - (char*)ref->key_buff, ref->key_length, - EQ_RANGE))) + if (!(null_range= new (alloc) QUICK_RANGE((char*)ref->key_buff, + ref->key_length, + (char*)ref->key_buff, + ref->key_length, + EQ_RANGE))) goto err; *ref->null_ref_key= 0; // Clear null byte if (insert_dynamic(&quick->ranges,(gptr)&null_range)) goto err; } - thd->mem_root= old_root; return quick; err: - thd->mem_root= old_root; delete quick; return 0; } @@ -6676,7 +6696,7 @@ void QUICK_INDEX_MERGE_SELECT::add_info_string(String *str) QUICK_RANGE_SELECT *quick; bool first= TRUE; List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); - str->append("sort_union("); + str->append(STRING_WITH_LEN("sort_union(")); while ((quick= it++)) { if (!first) @@ -6698,7 +6718,7 @@ void QUICK_ROR_INTERSECT_SELECT::add_info_string(String *str) bool first= TRUE; QUICK_RANGE_SELECT *quick; List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); - str->append("intersect("); + str->append(STRING_WITH_LEN("intersect(")); while ((quick= it++)) { KEY *key_info= head->key_info + quick->index; @@ -6722,7 +6742,7 @@ void QUICK_ROR_UNION_SELECT::add_info_string(String *str) bool first= TRUE; QUICK_SELECT_I *quick; List_iterator_fast<QUICK_SELECT_I> it(quick_selects); - str->append("union("); + str->append(STRING_WITH_LEN("union(")); while ((quick= it++)) { if (!first) @@ -7182,6 +7202,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) { select_items_it.rewind(); cur_used_key_parts.clear_all(); + uint max_key_part= 0; while ((item= select_items_it++)) { item_field= (Item_field*) item; /* (SA5) already checked above. */ @@ -7199,7 +7220,19 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) cur_group_prefix_len+= cur_part->store_length; cur_used_key_parts.set_bit(key_part_nr); ++cur_group_key_parts; + max_key_part= max(max_key_part,key_part_nr); } + /* + Check that used key parts forms a prefix of the index. + To check this we compare bits in all_parts and cur_parts. + all_parts have all bits set from 0 to (max_key_part-1). + cur_parts have bits set for only used keyparts. + */ + ulonglong all_parts, cur_parts; + all_parts= (1<<max_key_part) - 1; + cur_parts= cur_used_key_parts.to_ulonglong() >> 1; + if (all_parts != cur_parts) + goto next_index; } else DBUG_ASSERT(FALSE); @@ -8853,7 +8886,7 @@ static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map, } } if (!tmp.length()) - tmp.append("(empty)"); + tmp.append(STRING_WITH_LEN("(empty)")); DBUG_PRINT("info", ("SEL_TREE %p (%s) scans:%s", tree, msg, tmp.ptr())); @@ -8879,7 +8912,7 @@ static void print_ror_scans_arr(TABLE *table, const char *msg, tmp.append(table->key_info[(*start)->keynr].name); } if (!tmp.length()) - tmp.append("(empty)"); + tmp.append(STRING_WITH_LEN("(empty)")); DBUG_PRINT("info", ("ROR key scans (%s): %s", msg, tmp.ptr())); DBUG_VOID_RETURN; } diff --git a/sql/parse_file.cc b/sql/parse_file.cc index d3e5645bafc..041b770ac0b 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -50,23 +50,23 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s) */ switch(*ptr) { case '\\': // escape character - if (my_b_append(file, (const byte *)"\\\\", 2)) + if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\\\"))) return TRUE; break; case '\n': // parameter value delimiter - if (my_b_append(file, (const byte *)"\\n", 2)) + if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\n"))) return TRUE; break; case '\0': // problem for some string processing utilities - if (my_b_append(file, (const byte *)"\\0", 2)) + if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\0"))) return TRUE; break; case 26: // problem for windows utilities (Ctrl-Z) - if (my_b_append(file, (const byte *)"\\z", 2)) + if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\z"))) return TRUE; break; case '\'': // list of string delimiter - if (my_b_append(file, (const byte *)"\\\'", 2)) + if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\\'"))) return TRUE; break; default: @@ -155,10 +155,10 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, while ((str= it++)) { // We need ' ' after string to detect list continuation - if ((!first && my_b_append(file, (const byte *)" ", 1)) || - my_b_append(file, (const byte *)"\'", 1) || + if ((!first && my_b_append(file, (const byte *)STRING_WITH_LEN(" "))) || + my_b_append(file, (const byte *)STRING_WITH_LEN("\'")) || write_escaped_string(file, str) || - my_b_append(file, (const byte *)"\'", 1)) + my_b_append(file, (const byte *)STRING_WITH_LEN("\'"))) { DBUG_RETURN(TRUE); } @@ -176,7 +176,7 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, { num.set(*val, &my_charset_bin); // We need ' ' after string to detect list continuation - if ((!first && my_b_append(file, (const byte *)" ", 1)) || + if ((!first && my_b_append(file, (const byte *)STRING_WITH_LEN(" "))) || my_b_append(file, (const byte *)num.ptr(), num.length())) { DBUG_RETURN(TRUE); @@ -242,9 +242,9 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, goto err_w_file; // write header (file signature) - if (my_b_append(&file, (const byte *)"TYPE=", 5) || + if (my_b_append(&file, (const byte *)STRING_WITH_LEN("TYPE=")) || my_b_append(&file, (const byte *)type->str, type->length) || - my_b_append(&file, (const byte *)"\n", 1)) + my_b_append(&file, (const byte *)STRING_WITH_LEN("\n"))) goto err_w_file; // write parameters to temporary file @@ -252,9 +252,9 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, { if (my_b_append(&file, (const byte *)param->name.str, param->name.length) || - my_b_append(&file, (const byte *)"=", 1) || + my_b_append(&file, (const byte *)STRING_WITH_LEN("=")) || write_parameter(&file, base, param, &old_version) || - my_b_append(&file, (const byte *)"\n", 1)) + my_b_append(&file, (const byte *)STRING_WITH_LEN("\n"))) goto err_w_cache; } @@ -664,6 +664,61 @@ parse_quoted_escaped_string(char *ptr, char *end, /* + Parser for FILE_OPTIONS_ULLLIST type value. + + SYNOPSIS + get_file_options_ulllist() + ptr [in/out] pointer to parameter + end [in] end of the configuration + line [in] pointer to the line begining + base [in] base address for parameter writing (structure + like TABLE) + parameter [in] description + mem_root [in] MEM_ROOT for parameters allocation +*/ + +bool get_file_options_ulllist(char *&ptr, char *end, char *line, + gptr base, File_option *parameter, + MEM_ROOT *mem_root) +{ + List<ulonglong> *nlist= (List<ulonglong>*)(base + parameter->offset); + ulonglong *num; + nlist->empty(); + // list parsing + while (ptr < end) + { + int not_used; + char *num_end= end; + if (!(num= (ulonglong*)alloc_root(mem_root, sizeof(ulonglong))) || + nlist->push_back(num, mem_root)) + goto nlist_err; + *num= my_strtoll10(ptr, &num_end, ¬_used); + ptr= num_end; + switch (*ptr) { + case '\n': + goto end_of_nlist; + case ' ': + // we cant go over buffer bounds, because we have \0 at the end + ptr++; + break; + default: + goto nlist_err_w_message; + } + } + +end_of_nlist: + if (*(ptr++) != '\n') + goto nlist_err; + return FALSE; + +nlist_err_w_message: + my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0), parameter->name.str, line); +nlist_err: + return TRUE; +} + + +/* parse parameters SYNOPSIS @@ -673,6 +728,8 @@ parse_quoted_escaped_string(char *ptr, char *end, mem_root MEM_ROOT for parameters allocation parameters parameters description required number of required parameters in above list + hook hook called for unknown keys + hook_data some data specific for the hook RETURN FALSE - OK @@ -681,15 +738,15 @@ parse_quoted_escaped_string(char *ptr, char *end, my_bool File_parser::parse(gptr base, MEM_ROOT *mem_root, - struct File_option *parameters, uint required) + struct File_option *parameters, uint required, + Unknown_key_hook *hook) { uint first_param= 0, found= 0; - register char *ptr= start; + char *ptr= start; char *eol; LEX_STRING *str; List<LEX_STRING> *list; ulonglong *num; - List<ulonglong> *nlist; DBUG_ENTER("File_parser::parse"); while (ptr < end && found < required) @@ -829,58 +886,64 @@ list_err: DBUG_RETURN(TRUE); } case FILE_OPTIONS_ULLLIST: - { - nlist= (List<ulonglong>*)(base + parameter->offset); - nlist->empty(); - // list parsing - while (ptr < end) - { - int not_used; - char *num_end= end; - if (!(num= (ulonglong*)alloc_root(mem_root, sizeof(ulonglong))) || - nlist->push_back(num, mem_root)) - goto nlist_err; - *num= my_strtoll10(ptr, &num_end, ¬_used); - ptr= num_end; - switch (*ptr) { - case '\n': - goto end_of_nlist; - case ' ': - // we cant go over buffer bounds, because we have \0 at the end - ptr++; - break; - default: - goto nlist_err_w_message; - } - } - -end_of_nlist: - if (*(ptr++) != '\n') - goto nlist_err; + if (get_file_options_ulllist(ptr, end, line, base, + parameter, mem_root)) + DBUG_RETURN(TRUE); break; - -nlist_err_w_message: - my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0), - parameter->name.str, line); -nlist_err: - DBUG_RETURN(TRUE); - - } default: DBUG_ASSERT(0); // never should happened } } else { - // skip unknown parameter - if (!(ptr= strchr(ptr, '\n'))) - { - my_error(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER, MYF(0), line); - DBUG_RETURN(TRUE); - } - ptr++; + ptr= line; + if (hook->process_unknown_string(ptr, base, mem_root, end)) + { + DBUG_RETURN(TRUE); + } + // skip unknown parameter + if (!(ptr= strchr(ptr, '\n'))) + { + my_error(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER, MYF(0), line); + DBUG_RETURN(TRUE); + } + ptr++; } } } DBUG_RETURN(FALSE); } + + +/* + Dummy unknown key hook + + SYNOPSIS + File_parser_dummy_hook::process_unknown_string() + unknown_key [in/out] reference on the line with unknown + parameter and the parsing point + base [in] base address for parameter writing (structure like + TABLE) + mem_root [in] MEM_ROOT for parameters allocation + end [in] the end of the configuration + + NOTE + This hook used to catch no longer supported keys and process them for + backward compatibility, but it will not slow down processing of modern + format files. + This hook does nothing except debug output. + + RETURN + FALSE OK + TRUE Error +*/ + +bool +File_parser_dummy_hook::process_unknown_string(char *&unknown_key, + gptr base, MEM_ROOT *mem_root, + char *end) +{ + DBUG_ENTER("file_parser_dummy_hook::process_unknown_string"); + DBUG_PRINT("info", ("Unknown key: '%60s'", unknown_key)); + DBUG_RETURN(FALSE); +} diff --git a/sql/parse_file.h b/sql/parse_file.h index b4199e4fbf1..afa88da2ead 100644 --- a/sql/parse_file.h +++ b/sql/parse_file.h @@ -40,6 +40,35 @@ struct File_option file_opt_type type; /* Option type */ }; + +/* + This hook used to catch no longer supported keys and process them for + backward compatibility. +*/ + +class Unknown_key_hook +{ +public: + virtual bool process_unknown_string(char *&unknown_key, gptr base, + MEM_ROOT *mem_root, char *end)= 0; +}; + + +/* Dummy hook for parsers which do not need hook for unknown keys */ + +class File_parser_dummy_hook: public Unknown_key_hook +{ +public: + virtual bool process_unknown_string(char *&unknown_key, gptr base, + MEM_ROOT *mem_root, char *end); +}; + +extern File_parser_dummy_hook file_parser_dummy_hook; + +bool get_file_options_ulllist(char *&ptr, char *end, char *line, + gptr base, File_option *parameter, + MEM_ROOT *mem_root); + class File_parser; File_parser *sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root, bool bad_format_errors); @@ -64,7 +93,8 @@ public: my_bool ok() { return content_ok; } LEX_STRING *type() { return &file_type; } my_bool parse(gptr base, MEM_ROOT *mem_root, - struct File_option *parameters, uint required); + struct File_option *parameters, uint required, + Unknown_key_hook *hook); friend File_parser *sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root, diff --git a/sql/protocol.cc b/sql/protocol.cc index 8c3e5a62820..0a1b42f5236 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -498,7 +498,7 @@ void Protocol::init(THD *thd_arg) thd=thd_arg; packet= &thd->packet; convert= &thd->convert_buffer; -#ifndef DEBUG_OFF +#ifndef DBUG_OFF field_types= 0; #endif } @@ -551,7 +551,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags) (void) my_net_write(&thd->net, buff,(uint) (pos-buff)); } -#ifndef DEBUG_OFF +#ifndef DBUG_OFF field_types= (enum_field_types*) thd->alloc(sizeof(field_types) * list->elements); uint count= 0; @@ -572,7 +572,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags) if (thd->client_capabilities & CLIENT_PROTOCOL_41) { - if (prot.store("def", 3, cs, thd_charset) || + if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) || prot.store(field.db_name, (uint) strlen(field.db_name), cs, thd_charset) || prot.store(field.table_name, (uint) strlen(field.table_name), @@ -648,7 +648,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags) item->send(&prot, &tmp); // Send default value if (prot.write()) break; /* purecov: inspected */ -#ifndef DEBUG_OFF +#ifndef DBUG_OFF field_types[count++]= field.type; #endif } @@ -732,14 +732,14 @@ bool Protocol::store(I_List<i_string>* str_list) void Protocol_simple::prepare_for_resend() { packet->length(0); -#ifndef DEBUG_OFF +#ifndef DBUG_OFF field_pos= 0; #endif } bool Protocol_simple::store_null() { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF field_pos++; #endif char buff[1]; @@ -773,7 +773,7 @@ bool Protocol::store_string_aux(const char *from, uint length, bool Protocol_simple::store(const char *from, uint length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_DECIMAL || field_types[field_pos] == MYSQL_TYPE_BIT || @@ -790,7 +790,7 @@ bool Protocol_simple::store(const char *from, uint length, CHARSET_INFO *fromcs) { CHARSET_INFO *tocs= this->thd->variables.character_set_results; -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_DECIMAL || field_types[field_pos] == MYSQL_TYPE_BIT || @@ -805,7 +805,7 @@ bool Protocol_simple::store(const char *from, uint length, bool Protocol_simple::store_tiny(longlong from) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY); field_pos++; #endif @@ -817,7 +817,7 @@ bool Protocol_simple::store_tiny(longlong from) bool Protocol_simple::store_short(longlong from) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_YEAR || field_types[field_pos] == MYSQL_TYPE_SHORT); @@ -831,7 +831,7 @@ bool Protocol_simple::store_short(longlong from) bool Protocol_simple::store_long(longlong from) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_INT24 || field_types[field_pos] == MYSQL_TYPE_LONG); @@ -845,7 +845,7 @@ bool Protocol_simple::store_long(longlong from) bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_LONGLONG); field_pos++; @@ -860,7 +860,7 @@ bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag) bool Protocol_simple::store_decimal(const my_decimal *d) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL); field_pos++; @@ -874,7 +874,7 @@ bool Protocol_simple::store_decimal(const my_decimal *d) bool Protocol_simple::store(float from, uint32 decimals, String *buffer) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_FLOAT); field_pos++; @@ -886,7 +886,7 @@ bool Protocol_simple::store(float from, uint32 decimals, String *buffer) bool Protocol_simple::store(double from, uint32 decimals, String *buffer) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_DOUBLE); field_pos++; @@ -900,7 +900,7 @@ bool Protocol_simple::store(Field *field) { if (field->is_null()) return store_null(); -#ifndef DEBUG_OFF +#ifndef DBUG_OFF field_pos++; #endif char buff[MAX_FIELD_WIDTH]; @@ -921,7 +921,7 @@ bool Protocol_simple::store(Field *field) bool Protocol_simple::store(TIME *tm) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_DATETIME || field_types[field_pos] == MYSQL_TYPE_TIMESTAMP); @@ -944,7 +944,7 @@ bool Protocol_simple::store(TIME *tm) bool Protocol_simple::store_date(TIME *tm) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_DATE); field_pos++; @@ -963,7 +963,7 @@ bool Protocol_simple::store_date(TIME *tm) bool Protocol_simple::store_time(TIME *tm) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TIME); field_pos++; @@ -1088,7 +1088,7 @@ bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag) bool Protocol_prep::store_decimal(const my_decimal *d) { -#ifndef DEBUG_OFF +#ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL); field_pos++; diff --git a/sql/protocol.h b/sql/protocol.h index c00bbba4cc9..8d9da5774b2 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -31,7 +31,7 @@ protected: String *packet; String *convert; uint field_pos; -#ifndef DEBUG_OFF +#ifndef DBUG_OFF enum enum_field_types *field_types; #endif uint field_count; diff --git a/sql/records.cc b/sql/records.cc index 52c3dbdb798..b352f9f395a 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -28,11 +28,10 @@ static int rr_from_pointers(READ_RECORD *info); static int rr_from_cache(READ_RECORD *info); static int init_rr_cache(THD *thd, READ_RECORD *info); static int rr_cmp(uchar *a,uchar *b); - +static int rr_index_first(READ_RECORD *info); static int rr_index(READ_RECORD *info); - /* Initialize READ_RECORD structure to perform full index scan @@ -58,26 +57,19 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, bool print_error, uint idx) { bzero((char*) info,sizeof(*info)); - info->thd=thd; - info->table=table; - info->file= table->file; - info->forms= &info->table; /* Only one table */ - + info->table= table; + info->file= table->file; info->record= table->record[0]; - info->ref_length= table->file->ref_length; + info->print_error= print_error; - info->select=NULL; - info->print_error=print_error; - info->ignore_not_found_rows= 0; table->status=0; /* And it's always found */ - if (!table->file->inited) { table->file->ha_index_init(idx); table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY); } - info->read_record= rr_index; - info->first= TRUE; + /* read_record will be changed to rr_index in rr_index_first */ + info->read_record= rr_index_first; } @@ -209,6 +201,21 @@ void end_read_record(READ_RECORD *info) } } +static int rr_handle_error(READ_RECORD *info, int error) +{ + if (error == HA_ERR_END_OF_FILE) + error= -1; + else + { + if (info->print_error) + info->table->file->print_error(error, MYF(0)); + if (error < 0) // Fix negative BDB errno + error= 1; + } + return error; +} + + /* Read a record from head-database */ static int rr_quick(READ_RECORD *info) @@ -223,15 +230,7 @@ static int rr_quick(READ_RECORD *info) } if (tmp != HA_ERR_RECORD_DELETED) { - if (tmp == HA_ERR_END_OF_FILE) - tmp= -1; - else - { - if (info->print_error) - info->file->print_error(tmp,MYF(0)); - if (tmp < 0) // Fix negative BDB errno - tmp=1; - } + tmp= rr_handle_error(info, tmp); break; } } @@ -240,7 +239,31 @@ static int rr_quick(READ_RECORD *info) /* - A READ_RECORD::read_record implementation that reads index sequentially + Reads first row in an index scan + + SYNOPSIS + rr_index_first() + info Scan info + + RETURN + 0 Ok + -1 End of records + 1 Error +*/ + + +static int rr_index_first(READ_RECORD *info) +{ + int tmp= info->file->index_first(info->record); + info->read_record= rr_index; + if (tmp) + tmp= rr_handle_error(info, tmp); + return tmp; +} + + +/* + Reads index sequentially after first row SYNOPSIS rr_index() @@ -256,43 +279,16 @@ static int rr_quick(READ_RECORD *info) 1 Error */ + static int rr_index(READ_RECORD *info) { - int tmp; - while (1) - { - if (info->first) - { - info->first= FALSE; - tmp= info->file->index_first(info->record); - } - else - tmp= info->file->index_next(info->record); - - if (!tmp) - break; - if (info->thd->killed) - { - my_error(ER_SERVER_SHUTDOWN,MYF(0)); - return 1; - } - if (tmp != HA_ERR_RECORD_DELETED) - { - if (tmp == HA_ERR_END_OF_FILE) - tmp= -1; - else - { - if (info->print_error) - info->table->file->print_error(tmp,MYF(0)); - if (tmp < 0) // Fix negative BDB errno - tmp=1; - } - break; - } - } + int tmp= info->file->index_next(info->record); + if (tmp) + tmp= rr_handle_error(info, tmp); return tmp; } + static int rr_sequential(READ_RECORD *info) { int tmp; @@ -303,17 +299,13 @@ static int rr_sequential(READ_RECORD *info) info->thd->send_kill_message(); return 1; } + /* + rnd_next can return RECORD_DELETED for MyISAM when one thread is + reading and another deleting without locks. + */ if (tmp != HA_ERR_RECORD_DELETED) { - if (tmp == HA_ERR_END_OF_FILE) - tmp= -1; - else - { - if (info->print_error) - info->table->file->print_error(tmp,MYF(0)); - if (tmp < 0) // Fix negative BDB errno - tmp=1; - } + tmp= rr_handle_error(info, tmp); break; } } @@ -324,23 +316,18 @@ static int rr_sequential(READ_RECORD *info) static int rr_from_tempfile(READ_RECORD *info) { int tmp; -tryNext: - if (my_b_read(info->io_cache,info->ref_pos,info->ref_length)) - return -1; /* End of file */ - if ((tmp=info->file->rnd_pos(info->record,info->ref_pos))) + for (;;) { - if (tmp == HA_ERR_END_OF_FILE) - tmp= -1; - else if (tmp == HA_ERR_RECORD_DELETED || - (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows)) - goto tryNext; - else - { - if (info->print_error) - info->file->print_error(tmp,MYF(0)); - if (tmp < 0) // Fix negative BDB errno - tmp=1; - } + if (my_b_read(info->io_cache,info->ref_pos,info->ref_length)) + return -1; /* End of file */ + if (!(tmp=info->file->rnd_pos(info->record,info->ref_pos))) + break; + /* The following is extremely unlikely to happen */ + if (tmp == HA_ERR_RECORD_DELETED || + (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows)) + continue; + tmp= rr_handle_error(info, tmp); + break; } return tmp; } /* rr_from_tempfile */ @@ -378,26 +365,23 @@ static int rr_from_pointers(READ_RECORD *info) { int tmp; byte *cache_pos; -tryNext: - if (info->cache_pos == info->cache_end) - return -1; /* End of file */ - cache_pos=info->cache_pos; - info->cache_pos+=info->ref_length; - if ((tmp=info->file->rnd_pos(info->record,cache_pos))) + for (;;) { - if (tmp == HA_ERR_END_OF_FILE) - tmp= -1; - else if (tmp == HA_ERR_RECORD_DELETED || - (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows)) - goto tryNext; - else - { - if (info->print_error) - info->file->print_error(tmp,MYF(0)); - if (tmp < 0) // Fix negative BDB errno - tmp=1; - } + if (info->cache_pos == info->cache_end) + return -1; /* End of file */ + cache_pos= info->cache_pos; + info->cache_pos+= info->ref_length; + + if (!(tmp=info->file->rnd_pos(info->record,cache_pos))) + break; + + /* The following is extremely unlikely to happen */ + if (tmp == HA_ERR_RECORD_DELETED || + (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows)) + continue; + tmp= rr_handle_error(info, tmp); + break; } return tmp; } diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 2f00e43deec..d76be2ec2e4 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -502,7 +502,7 @@ int update_slave_list(MYSQL* mysql, MASTER_INFO* mi) int port_ind; DBUG_ENTER("update_slave_list"); - if (mysql_real_query(mysql,"SHOW SLAVE HOSTS",16) || + if (mysql_real_query(mysql, STRING_WITH_LEN("SHOW SLAVE HOSTS")) || !(res = mysql_store_result(mysql))) { error= mysql_error(mysql); @@ -795,7 +795,7 @@ bool load_master_data(THD* thd) MYSQL_RES *db_res, **table_res, **table_res_end, **cur_table_res; uint num_dbs; - if (mysql_real_query(&mysql, "SHOW DATABASES", 14) || + if (mysql_real_query(&mysql, STRING_WITH_LEN("SHOW DATABASES")) || !(db_res = mysql_store_result(&mysql))) { my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql)); @@ -821,8 +821,9 @@ bool load_master_data(THD* thd) we wait to issue FLUSH TABLES WITH READ LOCK for as long as we can to minimize the lock time. */ - if (mysql_real_query(&mysql, "FLUSH TABLES WITH READ LOCK", 27) || - mysql_real_query(&mysql, "SHOW MASTER STATUS",18) || + if (mysql_real_query(&mysql, + STRING_WITH_LEN("FLUSH TABLES WITH READ LOCK")) || + mysql_real_query(&mysql, STRING_WITH_LEN("SHOW MASTER STATUS")) || !(master_status_res = mysql_store_result(&mysql))) { my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql)); @@ -875,7 +876,7 @@ bool load_master_data(THD* thd) } if (mysql_select_db(&mysql, db) || - mysql_real_query(&mysql, "SHOW TABLES", 11) || + mysql_real_query(&mysql, STRING_WITH_LEN("SHOW TABLES")) || !(*cur_table_res = mysql_store_result(&mysql))) { my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql)); @@ -933,7 +934,7 @@ bool load_master_data(THD* thd) mysql_free_result(master_status_res); } - if (mysql_real_query(&mysql, "UNLOCK TABLES", 13)) + if (mysql_real_query(&mysql, STRING_WITH_LEN("UNLOCK TABLES"))) { my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql)); goto err; diff --git a/sql/set_var.cc b/sql/set_var.cc index 8cf7311265c..632c37d2296 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -200,9 +200,12 @@ sys_var_key_cache_long sys_key_cache_age_threshold("key_cache_age_threshold", param_age_threshold)); sys_var_bool_ptr sys_local_infile("local_infile", &opt_local_infile); -sys_var_bool_ptr +sys_var_trust_routine_creators sys_trust_routine_creators("log_bin_trust_routine_creators", - &trust_routine_creators); + &trust_function_creators); +sys_var_bool_ptr +sys_trust_function_creators("log_bin_trust_function_creators", + &trust_function_creators); sys_var_thd_ulong sys_log_warnings("log_warnings", &SV::log_warnings); sys_var_thd_ulong sys_long_query_time("long_query_time", &SV::long_query_time); @@ -258,6 +261,8 @@ sys_var_long_ptr sys_max_relay_log_size("max_relay_log_size", fix_max_relay_log_size); sys_var_thd_ulong sys_max_sort_length("max_sort_length", &SV::max_sort_length); +sys_var_thd_ulong sys_max_sp_recursion_depth("max_sp_recursion_depth", + &SV::max_sp_recursion_depth); sys_var_max_user_conn sys_max_user_connections("max_user_connections"); sys_var_thd_ulong sys_max_tmp_tables("max_tmp_tables", &SV::max_tmp_tables); @@ -628,6 +633,7 @@ sys_var *sys_variables[]= &sys_max_relay_log_size, &sys_max_seeks_for_key, &sys_max_sort_length, + &sys_max_sp_recursion_depth, &sys_max_tmp_tables, &sys_max_user_connections, &sys_max_write_lock_count, @@ -722,6 +728,7 @@ sys_var *sys_variables[]= &sys_innodb_commit_concurrency, #endif &sys_trust_routine_creators, + &sys_trust_function_creators, &sys_engine_condition_pushdown, #ifdef HAVE_NDBCLUSTER_DB &sys_ndb_autoincrement_prefetch_sz, @@ -814,7 +821,7 @@ struct show_var_st init_vars[]= { {"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG }, {sys_innodb_autoextend_increment.name, (char*) &sys_innodb_autoextend_increment, SHOW_SYS}, {"innodb_buffer_pool_awe_mem_mb", (char*) &innobase_buffer_pool_awe_mem_mb, SHOW_LONG }, - {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG }, + {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONGLONG }, {"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL}, {sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS}, {sys_innodb_concurrency_tickets.name, (char*) &sys_innodb_concurrency_tickets, SHOW_SYS}, @@ -832,7 +839,7 @@ struct show_var_st init_vars[]= { {"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR}, {"innodb_log_archive", (char*) &innobase_log_archive, SHOW_MY_BOOL}, {"innodb_log_buffer_size", (char*) &innobase_log_buffer_size, SHOW_LONG }, - {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONG}, + {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONGLONG}, {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG}, {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR}, {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS}, @@ -865,7 +872,7 @@ struct show_var_st init_vars[]= { #endif {"log", (char*) &opt_log, SHOW_BOOL}, {"log_bin", (char*) &opt_bin_log, SHOW_BOOL}, - {sys_trust_routine_creators.name,(char*) &sys_trust_routine_creators, SHOW_SYS}, + {sys_trust_function_creators.name,(char*) &sys_trust_function_creators, SHOW_SYS}, {"log_error", (char*) log_error_file, SHOW_CHAR}, #ifdef HAVE_REPLICATION {"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_MY_BOOL}, @@ -892,6 +899,8 @@ struct show_var_st init_vars[]= { {sys_max_relay_log_size.name, (char*) &sys_max_relay_log_size, SHOW_SYS}, {sys_max_seeks_for_key.name, (char*) &sys_max_seeks_for_key, SHOW_SYS}, {sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS}, + {sys_max_sp_recursion_depth.name, + (char*) &sys_max_sp_recursion_depth, SHOW_SYS}, {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS}, {sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS}, {sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS}, @@ -3463,6 +3472,26 @@ bool process_key_caches(int (* func) (const char *name, KEY_CACHE *)) } +void sys_var_trust_routine_creators::warn_deprecated(THD *thd) +{ + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_DEPRECATED_SYNTAX, + ER(ER_WARN_DEPRECATED_SYNTAX), "log_bin_trust_routine_creators", + "log_bin_trust_function_creators"); +} + +void sys_var_trust_routine_creators::set_default(THD *thd, enum_var_type type) +{ + warn_deprecated(thd); + sys_var_bool_ptr::set_default(thd, type); +} + +bool sys_var_trust_routine_creators::update(THD *thd, set_var *var) +{ + warn_deprecated(thd); + return sys_var_bool_ptr::update(thd, var); +} + /**************************************************************************** Used templates ****************************************************************************/ diff --git a/sql/set_var.h b/sql/set_var.h index 854409c159e..18c3353e8ff 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -738,6 +738,17 @@ public: byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; +class sys_var_trust_routine_creators :public sys_var_bool_ptr +{ + /* We need a derived class only to have a warn_deprecated() */ +public: + sys_var_trust_routine_creators(const char *name_arg, my_bool *value_arg) : + sys_var_bool_ptr(name_arg, value_arg) {}; + void warn_deprecated(THD *thd); + void set_default(THD *thd, enum_var_type type); + bool update(THD *thd, set_var *var); +}; + /**************************************************************************** Classes for parsing of the SET command ****************************************************************************/ diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am index 2e23027f1f5..6d905ba35dc 100644 --- a/sql/share/Makefile.am +++ b/sql/share/Makefile.am @@ -49,5 +49,15 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/charsets/README $(DESTDIR)$(pkgdatadir)/charsets/README $(INSTALL_DATA) $(srcdir)/charsets/*.xml $(DESTDIR)$(pkgdatadir)/charsets +# FIXME maybe shouldn't remove, could be needed by other installation? +uninstall-local: + @RM@ -f -r $(DESTDIR)$(pkgdatadir) + +distclean-local: + @RM@ -f */errmsg.sys + +# Do nothing +link_sources: + # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/sql/share/charsets/latin5.xml b/sql/share/charsets/latin5.xml index 67e5873c503..5004f045889 100644 --- a/sql/share/charsets/latin5.xml +++ b/sql/share/charsets/latin5.xml @@ -112,11 +112,6 @@ <collation name="latin5_turkish_ci"> -<!-- -# Note: all accented characters are compared separately (this -# is different from the default latin1 character set, where -# e.g. a = ä = á, etc.). ---> <map> 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F @@ -130,10 +125,10 @@ 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB - CC CD CE CF D0 D1 D2 44 D3 D4 D5 D6 D7 D8 D9 DA - 49 DB DC DD DE DF 53 E0 E1 E2 E3 E4 5B 4C 58 E5 - CC CD CE CF D0 D1 D2 44 D3 D4 D5 D6 D7 D8 D9 DA - 49 DB DC DD DE DF 53 FA E1 E2 E3 E4 5B 4B 58 FF + 41 41 41 41 41 41 41 44 46 46 46 46 4C 4C 4C 4C + 49 51 52 52 52 52 53 E0 52 5A 5A 5A 5B 4C 58 57 + 41 41 41 41 41 41 41 44 46 46 46 46 4C 4C 4C 4C + 49 51 52 52 52 52 53 FA 52 5A 5A 5A 5B 4B 58 5F </map> </collation> diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index ccf11248a1f..185b4326c5c 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -132,7 +132,7 @@ ER_DB_CREATE_EXISTS jps "'%-.64s' ƒf[ƒ^ƒx[ƒX‚ªì‚ê‚Ü‚¹‚ñ.Šù‚É‚»‚̃f[ƒ^ƒx[ƒX‚ª‘¶Ý‚µ‚Ü‚·", est "Ei suuda luua andmebaasi '%-.64s': andmebaas juba eksisteerib" fre "Ne peut créer la base '%-.64s'; elle existe déjà" - ger "Kann Datenbank '%-.64s' nicht erzeugen. Datenbank '%-.64s' existiert bereits" + ger "Kann Datenbank '%-.64s' nicht erzeugen. Datenbank existiert bereits" greek "Áäýíáôç ç äçìéïõñãßá ôçò âÜóçò äåäïìÝíùí '%-.64s'; Ç âÜóç äåäïìÝíùí õðÜñ÷åé Þäç" hun "Az '%-.64s' adatbazis nem hozhato letre Az adatbazis mar letezik" ita "Impossibile creare il database '%-.64s'; il database esiste" @@ -157,7 +157,7 @@ ER_DB_DROP_EXISTS jps "'%-.64s' ƒf[ƒ^ƒx[ƒX‚ð”jŠü‚Å‚«‚Ü‚¹‚ñ. ‚»‚̃f[ƒ^ƒx[ƒX‚ª‚È‚¢‚Ì‚Å‚·.", est "Ei suuda kustutada andmebaasi '%-.64s': andmebaasi ei eksisteeri" fre "Ne peut effacer la base '%-.64s'; elle n'existe pas" - ger "Kann Datenbank '%-.64s' nicht löschen. Keine Datenbank '%-.64s' vorhanden" + ger "Kann Datenbank '%-.64s' nicht löschen; Datenbank nicht vorhanden" greek "Áäýíáôç ç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí '%-.64s'. Ç âÜóç äåäïìÝíùí äåí õðÜñ÷åé" hun "A(z) '%-.64s' adatbazis nem szuntetheto meg. Az adatbazis nem letezik" ita "Impossibile cancellare '%-.64s'; il database non esiste" @@ -182,7 +182,7 @@ ER_DB_DROP_DELETE jps "ƒf[ƒ^ƒx[ƒX”jŠüƒGƒ‰[ ('%-.64s' ‚ð휂ł«‚Ü‚¹‚ñ, errno: %d)", est "Viga andmebaasi kustutamisel (ei suuda kustutada faili '%-.64s', veakood: %d)" fre "Ne peut effacer la base '%-.64s' (erreur %d)" - ger "Fehler beim Löschen der Datenbank ('%-.64s' kann nicht gelöscht werden, Fehlernuumer: %d)" + ger "Fehler beim Löschen der Datenbank ('%-.64s' kann nicht gelöscht werden, Fehler: %d)" greek "ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí (áäýíáôç ç äéáãñáöÞ '%-.64s', êùäéêüò ëÜèïõò: %d)" hun "Adatbazis megszuntetesi hiba ('%-.64s' nem torolheto, hibakod: %d)" ita "Errore durante la cancellazione del database (impossibile cancellare '%-.64s', errno: %d)" @@ -207,7 +207,7 @@ ER_DB_DROP_RMDIR jps "ƒf[ƒ^ƒx[ƒX”jŠüƒGƒ‰[ ('%-.64s' ‚ð rmdir ‚Å‚«‚Ü‚¹‚ñ, errno: %d)", est "Viga andmebaasi kustutamisel (ei suuda kustutada kataloogi '%-.64s', veakood: %d)" fre "Erreur en effaçant la base (rmdir '%-.64s', erreur %d)" - ger "Fehler beim Löschen der Datenbank (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehlernummer: %d)" + ger "Fehler beim Löschen der Datenbank (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehler: %d)" greek "ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí (áäýíáôç ç äéáãñáöÞ ôïõ öáêÝëëïõ '%-.64s', êùäéêüò ëÜèïõò: %d)" hun "Adatbazis megszuntetesi hiba ('%-.64s' nem szuntetheto meg, hibakod: %d)" ita "Errore durante la cancellazione del database (impossibile rmdir '%-.64s', errno: %d)" @@ -357,7 +357,7 @@ ER_CANT_OPEN_FILE jps "'%-.64s' ƒtƒ@ƒCƒ‹‚ðŠJ‚Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d)", est "Ei suuda avada faili '%-.64s' (veakood: %d)" fre "Ne peut ouvrir le fichier: '%-.64s' (Errcode: %d)" - ger "Datei '%-.64s' nicht öffnen (Fehler: %d)" + ger "Kann Datei '%-.64s' nicht öffnen (Fehler: %d)" greek "Äåí åßíáé äõíáôü íá áíïé÷ôåß ôï áñ÷åßï: '%-.64s' (êùäéêüò ëÜèïõò: %d)" hun "A '%-.64s' file nem nyithato meg (hibakod: %d)" ita "Impossibile aprire il file: '%-.64s' (errno: %d)" @@ -702,7 +702,7 @@ ER_GET_ERRNO eng "Got error %d from storage engine" est "Tabeli handler tagastas vea %d" fre "Reçu l'erreur %d du handler de la table" - ger "Fehler %d (Tabellenhandler)" + ger "Fehler %d (Speicher-Engine)" greek "ÅëÞöèç ìÞíõìá ëÜèïõò %d áðü ôïí ÷åéñéóôÞ ðßíáêá (table handler)" hun "%d hibajelzes a tablakezelotol" ita "Rilevato l'errore %d dal gestore delle tabelle" @@ -726,7 +726,7 @@ ER_ILLEGAL_HA eng "Table storage engine for '%-.64s' doesn't have this option" est "Tabeli '%-.64s' handler ei toeta antud operatsiooni" fre "Le handler de la table '%-.64s' n'a pas cette option" - ger "Diese Option gibt es nicht (Tabellenhandler)" + ger "Diese Option gibt es nicht (Speicher-Engine für '%-.64s')" greek "Ï ÷åéñéóôÞò ðßíáêá (table handler) ãéá '%-.64s' äåí äéáèÝôåé áõôÞ ôçí åðéëïãÞ" hun "A(z) '%-.64s' tablakezelonek nincs ilyen opcioja" ita "Il gestore delle tabelle per '%-.64s' non ha questa opzione" @@ -751,7 +751,7 @@ ER_KEY_NOT_FOUND jps "'%-.64s'‚Ì‚È‚©‚ɃŒƒR[ƒh‚ªŒ©•t‚©‚è‚Ü‚¹‚ñ", est "Ei suuda leida kirjet '%-.64s'-s" fre "Ne peut trouver l'enregistrement dans '%-.64s'" - ger "Kann Datensatz nicht finden" + ger "Kann Datensatz in '%-.64s' nicht finden" greek "Áäýíáôç ç áíåýñåóç åããñáöÞò óôï '%-.64s'" hun "Nem talalhato a rekord '%-.64s'-ben" ita "Impossibile trovare il record in '%-.64s'" @@ -801,7 +801,7 @@ ER_NOT_KEYFILE jps "'%-.64s' ƒe[ƒuƒ‹‚Ì key file ‚ªŠÔˆá‚Á‚Ä‚¢‚é‚悤‚Å‚·. C•œ‚ð‚µ‚Ä‚‚¾‚³‚¢", est "Tabeli '%-.64s' võtmefail on vigane; proovi seda parandada" fre "Index corrompu dans la table: '%-.64s'; essayez de le réparer" - ger "Falsche Schlüssel-Datei für Tabelle '%-.64s'. versuche zu reparieren" + ger "Fehlerhafte Index-Datei für Tabelle '%-.64s'; versuche zu reparieren" greek "ËÜèïò áñ÷åßï ôáîéíüìéóçò (key file) ãéá ôïí ðßíáêá: '%-.64s'; Ðáñáêáëþ, äéïñèþóôå ôï!" hun "Ervenytelen kulcsfile a tablahoz: '%-.64s'; probalja kijavitani!" ita "File chiave errato per la tabella : '%-.64s'; prova a riparalo" @@ -826,7 +826,7 @@ ER_OLD_KEYFILE jps "'%-.64s' ƒe[ƒuƒ‹‚͌¢Œ`Ž®‚Ì key file ‚̂悤‚Å‚·; C•œ‚ð‚µ‚Ä‚‚¾‚³‚¢", est "Tabeli '%-.64s' võtmefail on aegunud; paranda see!" fre "Vieux fichier d'index pour la table '%-.64s'; réparez le!" - ger "Alte Schlüssel-Datei für Tabelle '%-.64s'. Bitte reparieren" + ger "Alte Index-Datei für Tabelle '%-.64s'. Bitte reparieren" greek "Ðáëáéü áñ÷åßï ôáîéíüìéóçò (key file) ãéá ôïí ðßíáêá '%-.64s'; Ðáñáêáëþ, äéïñèþóôå ôï!" hun "Regi kulcsfile a '%-.64s'tablahoz; probalja kijavitani!" ita "File chiave vecchio per la tabella '%-.64s'; riparalo!" @@ -851,7 +851,7 @@ ER_OPEN_AS_READONLY jps "'%-.64s' ‚Í“Ç‚Ýž‚Ýê—p‚Å‚·", est "Tabel '%-.64s' on ainult lugemiseks" fre "'%-.64s' est en lecture seulement" - ger "'%-.64s' ist nur lesbar" + ger "Tabelle '%-.64s' ist nur lesbar" greek "'%-.64s' åðéôñÝðåôáé ìüíï ç áíÜãíùóç" hun "'%-.64s' irasvedett" ita "'%-.64s' e` di sola lettura" @@ -901,7 +901,7 @@ ER_OUT_OF_SORTMEMORY HY001 S1001 jps "Out of sort memory. sort buffer size ‚ª‘«‚è‚È‚¢‚悤‚Å‚·.", est "Mälu sai sorteerimisel otsa. Suurenda MySQL-i sorteerimispuhvrit" fre "Manque de mémoire pour le tri. Augmentez-la." - ger "Kein Speicher zum Sortieren vorhanden. sort_buffer_size sollte erhöht werden" + ger "Kein Speicher zum Sortieren vorhanden. sort_buffer_size sollte im Server erhöht werden" greek "Äåí õðÜñ÷åé äéáèÝóéìç ìíÞìç ãéá ôáîéíüìéóç. ÁõîÞóôå ôï sort buffer size ãéá ôç äéáäéêáóßá (demon)" hun "Nincs eleg memoria a rendezeshez. Novelje a rendezo demon puffermeretet" ita "Memoria per gli ordinamenti esaurita. Incrementare il 'sort_buffer' al demone" @@ -976,7 +976,7 @@ ER_OUT_OF_RESOURCES jps "Out of memory; mysqld ‚©‚»‚Ì‘¼‚̃vƒƒZƒX‚ªƒƒ‚ƒŠ[‚ð‘S‚ÄŽg‚Á‚Ä‚¢‚é‚©Šm”F‚µ‚Ä‚‚¾‚³‚¢. ƒƒ‚ƒŠ[‚ðŽg‚¢Ø‚Á‚Ä‚¢‚È‚¢ê‡A'ulimit' ‚ðݒ肵‚Ä mysqld ‚̃ƒ‚ƒŠ[Žg—pŒÀŠE—ʂ𑽂‚·‚é‚©Aswap space ‚ð‘‚₵‚Ä‚Ý‚Ä‚‚¾‚³‚¢", est "Mälu sai otsa. Võimalik, et aitab swap-i lisamine või käsu 'ulimit' abil MySQL-le rohkema mälu kasutamise lubamine" fre "Manque de 'threads'/mémoire" - ger "Kein Speicher mehr vorhanden. Prüfen Sie, ob mysqld oder ein anderer Prozess allen Speicher verbraucht. Wenn nicht, sollten Sie mit 'ulimit' dafür sorgen, dass mysqld mehr Speicher benutzen darf, oder mehr Swap-Speicher einrichten" + ger "Kein Speicher mehr vorhanden. Prüfen Sie, ob mysqld oder ein anderer Prozess den gesamten Speicher verbraucht. Wenn nicht, sollten Sie mit 'ulimit' dafür sorgen, dass mysqld mehr Speicher benutzen darf, oder mehr Swap-Speicher einrichten" greek "Ðñüâëçìá ìå ôç äéáèÝóéìç ìíÞìç (Out of thread space/memory)" hun "Elfogyott a thread-memoria" ita "Fine dello spazio/memoria per i thread" @@ -1025,7 +1025,7 @@ ER_HANDSHAKE_ERROR 08S01 eng "Bad handshake" est "Väär handshake" fre "Mauvais 'handshake'" - ger "Schlechter Handshake" + ger "Ungültiger Handshake" greek "Ç áíáãíþñéóç (handshake) äåí Ýãéíå óùóôÜ" hun "A kapcsolatfelvetel nem sikerult (Bad handshake)" ita "Negoziazione impossibile" @@ -1245,7 +1245,7 @@ ER_NON_UNIQ_ERROR 23000 eng "Column '%-.64s' in %-.64s is ambiguous" est "Väli '%-.64s' %-.64s-s ei ole ühene" fre "Champ: '%-.64s' dans %s est ambigu" - ger "Spalte '%-.64s' in %-.64s ist nicht eindeutig" + ger "Feld '%-.64s' in %-.64s ist nicht eindeutig" greek "Ôï ðåäßï: '%-.64s' óå %-.64s äåí Ý÷åé êáèïñéóôåß" hun "A(z) '%-.64s' oszlop %-.64s-ben ketertelmu" ita "Colonna: '%-.64s' di %-.64s e` ambigua" @@ -1411,7 +1411,7 @@ ER_TOO_LONG_IDENT 42000 S1009 jps "Identifier name '%-.100s' ‚Í’·‚·‚¬‚Ü‚·", est "Identifikaatori '%-.100s' nimi on liiga pikk" fre "Le nom de l'identificateur '%-.64s' est trop long" - ger "Name des Bezeichners '%-.64s' ist zu lang" + ger "Name des Bezeichners '%-.100s' ist zu lang" greek "Ôï identifier name '%-.100s' åßíáé ðïëý ìåãÜëï" hun "A(z) '%-.100s' azonositonev tul hosszu." ita "Il nome dell'identificatore '%-.100s' e` troppo lungo" @@ -1436,7 +1436,7 @@ ER_DUP_FIELDNAME 42S21 S1009 jps "'%-.64s' ‚Æ‚¢‚¤ column –¼‚Íd•¡‚µ‚Ä‚Ü‚·", est "Kattuv tulba nimi '%-.64s'" fre "Nom du champ '%-.64s' déjà utilisé" - ger "Doppelter Spaltenname vorhanden: '%-.64s'" + ger "Doppelter Spaltenname: '%-.64s'" greek "ÅðáíÜëçøç column name '%-.64s'" hun "Duplikalt oszlopazonosito: '%-.64s'" ita "Nome colonna duplicato '%-.64s'" @@ -1461,7 +1461,7 @@ ER_DUP_KEYNAME 42000 S1009 jps "'%-.64s' ‚Æ‚¢‚¤ key ‚Ì–¼‘O‚Íd•¡‚µ‚Ä‚¢‚Ü‚·", est "Kattuv võtme nimi '%-.64s'" fre "Nom de clef '%-.64s' déjà utilisé" - ger "Doppelter Name für Schlüssel (Key) vorhanden: '%-.64s'" + ger "Doppelter Name für Schlüssel vorhanden: '%-.64s'" greek "ÅðáíÜëçøç key name '%-.64s'" hun "Duplikalt kulcsazonosito: '%-.64s'" ita "Nome chiave duplicato '%-.64s'" @@ -1510,7 +1510,7 @@ ER_WRONG_FIELD_SPEC 42000 S1009 eng "Incorrect column specifier for column '%-.64s'" est "Vigane tulba kirjeldus tulbale '%-.64s'" fre "Mauvais paramètre de champ pour le champ '%-.64s'" - ger "Falsche Spaltenangaben für Spalte '%-.64s'" + ger "Falsche Spezifikation für Feld '%-.64s'" greek "ÅóöáëìÝíï column specifier ãéá ôï ðåäßï '%-.64s'" hun "Rossz oszlopazonosito: '%-.64s'" ita "Specifica errata per la colonna '%-.64s'" @@ -1608,7 +1608,7 @@ ER_INVALID_DEFAULT 42000 S1009 eng "Invalid default value for '%-.64s'" est "Vigane vaikeväärtus '%-.64s' jaoks" fre "Valeur par défaut invalide pour '%-.64s'" - ger "Fehlerhafter Vorgabewert (DEFAULT): '%-.64s'" + ger "Fehlerhafter Vorgabewert (DEFAULT) für '%-.64s'" greek "ÅóöáëìÝíç ðñïêáèïñéóìÝíç ôéìÞ (default value) ãéá '%-.64s'" hun "Ervenytelen ertek: '%-.64s'" ita "Valore di default non valido per '%-.64s'" @@ -1632,7 +1632,7 @@ ER_MULTIPLE_PRI_KEY 42000 S1009 jps "•¡”‚Ì primary key ‚ª’è‹`‚³‚ê‚Ü‚µ‚½", est "Mitut primaarset võtit ei saa olla" fre "Plusieurs clefs primaires définies" - ger "Mehrfacher Primärschlüssel (PRIMARY KEY) definiert" + ger "Mehrere Primärschlüssel (PRIMARY KEY) definiert" greek "Ðåñéóóüôåñá áðü Ýíá primary key ïñßóôçêáí" hun "Tobbszoros elsodleges kulcs definialas." ita "Definite piu` chiave primarie" @@ -1681,7 +1681,7 @@ ER_TOO_MANY_KEY_PARTS 42000 S1009 eng "Too many key parts specified; max %d parts allowed" est "Võti koosneb liiga paljudest osadest. Maksimaalselt võib olla %d osa" fre "Trop de parties specifiées dans la clef. Maximum de %d parties" - ger "Zu viele Teilschlüssel definiert. Maximal sind %d Teilschlüssel erlaubt" + ger "Zu viele Teilschlüssel definiert. Maximal %d Teilschlüssel erlaubt" greek "ÐÜñá ðïëëÜ key parts ïñßóèçêáí. Ôï ðïëý %d åðéôñÝðïíôáé" hun "Tul sok kulcsdarabot definialt. Maximum %d resz engedelyezett" ita "Troppe parti di chiave specificate. Sono ammesse max %d parti" @@ -1730,7 +1730,7 @@ ER_KEY_COLUMN_DOES_NOT_EXITS 42000 S1009 jps "Key column '%-.64s' ‚ªƒe[ƒuƒ‹‚É‚ ‚è‚Ü‚¹‚ñ.", est "Võtme tulp '%-.64s' puudub tabelis" fre "La clé '%-.64s' n'existe pas dans la table" - ger "In der Tabelle gibt es keine Schlüsselspalte '%-.64s'" + ger "In der Tabelle gibt es kein Schlüsselfeld '%-.64s'" greek "Ôï ðåäßï êëåéäß '%-.64s' äåí õðÜñ÷åé óôïí ðßíáêá" hun "A(z) '%-.64s'kulcsoszlop nem letezik a tablaban" ita "La colonna chiave '%-.64s' non esiste nella tabella" @@ -1778,7 +1778,7 @@ ER_TOO_BIG_FIELDLENGTH 42000 S1009 jps "column '%-.64s' ‚Í,Šm•Û‚·‚é column ‚Ì‘å‚«‚³‚ª‘½‚·‚¬‚Ü‚·. (Å‘å %d ‚Ü‚Å). BLOB ‚ð‚©‚í‚è‚ÉŽg—p‚µ‚Ä‚‚¾‚³‚¢.", est "Tulba '%-.64s' pikkus on liiga pikk (maksimaalne pikkus: %d). Kasuta BLOB väljatüüpi" fre "Champ '%-.64s' trop long (max = %d). Utilisez un BLOB" - ger "Feldlänge für Feld '%-.64s' zu groß (maximal %d). BLOB-Feld verwenden!" + ger "Feldlänge für Feld '%-.64s' zu groß (maximal %d). BLOB- oder TEXT-Spaltentyp verwenden!" greek "Ðïëý ìåãÜëï ìÞêïò ãéá ôï ðåäßï '%-.64s' (max = %d). Ðáñáêáëþ ÷ñçóéìïðïéåßóôå ôïí ôýðï BLOB" hun "A(z) '%-.64s' oszlop tul hosszu. (maximum = %d). Hasznaljon BLOB tipust inkabb." ita "La colonna '%-.64s' e` troppo grande (max=%d). Utilizza un BLOB." @@ -1803,7 +1803,7 @@ ER_WRONG_AUTO_KEY 42000 S1009 jps "ƒe[ƒuƒ‹‚Ì’è‹`‚ªˆá‚¢‚Ü‚·; there can be only one auto column and it must be defined as a key", est "Vigane tabelikirjeldus; Tabelis tohib olla üks auto_increment tüüpi tulp ning see peab olema defineeritud võtmena" fre "Un seul champ automatique est permis et il doit être indexé" - ger "Falsche Tabellendefinition. Es darf nur ein Auto-Feld geben und dieses muss als Schlüssel definiert werden" + ger "Falsche Tabellendefinition. Es darf nur eine AUTO_INCREMENT-Spalte geben, und diese muss als Schlüssel definiert werden" greek "Ìðïñåß íá õðÜñ÷åé ìüíï Ýíá auto field êáé ðñÝðåé íá Ý÷åé ïñéóèåß óáí key" hun "Csak egy auto mezo lehetseges, es azt kulcskent kell definialni." ita "Puo` esserci solo un campo AUTO e deve essere definito come chiave" @@ -1828,7 +1828,7 @@ ER_READY jps "%s: €”õŠ®—¹", est "%s: ootab ühendusi" fre "%s: Prêt pour des connections" - ger "%-.64s: Bereit für Verbindungen" + ger "%-.64s: Bereit für Verbindungen.\nVersion: '%2' Socket: '%s' Port: %d" greek "%s: óå áíáìïíÞ óõíäÝóåùí" hun "%s: kapcsolatra kesz" ita "%s: Pronto per le connessioni\n" @@ -1901,7 +1901,7 @@ ER_SHUTDOWN_COMPLETE jps "%s: Shutdown Š®—¹\n", est "%s: Lõpp\n" fre "%s: Arrêt du serveur terminé\n" - ger "%-.64s: Heruntergefahren (shutdown)\n" + ger "%-.64s: Herunterfahren beendet\n" greek "%s: Ç äéáäéêáóßá Shutdown ïëïêëçñþèçêå\n" hun "%s: A leallitas kesz\n" ita "%s: Shutdown completato\n" @@ -1976,7 +1976,7 @@ ER_NO_SUCH_INDEX 42S12 S1009 jps "Table '%-.64s' ‚Í‚»‚̂悤‚È index ‚ðŽ‚Á‚Ä‚¢‚Ü‚¹‚ñ(CREATE INDEX ŽÀsŽž‚ÉŽw’肳‚ê‚Ä‚¢‚Ü‚¹‚ñ). ƒe[ƒuƒ‹‚ðì‚è’¼‚µ‚Ä‚‚¾‚³‚¢", est "Tabelil '%-.64s' puuduvad võtmed. Loo tabel uuesti" fre "La table '%-.64s' n'a pas d'index comme celle utilisée dans CREATE INDEX. Recréez la table" - ger "Tabelle '%-.64s' besitzt keinen wie den in CREATE INDEX verwendeten Index. Index neu anlegen" + ger "Tabelle '%-.64s' besitzt keinen wie den in CREATE INDEX verwendeten Index. Tabelle neu anlegen" greek "Ï ðßíáêáò '%-.64s' äåí Ý÷åé åõñåôÞñéï (index) óáí áõôü ðïõ ÷ñçóéìïðïéåßôå óôçí CREATE INDEX. Ðáñáêáëþ, îáíáäçìéïõñãÞóôå ôïí ðßíáêá" hun "A(z) '%-.64s' tablahoz nincs meg a CREATE INDEX altal hasznalt index. Alakitsa at a tablat" ita "La tabella '%-.64s' non ha nessun indice come quello specificatato dalla CREATE INDEX. Ricrea la tabella" @@ -2048,7 +2048,7 @@ ER_TEXTFILE_NOT_READABLE jps "ƒtƒ@ƒCƒ‹ '%-.64s' ‚Í databse ‚Ì directory ‚É‚ ‚é‚©‘S‚Ẵ†[ƒU[‚ª“Ç‚ß‚é‚悤‚É‹–‰Â‚³‚ê‚Ä‚¢‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ.", est "Fail '%-.64s' peab asuma andmebaasi kataloogis või olema kõigile loetav" fre "Le fichier '%-.64s' doit être dans le répertoire de la base et lisible par tous" - ger "Datei '%-.64s' muss im Datenbank-Verzeichnis vorhanden und lesbar für alle sein" + ger "Datei '%-.64s' muss im Datenbank-Verzeichnis vorhanden oder lesbar für alle sein" greek "Ôï áñ÷åßï '%-.64s' ðñÝðåé íá õðÜñ÷åé óôï database directory Þ íá ìðïñåß íá äéáâáóôåß áðü üëïõò" hun "A(z) '%-.64s'-nak az adatbazis konyvtarban kell lennie, vagy mindenki szamara olvashatonak" ita "Il file '%-.64s' deve essere nella directory del database e deve essere leggibile da tutti" @@ -2073,7 +2073,7 @@ ER_FILE_EXISTS_ERROR jps "File '%-.64s' ‚ÍŠù‚É‘¶Ý‚µ‚Ü‚·", est "Fail '%-.80s' juba eksisteerib" fre "Le fichier '%-.64s' existe déjà" - ger "Datei '%-.64s' bereits vorhanden" + ger "Datei '%-.80s' bereits vorhanden" greek "Ôï áñ÷åßï '%-.64s' õðÜñ÷åé Þäç" hun "A '%-.64s' file mar letezik." ita "Il file '%-.64s' esiste gia`" @@ -2147,7 +2147,7 @@ ER_WRONG_SUB_KEY eng "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" est "Vigane võtme osa. Kasutatud võtmeosa ei ole string tüüpi, määratud pikkus on pikem kui võtmeosa või tabelihandler ei toeta seda tüüpi võtmeid" fre "Mauvaise sous-clef. Ce n'est pas un 'string' ou la longueur dépasse celle définie dans la clef" - ger "Falscher Unterteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String, die verwendete Länge ist länger als der Teilschlüssel oder der Tabellenhandler unterstützt keine Unterteilschlüssel" + ger "Falscher Unterteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String, die verwendete Länge ist länger als der Teilschlüssel oder die Speicher-Engine unterstützt keine Unterteilschlüssel" greek "ÅóöáëìÝíï sub part key. Ôï ÷ñçóéìïðïéïýìåíï key part äåí åßíáé string Þ ôï ìÞêïò ôïõ åßíáé ìåãáëýôåñï" hun "Rossz alkulcs. A hasznalt kulcsresz nem karaktersorozat vagy hosszabb, mint a kulcsresz" ita "Sotto-parte della chiave errata. La parte di chiave utilizzata non e` una stringa o la lunghezza e` maggiore della parte di chiave." @@ -2197,7 +2197,7 @@ ER_CANT_DROP_FIELD_OR_KEY 42000 jps "'%-.64s' ‚ð”jŠü‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½; check that column/key exists", est "Ei suuda kustutada '%-.64s'. Kontrolli kas tulp/võti eksisteerib" fre "Ne peut effacer (DROP) '%-.64s'. Vérifiez s'il existe" - ger "Kann '%-.64s' nicht löschen. Existiert das Feld / der Schlüssel?" + ger "Kann '%-.64s' nicht löschen. Existiert die Spalte oder der Schlüssel?" greek "Áäýíáôç ç äéáãñáöÞ (DROP) '%-.64s'. Ðáñáêáëþ åëÝãîôå áí ôï ðåäßï/êëåéäß õðÜñ÷åé" hun "A DROP '%-.64s' nem lehetseges. Ellenorizze, hogy a mezo/kulcs letezik-e" ita "Impossibile cancellare '%-.64s'. Controllare che il campo chiave esista" @@ -2325,7 +2325,7 @@ ER_TOO_BIG_SET eng "Too many strings for column %-.64s and SET" est "Liiga palju string tulbale %-.64s tüübile SET" fre "Trop de chaînes dans la colonne %s avec SET" - ger "Zu viele Strings für SET-Spalte %-.64s angegeben" + ger "Zu viele Strings für Feld %-.64s und SET angegeben" greek "ÐÜñá ðïëëÜ strings ãéá ôï ðåäßï %-.64s êáé SET" hun "Tul sok karakter: %-.64s es SET" ita "Troppe stringhe per la colonna %-.64s e la SET" @@ -2348,7 +2348,7 @@ ER_NO_UNIQUE_LOGFILE eng "Can't generate a unique log-filename %-.64s.(1-999)\n" est "Ei suuda luua unikaalset logifaili nime %-.64s.(1-999)\n" fre "Ne peut générer un unique nom de journal %s.(1-999)\n" - ger "Kann keinen eindeutigen Dateinamen für die Logdatei %-.64s erzeugen (1-999)\n" + ger "Kann keinen eindeutigen Dateinamen für die Logdatei %-.64s(1-999) erzeugen\n" greek "Áäýíáôç ç äçìéïõñãßá unique log-filename %-.64s.(1-999)\n" hun "Egyedi log-filenev nem generalhato: %-.64s.(1-999)\n" ita "Impossibile generare un nome del file log unico %-.64s.(1-999)\n" @@ -2421,7 +2421,7 @@ ER_BLOB_CANT_HAVE_DEFAULT 42000 eng "BLOB/TEXT column '%-.64s' can't have a default value" est "BLOB-tüüpi tulp '%-.64s' ei saa omada vaikeväärtust" fre "BLOB '%-.64s' ne peut avoir de valeur par défaut" - ger "BLOB-Feld '%-.64s' darf keinen Vorgabewert (DEFAULT) haben" + ger "BLOB/TEXT-Feld '%-.64s' darf keinen Vorgabewert (DEFAULT) haben" greek "Ôá Blob ðåäßá '%-.64s' äåí ìðïñïýí íá Ý÷ïõí ðñïêáèïñéóìÝíåò ôéìÝò (default value)" hun "A(z) '%-.64s' blob objektumnak nem lehet alapertelmezett erteke" ita "Il campo BLOB '%-.64s' non puo` avere un valore di default" @@ -2446,7 +2446,7 @@ ER_WRONG_DB_NAME 42000 jps "Žw’肵‚½ database –¼ '%-.100s' ‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚·", est "Vigane andmebaasi nimi '%-.100s'" fre "Nom de base de donnée illégal: '%-.64s'" - ger "Unerlaubter Datenbankname '%-.64s'" + ger "Unerlaubter Datenbankname '%-.100s'" greek "ËÜèïò üíïìá âÜóçò äåäïìÝíùí '%-.100s'" hun "Hibas adatbazisnev: '%-.100s'" ita "Nome database errato '%-.100s'" @@ -2471,7 +2471,7 @@ ER_WRONG_TABLE_NAME 42000 jps "Žw’肵‚½ table –¼ '%-.100s' ‚Í‚Ü‚¿‚ª‚Á‚Ä‚¢‚Ü‚·", est "Vigane tabeli nimi '%-.100s'" fre "Nom de table illégal: '%-.64s'" - ger "Unerlaubter Tabellenname '%-.64s'" + ger "Unerlaubter Tabellenname '%-.100s'" greek "ËÜèïò üíïìá ðßíáêá '%-.100s'" hun "Hibas tablanev: '%-.100s'" ita "Nome tabella errato '%-.100s'" @@ -2495,7 +2495,7 @@ ER_TOO_BIG_SELECT 42000 eng "The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay" est "SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET SQL_BIG_SELECTS=1" fre "SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET SQL_BIG_SELECTS=1 si SELECT se passe bien" - ger "Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange dauern. Bitte WHERE-Klausel überprüfen oder gegebenenfalls SET SQL_BIG_SELECTS=1 oder SET SQL_MAX_JOIN_SIZE=# verwenden" + ger "Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange dauern. Bitte WHERE-Klausel überprüfen und gegebenenfalls SET SQL_BIG_SELECTS=1 oder SET SQL_MAX_JOIN_SIZE=# verwenden" greek "Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü" hun "A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET SQL_BIG_SELECTS=1 beallitast, ha a SELECT okay" ita "La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET SQL_BIG_SELECTS=1 se e` tutto a posto." @@ -2676,7 +2676,7 @@ ER_UNSUPPORTED_EXTENSION 42000 eng "Table '%-.64s' uses an extension that doesn't exist in this MySQL version" est "Tabel '%-.64s' kasutab laiendust, mis ei eksisteeri antud MySQL versioonis" fre "Table '%-.64s' : utilise une extension invalide pour cette version de MySQL" - ger "Tabelle '%-.64s' verwendet eine Extension, die in dieser MySQL-Version nicht verfügbar ist" + ger "Tabelle '%-.64s' verwendet eine Erweiterung, die in dieser MySQL-Version nicht verfügbar ist" greek "Ï ðßíáêò '%-.64s' ÷ñçóéìïðïéåß êÜðïéï extension ðïõ äåí õðÜñ÷åé óôçí Ýêäïóç áõôÞ ôçò MySQL" hun "A(z) '%-.64s' tabla olyan bovitest hasznal, amely nem letezik ebben a MySQL versioban." ita "La tabella '%-.64s' usa un'estensione che non esiste in questa versione di MySQL" @@ -2700,7 +2700,7 @@ ER_TABLE_MUST_HAVE_COLUMNS 42000 jps "ƒe[ƒuƒ‹‚ÍÅ’á 1 ŒÂ‚Ì column ‚ª•K—v‚Å‚·", est "Tabelis peab olema vähemalt üks tulp" fre "Une table doit comporter au moins une colonne" - ger "Eine Tabelle muß mindestens 1 Spalte besitzen" + ger "Eine Tabelle muss mindestens eine Spalte besitzen" greek "Åíáò ðßíáêáò ðñÝðåé íá Ý÷åé ôïõëÜ÷éóôïí Ýíá ðåäßï" hun "A tablanak legalabb egy oszlopot tartalmazni kell" ita "Una tabella deve avere almeno 1 colonna" @@ -2788,7 +2788,7 @@ ER_TOO_MANY_FIELDS jps "column ‚ª‘½‚·‚¬‚Ü‚·", est "Liiga palju tulpasid" fre "Trop de champs" - ger "Zu viele Spalten" + ger "Zu viele Felder" greek "Ðïëý ìåãÜëïò áñéèìüò ðåäßùí" hun "Tul sok mezo" ita "Troppi campi" @@ -2810,7 +2810,7 @@ ER_TOO_BIG_ROWSIZE 42000 jps "row size ‚ª‘å‚«‚·‚¬‚Ü‚·. BLOB ‚ðŠÜ‚Ü‚È‚¢ê‡‚Ì row size ‚ÌÅ‘å‚Í %d ‚Å‚·. ‚¢‚‚‚©‚Ì field ‚ð BLOB ‚É•Ï‚¦‚Ä‚‚¾‚³‚¢.", est "Liiga pikk kirje. Kirje maksimumpikkus arvestamata BLOB-tüüpi välju on %d. Muuda mõned väljad BLOB-tüüpi väljadeks" fre "Ligne trop grande. Le taille maximale d'une ligne, sauf les BLOBs, est %d. Changez le type de quelques colonnes en BLOB" - ger "Zeilenlänge zu groß. Die maximale Spaltenlänge für den verwendeten Tabellentyp (ohne BLOB-Felder) beträgt %d. Einige Felder müssen in BLOB oder TEXT umgewandelt werden" + ger "Zeilenlänge zu groß. Die maximale Zeilenlänge für den verwendeten Tabellentyp (ohne BLOB-Felder) beträgt %ld. Einige Felder müssen in BLOB oder TEXT umgewandelt werden" greek "Ðïëý ìåãÜëï ìÝãåèïò åããñáöÞò. Ôï ìÝãéóôï ìÝãåèïò åããñáöÞò, ÷ùñßò íá õðïëïãßæïíôáé ôá blobs, åßíáé %d. ÐñÝðåé íá ïñßóåôå êÜðïéá ðåäßá óáí blobs" hun "Tul nagy sormeret. A maximalis sormeret (nem szamolva a blob objektumokat) %d. Nehany mezot meg kell valtoztatnia" ita "Riga troppo grande. La massima grandezza di una riga, non contando i BLOB, e` %d. Devi cambiare alcuni campi in BLOB" @@ -2831,7 +2831,7 @@ ER_STACK_OVERRUN eng "Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed" jps "Thread stack overrun: Used: %ld of a %ld stack. ƒXƒ^ƒbƒN—̈æ‚𑽂‚Ƃ肽‚¢ê‡A'mysqld -O thread_stack=#' ‚ÆŽw’肵‚Ä‚‚¾‚³‚¢", fre "Débordement de la pile des tâches (Thread stack). Utilisées: %ld pour une pile de %ld. Essayez 'mysqld -O thread_stack=#' pour indiquer une plus grande valeur" - ger "Thread-Stack-Überlauf. Benutzt: %ld von %ld Stack. 'mysqld -O thread_stack=#' verwenen, um notfalls einen größeren Stack anzulegen" + ger "Thread-Stack-Überlauf. Benutzt: %ld von %ld Stack. 'mysqld -O thread_stack=#' verwenden, um bei Bedarf einen größeren Stack anzulegen" greek "Stack overrun óôï thread: Used: %ld of a %ld stack. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå 'mysqld -O thread_stack=#' ãéá íá ïñßóåôå Ýíá ìåãáëýôåñï stack áí ÷ñåéÜæåôáé" hun "Thread verem tullepes: Used: %ld of a %ld stack. Hasznalja a 'mysqld -O thread_stack=#' nagyobb verem definialasahoz" ita "Thread stack overrun: Usati: %ld di uno stack di %ld. Usa 'mysqld -O thread_stack=#' per specificare uno stack piu` grande." @@ -3003,15 +3003,15 @@ ER_CANT_OPEN_LIBRARY swe "Kan inte öppna det dynamiska biblioteket '%-.64s' (Felkod: %d %s)" ukr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÒÏÚĦÌÀ×ÁÎÕ Â¦Â̦ÏÔÅËÕ '%-.64s' (ÐÏÍÉÌËÁ: %d %-.64s)" ER_CANT_FIND_DL_ENTRY - cze "Nemohu naj-Bít funkci '%-.64s' v knihovnì'" - dan "Kan ikke finde funktionen '%-.64s' i bibliotek'" + cze "Nemohu naj-Bít funkci '%-.64s' v knihovnì" + dan "Kan ikke finde funktionen '%-.64s' i bibliotek" nla "Kan functie '%-.64s' niet in library vinden" - eng "Can't find function '%-.64s' in library'" + eng "Can't find function '%-.64s' in library" jps "function '%-.64s' ‚ðƒ‰ƒCƒuƒ‰ƒŠ[’†‚ÉŒ©•t‚¯‚鎖‚ª‚Å‚«‚Ü‚¹‚ñ", est "Ei leia funktsiooni '%-.64s' antud teegis" - fre "Impossible de trouver la fonction '%-.64s' dans la bibliothèque'" + fre "Impossible de trouver la fonction '%-.64s' dans la bibliothèque" ger "Kann Funktion '%-.64s' in der Library nicht finden" - greek "Äåí åßíáé äõíáôÞ ç áíåýñåóç ôçò óõíÜñôçóçò '%-.64s' óôçí âéâëéïèÞêç'" + greek "Äåí åßíáé äõíáôÞ ç áíåýñåóç ôçò óõíÜñôçóçò '%-.64s' óôçí âéâëéïèÞêç" hun "A(z) '%-.64s' fuggveny nem talalhato a konyvtarban" ita "Impossibile trovare la funzione '%-.64s' nella libreria" jpn "function '%-.64s' ¤ò¥é¥¤¥Ö¥é¥ê¡¼Ãæ¤Ë¸«ÉÕ¤±¤ë»ö¤¬¤Ç¤¤Þ¤»¤ó" @@ -3020,10 +3020,10 @@ ER_CANT_FIND_DL_ENTRY rum "Nu pot gasi functia '%-.64s' in libraria" rus "îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÆÕÎËÃÉÀ '%-.64s' × ÂÉÂÌÉÏÔÅËÅ" serbian "Ne mogu da pronadjem funkciju '%-.64s' u biblioteci" - slo "Nemô¾em nájs» funkciu '%-.64s' v kni¾nici'" - spa "No puedo encontrar función '%-.64s' en libraria'" + slo "Nemô¾em nájs» funkciu '%-.64s' v kni¾nici" + spa "No puedo encontrar función '%-.64s' en libraria" swe "Hittar inte funktionen '%-.64s' in det dynamiska biblioteket" - ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÕÎËæÀ '%-.64s' Õ Â¦Â̦ÏÔÅæ'" + ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÕÎËæÀ '%-.64s' Õ Â¦Â̦ÏÔÅæ" ER_FUNCTION_NOT_DEFINED cze "Funkce '%-.64s' nen-Bí definována" dan "Funktionen '%-.64s' er ikke defineret" @@ -3198,7 +3198,7 @@ ER_WRONG_VALUE_COUNT_ON_ROW 21S01 nla "Kolom aantal komt niet overeen met waarde aantal in rij %ld" eng "Column count doesn't match value count at row %ld" est "Tulpade hulk erineb väärtuste hulgast real %ld" - ger "Anzahl der Spalten stimmt nicht mit der Anzahl der Werte in Zeile %ld überein" + ger "Anzahl der Felder stimmt nicht mit der Anzahl der Werte in Zeile %ld überein" hun "Az oszlopban talalhato ertek nem egyezik meg a %ld sorban szamitott ertekkel" ita "Il numero delle colonne non corrisponde al conteggio alla riga %ld" kor "Row %ld¿¡¼ Ä®·³ Ä«¿îÆ®¿Í value Ä«¿îÅÍ¿Í ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù." @@ -3276,7 +3276,7 @@ ER_MIX_OF_GROUP_FUNC_AND_FIELDS 42000 eng "Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause" est "GROUP tulpade (MIN(),MAX(),COUNT()...) kooskasutamine tavaliste tulpadega ilma GROUP BY klauslita ei ole lubatud" fre "Mélanger les colonnes GROUP (MIN(),MAX(),COUNT()...) avec des colonnes normales est interdit s'il n'y a pas de clause GROUP BY" - ger "Das Vermischen von GROUP-Spalten (MIN(),MAX(),COUNT()...) mit Nicht-GROUP-Spalten ist nicht zulässig, wenn keine GROUP BY-Klausel vorhanden ist" + ger "Das Vermischen von GROUP-Feldern (MIN(),MAX(),COUNT()...) mit Nicht-GROUP-Feldern ist nicht zulässig, wenn keine GROUP-BY-Klausel vorhanden ist" hun "A GROUP mezok (MIN(),MAX(),COUNT()...) kevert hasznalata nem lehetseges GROUP BY hivatkozas nelkul" ita "Il mescolare funzioni di aggregazione (MIN(),MAX(),COUNT()...) e non e` illegale se non c'e` una clausula GROUP BY" kor "Mixing of GROUP Ä®·³s (MIN(),MAX(),COUNT(),...) with no GROUP Ä®·³s is illegal if there is no GROUP BY clause" @@ -3315,7 +3315,7 @@ ER_TABLEACCESS_DENIED_ERROR 42000 jps "ƒRƒ}ƒ“ƒh %-.16s ‚Í ƒ†[ƒU[ '%-.32s'@'%-.64s' ,ƒe[ƒuƒ‹ '%-.64s' ‚ɑ΂µ‚Ä‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ", est "%-.16s käsk ei ole lubatud kasutajale '%-.32s'@'%-.64s' tabelis '%-.64s'" fre "La commande '%-.16s' est interdite à l'utilisateur: '%-.32s'@'@%-.64s' sur la table '%-.64s'" - ger "%-.16s Befehl nicht erlaubt für Benutzer '%-.32s'@'%-.64s' und für Tabelle '%-.64s'" + ger "%-.16s Befehl nicht erlaubt für Benutzer '%-.32s'@'%-.64s' auf Tabelle '%-.64s'" hun "%-.16s parancs a '%-.32s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.64s' tablaban" ita "Comando %-.16s negato per l'utente: '%-.32s'@'%-.64s' sulla tabella '%-.64s'" jpn "¥³¥Þ¥ó¥É %-.16s ¤Ï ¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s' ,¥Æ¡¼¥Ö¥ë '%-.64s' ¤ËÂФ·¤Æµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" @@ -3335,7 +3335,7 @@ ER_COLUMNACCESS_DENIED_ERROR 42000 jps "ƒRƒ}ƒ“ƒh %-.16s ‚Í ƒ†[ƒU[ '%-.32s'@'%-.64s'\n ƒJƒ‰ƒ€ '%-.64s' ƒe[ƒuƒ‹ '%-.64s' ‚ɑ΂µ‚Ä‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ", est "%-.16s käsk ei ole lubatud kasutajale '%-.32s'@'%-.64s' tulbale '%-.64s' tabelis '%-.64s'" fre "La commande '%-.16s' est interdite à l'utilisateur: '%-.32s'@'@%-.64s' sur la colonne '%-.64s' de la table '%-.64s'" - ger "%-.16s Befehl nicht erlaubt für Benutzer '%-.32s'@'%-.64s' und Spalte '%-.64s' in Tabelle '%-.64s'" + ger "%-.16s Befehl nicht erlaubt für Benutzer '%-.32s'@'%-.64s' und Feld '%-.64s' in Tabelle '%-.64s'" hun "%-.16s parancs a '%-.32s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.64s' mezo eseten a '%-.64s' tablaban" ita "Comando %-.16s negato per l'utente: '%-.32s'@'%-.64s' sulla colonna '%-.64s' della tabella '%-.64s'" jpn "¥³¥Þ¥ó¥É %-.16s ¤Ï ¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s'\n ¥«¥é¥à '%-.64s' ¥Æ¡¼¥Ö¥ë '%-.64s' ¤ËÂФ·¤Æµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" @@ -3419,7 +3419,7 @@ ER_NONEXISTING_TABLE_GRANT 42000 eng "There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'" est "Sellist õigust ei ole defineeritud kasutajale '%-.32s' masinast '%-.64s' tabelile '%-.64s'" fre "Un tel droit n'est pas défini pour l'utilisateur '%-.32s' sur l'hôte '%-.64s' sur la table '%-.64s'" - ger "Keine solche Berechtigung für User '%-.32s' auf Host '%-.64s' an Tabelle '%-.64s'" + ger "Eine solche Berechtigung ist für User '%-.32s' auf Host '%-.64s' an Tabelle '%-.64s' nicht definiert" hun "A '%-.32s' felhasznalo szamara a '%-.64s' host '%-.64s' tablajaban ez a parancs nem engedelyezett" ita "GRANT non definita per l'utente '%-.32s' dalla macchina '%-.64s' sulla tabella '%-.64s'" kor "»ç¿ëÀÚ '%-.32s'(È£½ºÆ® '%-.64s')´Â Å×À̺í '%-.64s'¸¦ »ç¿ëÇϱâ À§ÇÏ¿© Á¤ÀÇµÈ ½ÂÀÎÀº ¾ø½À´Ï´Ù. " @@ -3455,7 +3455,7 @@ ER_SYNTAX_ERROR 42000 eng "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use" est "Viga SQL süntaksis" fre "Erreur de syntaxe" - ger "Fehler in der SQL-Syntax. Bitte die korrekte Syntax im Handbuch nachschlagen (diese kann für verschiedene Server-Versionen unterschiedlich sein)" + ger "Fehler in der SQL-Syntax. Bitte die korrekte Syntax im Handbuch nachschlagen" greek "You have an error in your SQL syntax" hun "Szintaktikai hiba" ita "Errore di sintassi nella query SQL" @@ -3538,7 +3538,7 @@ ER_NET_PACKET_TOO_LARGE 08S01 eng "Got a packet bigger than 'max_allowed_packet' bytes" est "Saabus suurem pakett kui lubatud 'max_allowed_packet' muutujaga" fre "Paquet plus grand que 'max_allowed_packet' reçu" - ger "Empfangenes Paket ist größer als 'max_allowed_packet'" + ger "Empfangenes Paket ist größer als 'max_allowed_packet' Bytes" hun "A kapott csomag nagyobb, mint a maximalisan engedelyezett: 'max_allowed_packet'" ita "Ricevuto un pacchetto piu` grande di 'max_allowed_packet'" kor "'max_allowed_packet'º¸´Ù ´õÅ« ÆÐŶÀ» ¹Þ¾Ò½À´Ï´Ù." @@ -3556,7 +3556,7 @@ ER_NET_READ_ERROR_FROM_PIPE 08S01 eng "Got a read error from the connection pipe" est "Viga ühendustoru lugemisel" fre "Erreur de lecture reçue du pipe de connection" - ger "Lese-Fehler bei einer Kommunikations-Pipe" + ger "Lese-Fehler bei einer Verbindungs-Pipe" hun "Olvasasi hiba a kapcsolat soran" ita "Rilevato un errore di lettura dalla pipe di connessione" kor "¿¬°á ÆÄÀÌÇÁ·ÎºÎÅÍ ¿¡·¯°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù." @@ -3700,7 +3700,7 @@ ER_TOO_LONG_STRING 42000 eng "Result string is longer than 'max_allowed_packet' bytes" est "Tulemus on pikem kui lubatud 'max_allowed_packet' muutujaga" fre "La chaîne résultat est plus grande que 'max_allowed_packet'" - ger "Ergebnis ist länger als 'max_allowed_packet'" + ger "Ergebnis-String ist länger als 'max_allowed_packet' Bytes" hun "Ez eredmeny sztring nagyobb, mint a lehetseges maximum: 'max_allowed_packet'" ita "La stringa di risposta e` piu` lunga di 'max_allowed_packet'" por "'String' resultante é mais longa do que 'max_allowed_packet'" @@ -3717,7 +3717,7 @@ ER_TABLE_CANT_HANDLE_BLOB 42000 eng "The used table type doesn't support BLOB/TEXT columns" est "Valitud tabelitüüp ei toeta BLOB/TEXT tüüpi välju" fre "Ce type de table ne supporte pas les colonnes BLOB/TEXT" - ger "Der verwendete Tabellentyp unterstützt keine BLOB- und TEXT-Spalten" + ger "Der verwendete Tabellentyp unterstützt keine BLOB- und TEXT-Felder" hun "A hasznalt tabla tipus nem tamogatja a BLOB/TEXT mezoket" ita "Il tipo di tabella usata non supporta colonne di tipo BLOB/TEXT" por "Tipo de tabela usado não permite colunas BLOB/TEXT" @@ -3734,7 +3734,7 @@ ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 42000 eng "The used table type doesn't support AUTO_INCREMENT columns" est "Valitud tabelitüüp ei toeta AUTO_INCREMENT tüüpi välju" fre "Ce type de table ne supporte pas les colonnes AUTO_INCREMENT" - ger "Der verwendete Tabellentyp unterstützt keine AUTO_INCREMENT-Spalten" + ger "Der verwendete Tabellentyp unterstützt keine AUTO_INCREMENT-Felder" hun "A hasznalt tabla tipus nem tamogatja az AUTO_INCREMENT tipusu mezoket" ita "Il tipo di tabella usata non supporta colonne di tipo AUTO_INCREMENT" por "Tipo de tabela usado não permite colunas AUTO_INCREMENT" @@ -3751,7 +3751,7 @@ ER_DELAYED_INSERT_TABLE_LOCKED eng "INSERT DELAYED can't be used with table '%-.64s' because it is locked with LOCK TABLES" est "INSERT DELAYED ei saa kasutada tabeli '%-.64s' peal, kuna see on lukustatud LOCK TABLES käsuga" fre "INSERT DELAYED ne peut être utilisé avec la table '%-.64s', car elle est verrouée avec LOCK TABLES" - ger "INSERT DELAYED kann nicht auf Tabelle '%-.64s' angewendet werden, da diese mit LOCK TABLES gesperrt ist" + ger "INSERT DELAYED kann für Tabelle '%-.64s' nicht verwendet werden, da sie mit LOCK TABLES gesperrt ist" greek "INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES" hun "Az INSERT DELAYED nem hasznalhato a '%-.64s' tablahoz, mert a tabla zarolt (LOCK TABLES)" ita "L'inserimento ritardato (INSERT DELAYED) non puo` essere usato con la tabella '%-.64s', perche` soggetta a lock da 'LOCK TABLES'" @@ -3792,7 +3792,7 @@ ER_WRONG_KEY_COLUMN 42000 eng "The used storage engine can't index column '%-.64s'" est "Tabelihandler ei oska indekseerida tulpa '%-.64s'" fre "Le handler de la table ne peut indexé la colonne '%-.64s'" - ger "Der verwendete Tabellen-Handler kann die Spalte '%-.64s' nicht indizieren" + ger "Die verwendete Speicher-Engine kann die Spalte '%-.64s' nicht indizieren" greek "The used table handler can't index column '%-.64s'" hun "A hasznalt tablakezelo nem tudja a '%-.64s' mezot indexelni" ita "Il gestore delle tabelle non puo` indicizzare la colonna '%-.64s'" @@ -3839,7 +3839,7 @@ ER_DUP_UNIQUE 23000 eng "Can't write, because of unique constraint, to table '%-.64s'" est "Ei suuda kirjutada tabelisse '%-.64s', kuna see rikub ühesuse kitsendust" fre "Écriture impossible à cause d'un index UNIQUE sur la table '%-.64s'" - ger "Schreiben in Tabelle '%-.64s' nicht möglich wegen einer eindeutigen Beschränkung (unique constraint)" + ger "Schreiben in Tabelle '%-.64s' nicht möglich wegen einer Eindeutigkeitsbeschränkung (unique constraint)" hun "A '%-.64s' nem irhato, az egyedi mezok miatt" ita "Impossibile scrivere nella tabella '%-.64s' per limitazione di unicita`" por "Não pode gravar, devido à restrição UNIQUE, na tabela '%-.64s'" @@ -3880,7 +3880,7 @@ ER_PRIMARY_CANT_HAVE_NULL 42000 eng "All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead" est "Kõik PRIMARY KEY peavad olema määratletud NOT NULL piiranguga; vajadusel kasuta UNIQUE tüüpi võtit" fre "Toutes les parties d'un index PRIMARY KEY doivent être NOT NULL; Si vous avez besoin d'un NULL dans l'index, utilisez un index UNIQUE" - ger "Alle Teile eines PRIMARY KEY müssen als NOT NULL definiert sein. Wenn NULL in einem Schlüssel verwendet wird, muss ein UNIQUE-Schlüssel verwendet werden" + ger "Alle Teile eines PRIMARY KEY müssen als NOT NULL definiert sein. Wenn NULL in einem Schlüssel benötigt wird, muss ein UNIQUE-Schlüssel verwendet werden" hun "Az elsodleges kulcs teljes egeszeben csak NOT NULL tipusu lehet; Ha NULL mezot szeretne a kulcskent, hasznalja inkabb a UNIQUE-ot" ita "Tutte le parti di una chiave primaria devono essere dichiarate NOT NULL; se necessitano valori NULL nelle chiavi utilizzare UNIQUE" por "Todas as partes de uma chave primária devem ser não-nulas. Se você precisou usar um valor nulo (NULL) em uma chave, use a cláusula UNIQUE em seu lugar" @@ -3914,7 +3914,7 @@ ER_REQUIRES_PRIMARY_KEY 42000 eng "This table type requires a primary key" est "Antud tabelitüüp nõuab primaarset võtit" fre "Ce type de table nécessite une clé primaire (PRIMARY KEY)" - ger "Dieser Tabellentyp benötigt einen PRIMARY KEY" + ger "Dieser Tabellentyp benötigt einen Primärschlüssel (PRIMARY KEY)" hun "Az adott tablatipushoz elsodleges kulcs hasznalata kotelezo" ita "Questo tipo di tabella richiede una chiave primaria" por "Este tipo de tabela requer uma chave primária" @@ -3948,7 +3948,7 @@ ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE eng "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column" est "Katse muuta tabelit turvalises rezhiimis ilma WHERE klauslita" fre "Vous êtes en mode 'safe update' et vous essayez de faire un UPDATE sans clause WHERE utilisant un index" - ger "MySQL läuft im sicheren Aktualisierungsmodus (safe update mode). Sie haben versucht, eine Tabelle zu aktualisieren, ohne in der WHERE-Klausel eine KEY-Spalte anzugeben" + ger "MySQL läuft im sicheren Aktualisierungsmodus (safe update mode). Sie haben versucht, eine Tabelle zu aktualisieren, ohne in der WHERE-Klausel ein KEY-Feld anzugeben" hun "On a biztonsagos update modot hasznalja, es WHERE that uses a KEY column" ita "In modalita` 'safe update' si e` cercato di aggiornare una tabella senza clausola WHERE su una chiave" por "Você está usando modo de atualização seguro e tentou atualizar uma tabela sem uma cláusula WHERE que use uma coluna chave" @@ -4100,7 +4100,7 @@ ER_NEW_ABORTING_CONNECTION 08S01 eng "Aborted connection %ld to db: '%-.64s' user: '%-.32s' host: '%-.64s' (%-.64s)" est "Ühendus katkestatud %ld andmebaas: '%-.64s' kasutaja: '%-.32s' masin: '%-.64s' (%-.64s)" fre "Connection %ld avortée vers la bd: '%-.64s' utilisateur: '%-.32s' hôte: '%-.64s' (%-.64s)" - ger "Verbindungsabbruch %ld zur Datenbank '%-.64s'. Benutzer: '%-.32s', Host: '%-.64s' (%-.64s)" + ger "Abbruch der Verbindung %ld zur Datenbank '%-.64s'. Benutzer: '%-.32s', Host: '%-.64s' (%-.64s)" ita "Interrotta la connessione %ld al db: ''%-.64s' utente: '%-.32s' host: '%-.64s' (%-.64s)" por "Conexão %ld abortada para banco de dados '%-.64s' - usuário '%-.32s' - 'host' '%-.64s' ('%-.64s')" rus "ðÒÅÒ×ÁÎÏ ÓÏÅÄÉÎÅÎÉÅ %ld Ë ÂÁÚÅ ÄÁÎÎÙÈ '%-.64s' ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s' Ó ÈÏÓÔÁ '%-.64s' (%-.64s)" @@ -4137,7 +4137,7 @@ ER_INDEX_REBUILD nla "Gefaald tijdens heropbouw index van gedumpte tabel '%-.64s'" eng "Failed rebuilding the index of dumped table '%-.64s'" fre "La reconstruction de l'index de la table copiée '%-.64s' a échoué" - ger "Neuerstellung des Indizes der Dump-Tabelle '%-.64s' fehlgeschlagen" + ger "Neuerstellung des Index der Dump-Tabelle '%-.64s' fehlgeschlagen" greek "Failed rebuilding the index of dumped table '%-.64s'" hun "Failed rebuilding the index of dumped table '%-.64s'" ita "Fallita la ricostruzione dell'indice della tabella copiata '%-.64s'" @@ -4195,7 +4195,7 @@ ER_FT_MATCHING_KEY_NOT_FOUND eng "Can't find FULLTEXT index matching the column list" est "Ei suutnud leida FULLTEXT indeksit, mis kattuks kasutatud tulpadega" fre "Impossible de trouver un index FULLTEXT correspondant à cette liste de colonnes" - ger "Kann keinen FULLTEXT-Index finden, der der Spaltenliste entspricht" + ger "Kann keinen FULLTEXT-Index finden, der der Feldliste entspricht" ita "Impossibile trovare un indice FULLTEXT che corrisponda all'elenco delle colonne" por "Não pode encontrar um índice para o texto todo que combine com a lista de colunas" rus "îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÐÏÌÎÏÔÅËÓÔÏ×ÙÊ (FULLTEXT) ÉÎÄÅËÓ, ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÊ ÓÐÉÓËÕ ÓÔÏÌÂÃÏ×" @@ -4283,7 +4283,7 @@ ER_TRANS_CACHE_FULL eng "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again" est "Mitme lausendiga transaktsioon nõudis rohkem ruumi kui lubatud 'max_binlog_cache_size' muutujaga. Suurenda muutuja väärtust ja proovi uuesti" fre "Cette transaction à commandes multiples nécessite plus de 'max_binlog_cache_size' octets de stockage, augmentez cette variable de mysqld et réessayez" - ger "Transaktionen, die aus mehreren Befehlen bestehen, benötigen mehr als 'max_binlog_cache_size' Bytes an Speicher. Diese mysqld-Variable bitte vergrössern und erneut versuchen" + ger "Transaktionen, die aus mehreren Befehlen bestehen, benötigten mehr als 'max_binlog_cache_size' Bytes an Speicher. Btte vergrössern Sie diese Server-Variable versuchen Sie es noch einmal" ita "La transazione a comandi multipli (multi-statement) ha richiesto piu` di 'max_binlog_cache_size' bytes di disco: aumentare questa variabile di mysqld e riprovare" por "Transações multi-declaradas (multi-statement transactions) requeriram mais do que o valor limite (max_binlog_cache_size) de bytes para armazenagem. Aumente o valor desta variável do mysqld e tente novamente" rus "ôÒÁÎÚÁËÃÉÉ, ×ËÌÀÞÁÀÝÅÊ ÂÏÌØÛÏÅ ËÏÌÉÞÅÓÔ×Ï ËÏÍÁÎÄ, ÐÏÔÒÅÂÏ×ÁÌÏÓØ ÂÏÌÅÅ ÞÅÍ 'max_binlog_cache_size' ÂÁÊÔ. õ×ÅÌÉÞØÔÅ ÜÔÕ ÐÅÒÅÍÅÎÎÕÀ ÓÅÒ×ÅÒÁ mysqld É ÐÏÐÒÏÂÕÊÔÅ ÅÝÅ ÒÁÚ" @@ -4295,7 +4295,7 @@ ER_SLAVE_MUST_STOP nla "Deze operatie kan niet worden uitgevoerd met een actieve slave, doe eerst STOP SLAVE" eng "This operation cannot be performed with a running slave; run STOP SLAVE first" fre "Cette opération ne peut être réalisée avec un esclave actif, faites STOP SLAVE d'abord" - ger "Diese Operation kann nicht bei einem aktiven Slave durchgeführt werden. Bitte zuerst STOP SLAVE ausführen" + ger "Diese Operation kann bei einem aktiven Slave nicht durchgeführt werden. Bitte zuerst STOP SLAVE ausführen" ita "Questa operazione non puo' essere eseguita con un database 'slave' che gira, lanciare prima STOP SLAVE" por "Esta operação não pode ser realizada com um 'slave' em execução. Execute STOP SLAVE primeiro" rus "üÔÕ ÏÐÅÒÁÃÉÀ ÎÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÐÒÉ ÒÁÂÏÔÁÀÝÅÍ ÐÏÔÏËÅ ÐÏÄÞÉÎÅÎÎÏÇÏ ÓÅÒ×ÅÒÁ. óÎÁÞÁÌÁ ×ÙÐÏÌÎÉÔÅ STOP SLAVE" @@ -4332,6 +4332,7 @@ ER_BAD_SLAVE ER_MASTER_INFO eng "Could not initialize master info structure; more error messages can be found in the MySQL error log" fre "Impossible d'initialiser les structures d'information de maître, vous trouverez des messages d'erreur supplémentaires dans le journal des erreurs de MySQL" + ger "Konnte Master-Info-Struktur nicht initialisieren. Weitere Fehlermeldungen können im MySQL-Error-Log eingesehen werden" serbian "Nisam mogao da inicijalizujem informacionu strukturu glavnog servera, proverite da li imam privilegije potrebne za pristup file-u 'master.info'" swe "Kunde inte initialisera replikationsstrukturerna. See MySQL fel fil för mera information" ER_SLAVE_THREAD @@ -4339,7 +4340,7 @@ ER_SLAVE_THREAD nla "Kon slave thread niet aanmaken, controleer systeem resources" eng "Could not create slave thread; check system resources" fre "Impossible de créer une tâche esclave, vérifiez les ressources système" - ger "Konnte keinen Slave-Thread starten. Bitte System-Ressourcen überprüfen" + ger "Konnte Slave-Thread nicht starten. Bitte System-Ressourcen überprüfen" ita "Impossibile creare il thread 'slave', controllare le risorse di sistema" por "Não conseguiu criar 'thread' de 'slave'. Verifique os recursos do sistema" rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÐÏÔÏË ÐÏÄÞÉÎÅÎÎÏÇÏ ÓÅÒ×ÅÒÁ. ðÒÏ×ÅÒØÔÅ ÓÉÓÔÅÍÎÙÅ ÒÅÓÕÒÓÙ" @@ -4353,7 +4354,7 @@ ER_TOO_MANY_USER_CONNECTIONS 42000 eng "User %-.64s already has more than 'max_user_connections' active connections" est "Kasutajal %-.64s on juba rohkem ühendusi kui lubatud 'max_user_connections' muutujaga" fre "L'utilisateur %-.64s possède déjà plus de 'max_user_connections' connections actives" - ger "Benutzer '%-.64s' hat mehr als max_user_connections aktive Verbindungen" + ger "Benutzer '%-.64s' hat mehr als 'max_user_connections' aktive Verbindungen" ita "L'utente %-.64s ha gia' piu' di 'max_user_connections' connessioni attive" por "Usuário '%-.64s' já possui mais que o valor máximo de conexões (max_user_connections) ativas" rus "õ ÐÏÌØÚÏ×ÁÔÅÌÑ %-.64s ÕÖÅ ÂÏÌØÛÅ ÞÅÍ 'max_user_connections' ÁËÔÉ×ÎÙÈ ÓÏÅÄÉÎÅÎÉÊ" @@ -4409,7 +4410,7 @@ ER_READ_ONLY_TRANSACTION 25000 eng "Update locks cannot be acquired during a READ UNCOMMITTED transaction" est "Uuenduslukke ei saa kasutada READ UNCOMMITTED transaktsiooni käigus" fre "Un verrou en update ne peut être acquit pendant une transaction READ UNCOMMITTED" - ger "Während einer READ UNCOMMITED-Transaktion können keine UPDATE-Sperren angefordert werden" + ger "Während einer READ-UNCOMMITTED-Transaktion können keine UPDATE-Sperren angefordert werden" ita "I lock di aggiornamento non possono essere acquisiti durante una transazione 'READ UNCOMMITTED'" por "Travamentos de atualização não podem ser obtidos durante uma transação de tipo READ UNCOMMITTED" rus "âÌÏËÉÒÏ×ËÉ ÏÂÎÏ×ÌÅÎÉÊ ÎÅÌØÚÑ ÐÏÌÕÞÉÔØ × ÐÒÏÃÅÓÓÅ ÞÔÅÎÉÑ ÎÅ ÐÒÉÎÑÔÏÊ (× ÒÅÖÉÍÅ READ UNCOMMITTED) ÔÒÁÎÚÁËÃÉÉ" @@ -4463,7 +4464,7 @@ ER_NO_PERMISSION_TO_CREATE_USER 42000 eng "'%-.32s'@'%-.64s' is not allowed to create new users" est "Kasutajal '%-.32s'@'%-.64s' ei ole lubatud luua uusi kasutajaid" fre "'%-.32s'@'%-.64s' n'est pas autorisé à créer de nouveaux utilisateurs" - ger "'%-.32s'@'%-.64s' is nicht berechtigt, neue Benutzer hinzuzufügen" + ger "'%-.32s'@'%-.64s' ist nicht berechtigt, neue Benutzer hinzuzufügen" ita "A '%-.32s'@'%-.64s' non e' permesso creare nuovi utenti" por "Não é permitido a '%-.32s'@'%-.64s' criar novos usuários" rus "'%-.32s'@'%-.64s' ÎÅ ÒÁÚÒÅÛÁÅÔÓÑ ÓÏÚÄÁ×ÁÔØ ÎÏ×ÙÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ" @@ -4488,7 +4489,7 @@ ER_LOCK_DEADLOCK 40001 eng "Deadlock found when trying to get lock; try restarting transaction" est "Lukustamisel tekkis tupik (deadlock); alusta transaktsiooni otsast" fre "Deadlock découvert en essayant d'obtenir les verrous : essayez de redémarrer la transaction" - ger "Beim Versuch, eine Sperre anzufordern, ist ein Deadlock aufgetreten. Versuchen Sie, die Transaktion erneut zu starten" + ger "Beim Versuch, eine Sperre anzufordern, ist ein Deadlock aufgetreten. Versuchen Sie, die Transaktion neu zu starten" ita "Trovato deadlock durante il lock; Provare a far ripartire la transazione" por "Encontrado um travamento fatal (deadlock) quando tentava obter uma trava. Tente reiniciar a transação." rus "÷ÏÚÎÉËÌÁ ÔÕÐÉËÏ×ÁÑ ÓÉÔÕÁÃÉÑ × ÐÒÏÃÅÓÓÅ ÐÏÌÕÞÅÎÉÑ ÂÌÏËÉÒÏ×ËÉ; ðÏÐÒÏÂÕÊÔÅ ÐÅÒÅÚÁÐÕÓÔÉÔØ ÔÒÁÎÚÁËÃÉÀ" @@ -4512,7 +4513,7 @@ ER_CANNOT_ADD_FOREIGN nla "Kan foreign key beperking niet toevoegen" eng "Cannot add foreign key constraint" fre "Impossible d'ajouter des contraintes d'index externe" - ger "Fremdschlüssel-Beschränkung konnte nicht hinzugefügt werden" + ger "Fremdschlüssel-Beschränkung kann nicht hinzugefügt werden" ita "Impossibile aggiungere il vincolo di integrita' referenziale (foreign key constraint)" por "Não pode acrescentar uma restrição de chave estrangeira" rus "îÅ×ÏÚÍÏÖÎÏ ÄÏÂÁ×ÉÔØ ÏÇÒÁÎÉÞÅÎÉÑ ×ÎÅÛÎÅÇÏ ËÌÀÞÁ" @@ -4523,7 +4524,7 @@ ER_NO_REFERENCED_ROW 23000 nla "Kan onderliggende rij niet toevoegen: foreign key beperking gefaald" eng "Cannot add or update a child row: a foreign key constraint fails" fre "Impossible d'ajouter un enregistrement fils : une constrainte externe l'empèche" - ger "Hinzufügen eines Kind-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl" + ger "Hinzufügen oder Aktualisieren eines Kind-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl" greek "Cannot add a child row: a foreign key constraint fails" hun "Cannot add a child row: a foreign key constraint fails" ita "Impossibile aggiungere la riga: un vincolo d'integrita' referenziale non e' soddisfatto" @@ -4535,7 +4536,7 @@ ER_NO_REFERENCED_ROW 23000 ER_ROW_IS_REFERENCED 23000 eng "Cannot delete or update a parent row: a foreign key constraint fails" fre "Impossible de supprimer un enregistrement père : une constrainte externe l'empèche" - ger "Löschen eines Eltern-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl" + ger "Löschen oder Aktualisieren eines Eltern-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl" greek "Cannot delete a parent row: a foreign key constraint fails" hun "Cannot delete a parent row: a foreign key constraint fails" ita "Impossibile cancellare la riga: un vincolo d'integrita' referenziale non e' soddisfatto" @@ -4589,7 +4590,7 @@ ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 21000 nla "De gebruikte SELECT commando's hebben een verschillend aantal kolommen" eng "The used SELECT statements have a different number of columns" est "Tulpade arv kasutatud SELECT lausetes ei kattu" - ger "Die verwendeten SELECT-Befehle liefern eine unterschiedliche Anzahl von Spalten zurück" + ger "Die verwendeten SELECT-Befehle liefern unterschiedliche Anzahlen von Feldern zurück" ita "La SELECT utilizzata ha un numero di colonne differente" por "Os comandos SELECT usados têm diferente número de colunas" rus "éÓÐÏÌØÚÏ×ÁÎÎÙÅ ÏÐÅÒÁÔÏÒÙ ×ÙÂÏÒËÉ (SELECT) ÄÁÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×" @@ -4600,7 +4601,7 @@ ER_CANT_UPDATE_WITH_READLOCK nla "Kan de query niet uitvoeren vanwege een conflicterende read lock" eng "Can't execute the query because you have a conflicting read lock" est "Ei suuda täita päringut konfliktse luku tõttu" - ger "Augrund eines READ LOCK-Konflikts kann die Abfrage nicht ausgeführt werden" + ger "Augrund eines READ-LOCK-Konflikts kann die Abfrage nicht ausgeführt werden" ita "Impossibile eseguire la query perche' c'e' un conflitto con in lock di lettura" por "Não posso executar a consulta porque você tem um conflito de travamento de leitura" rus "îÅ×ÏÚÍÏÖÎÏ ÉÓÐÏÌÎÉÔØ ÚÁÐÒÏÓ, ÐÏÓËÏÌØËÕ Õ ×ÁÓ ÕÓÔÁÎÏ×ÌÅÎÙ ËÏÎÆÌÉËÔÕÀÝÉÅ ÂÌÏËÉÒÏ×ËÉ ÞÔÅÎÉÑ" @@ -4640,7 +4641,7 @@ ER_USER_LIMIT_REACHED 42000 ER_SPECIFIC_ACCESS_DENIED_ERROR 42000 nla "Toegang geweigerd. U moet het %-.128s privilege hebben voor deze operatie" eng "Access denied; you need the %-.128s privilege for this operation" - ger "Befehl nicht zulässig. Hierfür wird die Berechtigung %-.128s benötigt" + ger "Kein Zugriff. Hierfür wird die Berechtigung %-.128s benötigt" ita "Accesso non consentito. Serve il privilegio %-.128s per questa operazione" por "Acesso negado. Você precisa o privilégio %-.128s para essa operação" rus "÷ ÄÏÓÔÕÐÅ ÏÔËÁÚÁÎÏ. ÷ÁÍ ÎÕÖÎÙ ÐÒÉ×ÉÌÅÇÉÉ %-.128s ÄÌÑ ÜÔÏÊ ÏÐÅÒÁÃÉÉ" @@ -4722,7 +4723,7 @@ ER_NOT_SUPPORTED_YET 42000 ER_MASTER_FATAL_ERROR_READING_BINLOG nla "Kreeg fatale fout %d: '%-.128s' van master tijdens lezen van data uit binaire log" eng "Got fatal error %d: '%-.128s' from master when reading data from binary log" - ger "Schwerer Fehler %d: '%-.128s vom Master beim Lesen des binären Logs aufgetreten" + ger "Schwerer Fehler %d: '%-.128s vom Master beim Lesen des binären Logs" ita "Errore fatale %d: '%-.128s' dal master leggendo i dati dal log binario" por "Obteve fatal erro %d: '%-.128s' do master quando lendo dados do binary log" rus "ðÏÌÕÞÅÎÁ ÎÅÉÓÐÒÁ×ÉÍÁÑ ÏÛÉÂËÁ %d: '%-.128s' ÏÔ ÇÏÌÏ×ÎÏÇÏ ÓÅÒ×ÅÒÁ × ÐÒÏÃÅÓÓÅ ×ÙÂÏÒËÉ ÄÁÎÎÙÈ ÉÚ Ä×ÏÉÞÎÏÇÏ ÖÕÒÎÁÌÁ" @@ -4737,11 +4738,12 @@ ER_SLAVE_IGNORED_TABLE ER_INCORRECT_GLOBAL_LOCAL_VAR eng "Variable '%-.64s' is a %s variable" serbian "Incorrect foreign key definition for '%-.64s': %s" + ger "Variable '%-.64s' ist eine %s-Variable" spa "Variable '%-.64s' es una %s variable" swe "Variabel '%-.64s' är av typ %s" ER_WRONG_FK_DEF 42000 eng "Incorrect foreign key definition for '%-.64s': %s" - ger "Falsche Fremdschlüssel-Definition für '%-64s': %s" + ger "Falsche Fremdschlüssel-Definition für '%-.64s': %s" por "Definição errada da chave estrangeira para '%-.64s': %s" spa "Equivocada definición de llave extranjera para '%-.64s': %s" swe "Felaktig FOREIGN KEY-definition för '%-.64s': %s" @@ -4753,7 +4755,7 @@ ER_KEY_REF_DO_NOT_MATCH_TABLE_REF swe "Nyckelreferensen och tabellreferensen stämmer inte överens" ER_OPERAND_COLUMNS 21000 eng "Operand should contain %d column(s)" - ger "Operand solle %d Spalte(n) enthalten" + ger "Operand sollte %d Spalte(n) enthalten" rus "ïÐÅÒÁÎÄ ÄÏÌÖÅÎ ÓÏÄÅÒÖÁÔØ %d ËÏÌÏÎÏË" spa "Operando debe tener %d columna(s)" ukr "ïÐÅÒÁÎÄ ÍÁ¤ ÓËÌÁÄÁÔÉÓÑ Ú %d ÓÔÏ×Âæ×" @@ -4789,7 +4791,7 @@ ER_CYCLIC_REFERENCE ukr "ãÉË̦ÞÎÅ ÐÏÓÉÌÁÎÎÑ ÎÁ ЦÄÚÁÐÉÔ" ER_AUTO_CONVERT eng "Converting column '%s' from %s to %s" - ger "Spalte '%s' wird von %s nach %s umgewandelt" + ger "Feld '%s' wird von %s nach %s umgewandelt" por "Convertendo coluna '%s' de %s para %s" rus "ðÒÅÏÂÒÁÚÏ×ÁÎÉÅ ÐÏÌÑ '%s' ÉÚ %s × %s" spa "Convirtiendo columna '%s' de %s para %s" @@ -4831,7 +4833,7 @@ ER_NOT_SUPPORTED_AUTH_MODE 08004 swe "Klienten stöder inte autentiseringsprotokollet som begärts av servern; överväg uppgradering av klientprogrammet." ER_SPATIAL_CANT_HAVE_NULL 42000 eng "All parts of a SPATIAL index must be NOT NULL" - ger "Alle Teile eines SPATIAL index müssen als NOT NULL deklariert sein" + ger "Alle Teile eines SPATIAL-Index müssen als NOT NULL deklariert sein" por "Todas as partes de uma SPATIAL index devem ser NOT NULL" spa "Todas las partes de una SPATIAL index deben ser NOT NULL" swe "Alla delar av en SPATIAL index måste vara NOT NULL" @@ -4855,12 +4857,12 @@ ER_SLAVE_WAS_NOT_RUNNING swe "Slaven har redan stoppat" ER_TOO_BIG_FOR_UNCOMPRESS eng "Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)" - ger "Unkomprimierte Daten sind zu groß. Die maximale Größe beträgt %d" + ger "Unkomprimierte Daten sind zu groß. Die maximale Größe beträgt %d (wahrscheinlich wurde die Länge der unkomprimierten Daten beschädigt)" por "Tamanho muito grande dos dados des comprimidos. O máximo tamanho é %d. (provavelmente, o comprimento dos dados descomprimidos está corrupto)" spa "Tamaño demasiado grande para datos descomprimidos. El máximo tamaño es %d. (probablemente, extensión de datos descomprimidos fué corrompida)" ER_ZLIB_Z_MEM_ERROR eng "ZLIB: Not enough memory" - ger "ZLIB: Steht nicht genug Speicher zur Verfügung" + ger "ZLIB: Nicht genug Speicher" por "ZLIB: Não suficiente memória disponível" spa "Z_MEM_ERROR: No suficiente memoria para zlib" ER_ZLIB_Z_BUF_ERROR @@ -4882,27 +4884,27 @@ ER_CUT_VALUE_GROUP_CONCAT ukr "%d line(s) was(were) cut by group_concat()" ER_WARN_TOO_FEW_RECORDS 01000 eng "Row %ld doesn't contain data for all columns" - ger "Anzahl der Datensätze in Zeile %ld geringer als Anzahl der Spalten" + ger "Zeile %ld enthält nicht für alle Felder Daten" por "Conta de registro é menor que a conta de coluna na linha %ld" spa "Línea %ld no contiene datos para todas las columnas" ER_WARN_TOO_MANY_RECORDS 01000 eng "Row %ld was truncated; it contained more data than there were input columns" - ger "Anzahl der Datensätze in Zeile %ld größer als Anzahl der Spalten" + ger "Zeile %ld gekürzt, die Zeile enthielt mehr Daten, als es Eingabefelder gibt" por "Conta de registro é maior que a conta de coluna na linha %ld" spa "Línea %ld fué truncada; La misma contine mas datos que las que existen en las columnas de entrada" ER_WARN_NULL_TO_NOTNULL 22004 eng "Column set to default value; NULL supplied to NOT NULL column '%s' at row %ld" - ger "Daten abgeschnitten, NULL für NOT NULL-Spalte '%s' in Zeile %ld angegeben" + ger "Feld auf Vorgabewert gesetzt, da NULL für NOT-NULL-Feld '%s' in Zeile %ld angegeben" por "Dado truncado, NULL fornecido para NOT NULL coluna '%s' na linha %ld" spa "Datos truncado, NULL suministrado para NOT NULL columna '%s' en la línea %ld" ER_WARN_DATA_OUT_OF_RANGE 22003 eng "Out of range value adjusted for column '%s' at row %ld" - ger "Daten abgeschnitten, außerhalb des Wertebereichs für Spalte '%s' in Zeile %ld" + ger "Daten abgeschnitten, außerhalb des Wertebereichs für Feld '%s' in Zeile %ld" por "Dado truncado, fora de alcance para coluna '%s' na linha %ld" spa "Datos truncados, fuera de gama para columna '%s' en la línea %ld" WARN_DATA_TRUNCATED 01000 eng "Data truncated for column '%s' at row %ld" - ger "Daten abgeschnitten für Spalte '%s' in Zeile %ld" + ger "Daten abgeschnitten für Feld '%s' in Zeile %ld" por "Dado truncado para coluna '%s' na linha %ld" spa "Datos truncados para columna '%s' en la línea %ld" ER_WARN_USING_OTHER_HANDLER @@ -4913,40 +4915,40 @@ ER_WARN_USING_OTHER_HANDLER swe "Använder handler %s för tabell '%s'" ER_CANT_AGGREGATE_2COLLATIONS eng "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'" - ger "Unerlaubte Vermischung der Kollationen (%s,%s) und (%s,%s) für die Operation '%s'" + ger "Unerlaubte Mischung von Sortierreihenfolgen (%s, %s) und (%s, %s) für Operation '%s'" por "Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'" spa "Ilegal mezcla de collations (%s,%s) y (%s,%s) para operación '%s'" ER_DROP_USER eng "Cannot drop one or more of the requested users" ger "Kann einen oder mehrere der angegebenen Benutzer nicht löschen" ER_REVOKE_GRANTS - eng "Can't revoke all privileges, grant for one or more of the requested users" - ger "Kann nicht alle Berechtigungen widerrufen, grant for one or more of the requested users" + eng "Can't revoke all privileges for one or more of the requested users" + ger "Kann nicht alle Berechtigungen widerrufen, die für einen oder mehrere Benutzer gewährt wurden" por "Não pode revocar todos os privilégios, grant para um ou mais dos usuários pedidos" spa "No puede revocar todos los privilegios, derecho para uno o mas de los usuarios solicitados" ER_CANT_AGGREGATE_3COLLATIONS eng "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'" - ger "Unerlaubte Vermischung der Kollationen (%s,%s), (%s,%s), (%s,%s) für die Operation '%s'" + ger "Unerlaubte Mischung von Sortierreihenfolgen (%s, %s), (%s, %s), (%s, %s) für Operation '%s'" por "Ilegal combinação de collations (%s,%s), (%s,%s), (%s,%s) para operação '%s'" spa "Ilegal mezcla de collations (%s,%s), (%s,%s), (%s,%s) para operación '%s'" ER_CANT_AGGREGATE_NCOLLATIONS eng "Illegal mix of collations for operation '%s'" - ger "Unerlaubte Vermischung der Kollationen für die Operation '%s'" + ger "Unerlaubte Mischung von Sortierreihenfolgen für Operation '%s'" por "Ilegal combinação de collations para operação '%s'" spa "Ilegal mezcla de collations para operación '%s'" ER_VARIABLE_IS_NOT_STRUCT eng "Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)" - ger "Variable '%-.64s' ist keine Variablen-Komponenten (kann nicht als XXXX.variablen_name verwendet werden)" + ger "Variable '%-.64s' ist keine Variablen-Komponente (kann nicht als XXXX.variablen_name verwendet werden)" por "Variável '%-.64s' não é uma variável componente (Não pode ser usada como XXXX.variável_nome)" spa "Variable '%-.64s' no es una variable componente (No puede ser usada como XXXX.variable_name)" ER_UNKNOWN_COLLATION eng "Unknown collation: '%-.64s'" - ger "Unbekannte Kollation: '%-.64s'" + ger "Unbekannte Sortierreihenfolge: '%-.64s'" por "Collation desconhecida: '%-.64s'" spa "Collation desconocida: '%-.64s'" ER_SLAVE_IGNORED_SSL_PARAMS eng "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started" - ger "SSL-Parameter in CHANGE MASTER werden ignoriert, weil dieser MySQL-Slave ohne SSL-Unterstützung kompiliert wurde. Sie können aber später verwendet werden, wenn der MySQL-Slave mit SSL gestartet wird" + ger "SSL-Parameter in CHANGE MASTER werden ignoriert, weil dieser MySQL-Slave ohne SSL-Unterstützung kompiliert wurde. Sie können aber später verwendet werden, wenn ein MySQL-Slave mit SSL gestartet wird" por "SSL parâmetros em CHANGE MASTER são ignorados porque este escravo MySQL foi compilado sem o SSL suporte. Os mesmos podem ser usados mais tarde quando o escravo MySQL com SSL seja iniciado." spa "Parametros SSL en CHANGE MASTER son ignorados porque este slave MySQL fue compilado sin soporte SSL; pueden ser usados despues cuando el slave MySQL con SSL sea inicializado" ER_SERVER_IS_IN_SECURE_AUTH_MODE @@ -4969,7 +4971,7 @@ ER_BAD_SLAVE_UNTIL_COND spa "Parametro equivocado o combinación de parametros para START SLAVE UNTIL" ER_MISSING_SKIP_SLAVE eng "It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you will get problems if you get an unexpected slave's mysqld restart" - ger "Es wird empfohlen, mit --skip-slave-start zu starten, wenn mit START SLAVE UNTIL eine Schritt-für-Schritt-Replikation ausgeführt wird. Ansonsten gibt es Probleme, wenn der Slave-Server unerwartet neu startet" + ger "Es wird empfohlen, mit --skip-slave-start zu starten, wenn mit START SLAVE UNTIL eine Schritt-für-Schritt-Replikation ausgeführt wird. Ansonsten gibt es Probleme, wenn ein Slave-Server unerwartet neu startet" por "É recomendado para rodar com --skip-slave-start quando fazendo replicação passo-por-passo com START SLAVE UNTIL, de outra forma você não está seguro em caso de inesperada reinicialição do mysqld escravo" spa "Es recomendado rodar con --skip-slave-start cuando haciendo replicación step-by-step con START SLAVE UNTIL, a menos que usted no esté seguro en caso de inesperada reinicialización del mysqld slave" ER_UNTIL_COND_IGNORED @@ -4979,16 +4981,19 @@ ER_UNTIL_COND_IGNORED spa "SQL thread no es inicializado tal que opciones UNTIL son ignoradas" ER_WRONG_NAME_FOR_INDEX 42000 eng "Incorrect index name '%-.100s'" + ger "Falscher Indexname '%-.100s'" por "Incorreto nome de índice '%-.100s'" spa "Nombre de índice incorrecto '%-.100s'" swe "Felaktigt index namn '%-.100s'" ER_WRONG_NAME_FOR_CATALOG 42000 eng "Incorrect catalog name '%-.100s'" + ger "Falscher Katalogname '%-.100s'" por "Incorreto nome de catálogo '%-.100s'" spa "Nombre de catalog incorrecto '%-.100s'" swe "Felaktigt katalog namn '%-.100s'" ER_WARN_QC_RESIZE eng "Query cache failed to set size %lu; new query cache size is %lu" + ger "Änderung der Query-Cache-Größe auf %lu fehlgeschlagen; neue Query-Cache-Größe ist %lu" por "Falha em Query cache para configurar tamanho %lu, novo tamanho de query cache é %lu" rus "ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu, ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %lu" spa "Query cache fallada para configurar tamaño %lu, nuevo tamaño de query cache es %lu" @@ -4996,28 +5001,34 @@ ER_WARN_QC_RESIZE ukr "ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu, ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %lu" ER_BAD_FT_COLUMN eng "Column '%-.64s' cannot be part of FULLTEXT index" + ger "Feld '%-.64s' kann nicht Teil eines FULLTEXT-Index sein" por "Coluna '%-.64s' não pode ser parte de índice FULLTEXT" spa "Columna '%-.64s' no puede ser parte de FULLTEXT index" swe "Kolumn '%-.64s' kan inte vara del av ett FULLTEXT index" ER_UNKNOWN_KEY_CACHE eng "Unknown key cache '%-.100s'" + ger "Unbekannter Schlüssel-Cache '%-.100s'" por "Key cache desconhecida '%-.100s'" spa "Desconocida key cache '%-.100s'" swe "Okänd nyckel cache '%-.100s'" ER_WARN_HOSTNAME_WONT_WORK eng "MySQL is started in --skip-name-resolve mode; you must restart it without this switch for this grant to work" + ger "MySQL wurde mit --skip-name-resolve gestartet. Diese Option darf nicht verwendet werden, damit diese Rechtevergabe möglich ist" por "MySQL foi inicializado em modo --skip-name-resolve. Você necesita reincializá-lo sem esta opção para este grant funcionar" spa "MySQL esta inicializado en modo --skip-name-resolve. Usted necesita reinicializarlo sin esta opción para este derecho funcionar" ER_UNKNOWN_STORAGE_ENGINE 42000 eng "Unknown table engine '%s'" + ger "Unbekannte Speicher-Engine '%s'" por "Motor de tabela desconhecido '%s'" spa "Desconocido motor de tabla '%s'" ER_WARN_DEPRECATED_SYNTAX eng "'%s' is deprecated; use '%s' instead" + ger "'%s' ist veraltet. Bitte benutzen Sie '%s'" por "'%s' é desatualizado. Use '%s' em seu lugar" spa "'%s' está desaprobado, use '%s' en su lugar" ER_NON_UPDATABLE_TABLE eng "The target table %-.100s of the %s is not updatable" + ger "Die Zieltabelle %-.100s von %s ist nicht aktualisierbar" por "A tabela destino %-.100s do %s não é atualizável" rus "ôÁÂÌÉÃÁ %-.100s × %s ÎÅ ÍÏÖÅÔ ÉÚÍÅÎÑÔÓÑ" spa "La tabla destino %-.100s del %s no es actualizable" @@ -5025,400 +5036,572 @@ ER_NON_UPDATABLE_TABLE ukr "ôÁÂÌÉÃÑ %-.100s Õ %s ÎÅ ÍÏÖÅ ÏÎÏ×ÌÀ×ÁÔÉÓØ" ER_FEATURE_DISABLED eng "The '%s' feature is disabled; you need MySQL built with '%s' to have it working" + ger "Das Feature '%s' ist ausgeschaltet, Sie müssen MySQL mit '%s' übersetzen, damit es verfügbar ist" por "O recurso '%s' foi desativado; você necessita MySQL construído com '%s' para ter isto funcionando" spa "El recurso '%s' fue deshabilitado; usted necesita construir MySQL con '%s' para tener eso funcionando" swe "'%s' är inte aktiverad; För att aktivera detta måste du bygga om MySQL med '%s' definerad" ER_OPTION_PREVENTS_STATEMENT eng "The MySQL server is running with the %s option so it cannot execute this statement" + ger "Der MySQL-Server läuft mit der Option %s und kann diese Anweisung deswegen nicht ausführen" por "O servidor MySQL está rodando com a opção %s razão pela qual não pode executar esse commando" spa "El servidor MySQL está rodando con la opción %s tal que no puede ejecutar este comando" swe "MySQL är startad med --skip-grant-tables. Pga av detta kan du inte använda detta kommando" ER_DUPLICATED_VALUE_IN_TYPE eng "Column '%-.100s' has duplicated value '%-.64s' in %s" + ger "Feld '%-.100s' hat doppelten Wert '%-.64s' in %s" por "Coluna '%-.100s' tem valor duplicado '%-.64s' em %s" spa "Columna '%-.100s' tiene valor doblado '%-.64s' en %s" ER_TRUNCATED_WRONG_VALUE 22007 eng "Truncated incorrect %-.32s value: '%-.128s'" + ger "Falscher %-.32s-Wert gekürzt: '%-.128s'" por "Truncado errado %-.32s valor: '%-.128s'" spa "Equivocado truncado %-.32s valor: '%-.128s'" ER_TOO_MUCH_AUTO_TIMESTAMP_COLS eng "Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause" + ger "Fehlerhafte Tabellendefinition. Es kann nur eine einzige TIMESTAMP-Spalte mit CURRENT_TIMESTAMP als DEFAULT oder in einer ON-UPDATE-Klausel geben" por "Incorreta definição de tabela; Pode ter somente uma coluna TIMESTAMP com CURRENT_TIMESTAMP em DEFAULT ou ON UPDATE cláusula" spa "Incorrecta definición de tabla; Solamente debe haber una columna TIMESTAMP con CURRENT_TIMESTAMP en DEFAULT o ON UPDATE cláusula" ER_INVALID_ON_UPDATE eng "Invalid ON UPDATE clause for '%-.64s' column" + ger "Ungültige ON-UPDATE-Klausel für Spalte '%-.64s'" por "Inválida cláusula ON UPDATE para campo '%-.64s'" spa "Inválido ON UPDATE cláusula para campo '%-.64s'" ER_UNSUPPORTED_PS eng "This command is not supported in the prepared statement protocol yet" + ger "Dieser Befehl wird im Protokoll für vorbereitete Anweisungen noch nicht unterstützt" ER_GET_ERRMSG dan "Modtog fejl %d '%-.100s' fra %s" eng "Got error %d '%-.100s' from %s" + ger "Fehler %d '%-.100s' von %s" nor "Mottok feil %d '%-.100s' fa %s" norwegian-ny "Mottok feil %d '%-.100s' fra %s" ER_GET_TEMPORARY_ERRMSG dan "Modtog temporary fejl %d '%-.100s' fra %s" eng "Got temporary error %d '%-.100s' from %s" + ger "Temporärer Fehler %d '%-.100s' von %s" nor "Mottok temporary feil %d '%-.100s' fra %s" norwegian-ny "Mottok temporary feil %d '%-.100s' fra %s" ER_UNKNOWN_TIME_ZONE eng "Unknown or incorrect time zone: '%-.64s'" + ger "Unbekannte oder falsche Zeitzone: '%-.64s'" ER_WARN_INVALID_TIMESTAMP eng "Invalid TIMESTAMP value in column '%s' at row %ld" + ger "Ungültiger TIMESTAMP-Wert in Feld '%s', Zeile %ld" ER_INVALID_CHARACTER_STRING eng "Invalid %s character string: '%.64s'" + ger "Ungültiger %s-Zeichen-String: '%.64s'" ER_WARN_ALLOWED_PACKET_OVERFLOWED eng "Result of %s() was larger than max_allowed_packet (%ld) - truncated" + ger "Ergebnis von %s() war größer als max_allowed_packet (%ld) Bytes und wurde deshalb gekürzt" ER_CONFLICTING_DECLARATIONS eng "Conflicting declarations: '%s%s' and '%s%s'" + ger "Widersprüchliche Deklarationen: '%s%s' und '%s%s'" ER_SP_NO_RECURSIVE_CREATE 2F003 eng "Can't create a %s from within another stored routine" + ger "Kann kein %s innerhalb einer anderen gespeicherten Routine erzeugen" ER_SP_ALREADY_EXISTS 42000 eng "%s %s already exists" + ger "%s %s existiert bereits" ER_SP_DOES_NOT_EXIST 42000 eng "%s %s does not exist" + ger "%s %s existiert nicht" ER_SP_DROP_FAILED eng "Failed to DROP %s %s" + ger "DROP %s %s ist fehlgeschlagen" ER_SP_STORE_FAILED eng "Failed to CREATE %s %s" + ger "CREATE %s %s ist fehlgeschlagen" ER_SP_LILABEL_MISMATCH 42000 eng "%s with no matching label: %s" + ger "%s ohne passende Marke: %s" ER_SP_LABEL_REDEFINE 42000 eng "Redefining label %s" + ger "Neudefinition der Marke %s" ER_SP_LABEL_MISMATCH 42000 eng "End-label %s without match" + ger "Ende-Marke %s ohne zugehörigen Anfang" ER_SP_UNINIT_VAR 01000 eng "Referring to uninitialized variable %s" + ger "Zugriff auf nichtinitialisierte Variable %s" ER_SP_BADSELECT 0A000 eng "PROCEDURE %s can't return a result set in the given context" + ger "PROCEDURE %s kann im gegebenen Kontext keine Ergebnismenge zurückgeben" ER_SP_BADRETURN 42000 eng "RETURN is only allowed in a FUNCTION" + ger "RETURN ist nur innerhalb einer FUNCTION erlaubt" ER_SP_BADSTATEMENT 0A000 eng "%s is not allowed in stored procedures" + ger "%s ist in gespeicherten Prozeduren nicht erlaubt" ER_UPDATE_LOG_DEPRECATED_IGNORED 42000 eng "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored" + ger "Das Update-Log ist veraltet und wurde durch das Binär-Log ersetzt. SET SQL_LOG_UPDATE wird ignoriert" ER_UPDATE_LOG_DEPRECATED_TRANSLATED 42000 eng "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been translated to SET SQL_LOG_BIN" + ger "Das Update-Log ist veraltet und wurde durch das Binär-Log ersetzt. SET SQL_LOG_UPDATE wurde in SET SQL_LOG_BIN übersetzt" ER_QUERY_INTERRUPTED 70100 eng "Query execution was interrupted" + ger "Ausführung der Abfrage wurde unterbrochen" ER_SP_WRONG_NO_OF_ARGS 42000 eng "Incorrect number of arguments for %s %s; expected %u, got %u" + ger "Falsche Anzahl von Argumenten für %s %s; erwarte %u, erhalte %u" ER_SP_COND_MISMATCH 42000 eng "Undefined CONDITION: %s" + ger "Undefinierte CONDITION: %s" ER_SP_NORETURN 42000 eng "No RETURN found in FUNCTION %s" + ger "Kein RETURN in FUNCTION %s gefunden" ER_SP_NORETURNEND 2F005 eng "FUNCTION %s ended without RETURN" + ger "FUNCTION %s endete ohne RETURN" ER_SP_BAD_CURSOR_QUERY 42000 eng "Cursor statement must be a SELECT" + ger "Cursor-Anweisung muss ein SELECT sein" ER_SP_BAD_CURSOR_SELECT 42000 eng "Cursor SELECT must not have INTO" + ger "Cursor-SELECT darf kein INTO haben" ER_SP_CURSOR_MISMATCH 42000 eng "Undefined CURSOR: %s" + ger "Undefinierter CURSOR: %s" ER_SP_CURSOR_ALREADY_OPEN 24000 eng "Cursor is already open" + ger "Cursor ist schon geöffnet" ER_SP_CURSOR_NOT_OPEN 24000 eng "Cursor is not open" + ger "Cursor ist nicht geöffnet" ER_SP_UNDECLARED_VAR 42000 eng "Undeclared variable: %s" + ger "Nicht deklarierte Variable: %s" ER_SP_WRONG_NO_OF_FETCH_ARGS eng "Incorrect number of FETCH variables" + ger "Falsche Anzahl von FETCH-Variablen" ER_SP_FETCH_NO_DATA 02000 eng "No data to FETCH" + ger "Keine Daten mit FETCH abzuholen" ER_SP_DUP_PARAM 42000 eng "Duplicate parameter: %s" + ger "Doppelter Parameter: %s" ER_SP_DUP_VAR 42000 eng "Duplicate variable: %s" + ger "Doppelte Variable: %s" ER_SP_DUP_COND 42000 eng "Duplicate condition: %s" + ger "Doppelte Bedingung: %s" ER_SP_DUP_CURS 42000 eng "Duplicate cursor: %s" + ger "Doppelter Cursor: %s" ER_SP_CANT_ALTER eng "Failed to ALTER %s %s" + ger "ALTER %s %s fehlgeschlagen" ER_SP_SUBSELECT_NYI 0A000 eng "Subselect value not supported" + ger "Subselect-Wert wird nicht unterstützt" ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG 0A000 eng "%s is not allowed in stored function or trigger" + ger "%s ist in gespeicherten Funktionen und in Triggern nicht erlaubt" ER_SP_VARCOND_AFTER_CURSHNDLR 42000 eng "Variable or condition declaration after cursor or handler declaration" + ger "Deklaration einer Variablen oder einer Bedingung nach der Deklaration eines Cursors oder eines Handlers" ER_SP_CURSOR_AFTER_HANDLER 42000 eng "Cursor declaration after handler declaration" + ger "Deklaration eines Cursors nach der Deklaration eines Handlers" ER_SP_CASE_NOT_FOUND 20000 eng "Case not found for CASE statement" + ger "Fall für CASE-Anweisung nicht gefunden" ER_FPARSER_TOO_BIG_FILE eng "Configuration file '%-.64s' is too big" + ger "Konfigurationsdatei '%-.64s' ist zu groß" rus "óÌÉÛËÏÍ ÂÏÌØÛÏÊ ËÏÎÆÉÇÕÒÁÃÉÏÎÎÙÊ ÆÁÊÌ '%-.64s'" ukr "úÁÎÁÄÔÏ ×ÅÌÉËÉÊ ËÏÎƦÇÕÒÁæÊÎÉÊ ÆÁÊÌ '%-.64s'" ER_FPARSER_BAD_HEADER eng "Malformed file type header in file '%-.64s'" + ger "Nicht wohlgeformter Dateityp-Header in Datei '%-.64s'" rus "îÅ×ÅÒÎÙÊ ÚÁÇÏÌÏ×ÏË ÔÉÐÁ ÆÁÊÌÁ '%-.64s'" ukr "îÅצÒÎÉÊ ÚÁÇÏÌÏ×ÏË ÔÉÐÕ Õ ÆÁÊ̦ '%-.64s'" ER_FPARSER_EOF_IN_COMMENT eng "Unexpected end of file while parsing comment '%-.64s'" + ger "Unerwartetes Dateiende beim Parsen des Kommentars '%-.64s'" rus "îÅÏÖÉÄÁÎÎÙÊ ËÏÎÅà ÆÁÊÌÁ × ËÏÍÅÎÔÁÒÉÉ '%-.64s'" ukr "îÅÓÐÏĦ×ÁÎÎÉÊ Ë¦ÎÅÃØ ÆÁÊÌÕ Õ ËÏÍÅÎÔÁÒ¦ '%-.64s'" ER_FPARSER_ERROR_IN_PARAMETER eng "Error while parsing parameter '%-.64s' (line: '%-.64s')" + ger "Fehler beim Parsen des Parameters '%-.64s' (Zeile: '%-.64s')" rus "ïÛÉÂËÁ ÐÒÉ ÒÁÓÐÏÚÎÁ×ÁÎÉÉ ÐÁÒÁÍÅÔÒÁ '%-.64s' (ÓÔÒÏËÁ: '%-.64s')" ukr "ðÏÍÉÌËÁ × ÒÏÓЦÚÎÁ×ÁÎΦ ÐÁÒÁÍÅÔÒÕ '%-.64s' (ÒÑÄÏË: '%-.64s')" ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER eng "Unexpected end of file while skipping unknown parameter '%-.64s'" + ger "Unerwartetes Dateiende beim Überspringen des unbekannten Parameters '%-.64s'" rus "îÅÏÖÉÄÁÎÎÙÊ ËÏÎÅà ÆÁÊÌÁ ÐÒÉ ÐÒÏÐÕÓËÅ ÎÅÉÚ×ÅÓÔÎÏÇÏ ÐÁÒÁÍÅÔÒÁ '%-.64s'" ukr "îÅÓÐÏĦ×ÁÎÎÉÊ Ë¦ÎÅÃØ ÆÁÊÌÕ Õ ÓÐÒϦ ÐÒÏÍÉÎÕÔÉ ÎÅצÄÏÍÉÊ ÐÁÒÁÍÅÔÒ '%-.64s'" ER_VIEW_NO_EXPLAIN eng "EXPLAIN/SHOW can not be issued; lacking privileges for underlying table" + ger "EXPLAIN/SHOW kann nicht verlangt werden. Rechte für zugrunde liegende Tabelle fehlen" rus "EXPLAIN/SHOW ÎÅ ÍÏÖÅÔ ÂÙÔØ ×ÙÐÏÌÎÅÎÎÏ; ÎÅÄÏÓÔÁÔÏÞÎÏ ÐÒÁ× ÎÁ ÔÁËÂÌÉÃÙ ÚÁÐÒÏÓÁ" ukr "EXPLAIN/SHOW ÎÅ ÍÏÖÅ ÂÕÔÉ ×¦ËÏÎÁÎÏ; ÎÅÍÁ¤ ÐÒÁ× ÎÁ ÔÉÂÌÉæ ÚÁÐÉÔÕ" ER_FRM_UNKNOWN_TYPE eng "File '%-.64s' has unknown type '%-.64s' in its header" + ger "Datei '%-.64s' hat unbekannten Typ '%-.64s' im Header" rus "æÁÊÌ '%-.64s' ÓÏÄÅÒÖÉÔ ÎÅÉÚ×ÅÓÔÎÙÊ ÔÉÐ '%-.64s' × ÚÁÇÏÌÏ×ËÅ" ukr "æÁÊÌ '%-.64s' ÍÁ¤ ÎÅצÄÏÍÉÊ ÔÉÐ '%-.64s' Õ ÚÁÇÏÌÏ×ËÕ" ER_WRONG_OBJECT eng "'%-.64s.%-.64s' is not %s" + ger "'%-.64s.%-.64s' ist nicht %s" rus "'%-.64s.%-.64s' - ÎÅ %s" ukr "'%-.64s.%-.64s' ÎÅ ¤ %s" ER_NONUPDATEABLE_COLUMN eng "Column '%-.64s' is not updatable" + ger "Feld '%-.64s' ist nicht aktualisierbar" rus "óÔÏÌÂÅà '%-.64s' ÎÅ ÏÂÎÏ×ÌÑÅÍÙÊ" ukr "óÔÏ×ÂÅÃØ '%-.64s' ÎÅ ÍÏÖÅ ÂÕÔÉ ÚÍÉÎÅÎÉÊ" ER_VIEW_SELECT_DERIVED eng "View's SELECT contains a subquery in the FROM clause" + ger "SELECT der View enthält eine Subquery in der FROM-Klausel" rus "View SELECT ÓÏÄÅÒÖÉÔ ÐÏÄÚÁÐÒÏÓ × ËÏÎÓÔÒÕËÃÉÉ FROM" ukr "View SELECT ÍÁ¤ ЦÄÚÁÐÉÔ Õ ËÏÎÓÔÒÕËæ§ FROM" ER_VIEW_SELECT_CLAUSE eng "View's SELECT contains a '%s' clause" + ger "SELECT der View enthält eine '%s'-Klausel" rus "View SELECT ÓÏÄÅÒÖÉÔ ËÏÎÓÔÒÕËÃÉÀ '%s'" ukr "View SELECT ÍÁ¤ ËÏÎÓÔÒÕËæÀ '%s'" ER_VIEW_SELECT_VARIABLE eng "View's SELECT contains a variable or parameter" + ger "SELECT der View enthält eine Variable oder einen Parameter" rus "View SELECT ÓÏÄÅÒÖÉÔ ÐÅÒÅÍÅÎÎÕÀ ÉÌÉ ÐÁÒÁÍÅÔÒ" ukr "View SELECT ÍÁ¤ ÚÍÉÎÎÕ ÁÂÏ ÐÁÒÁÍÅÔÅÒ" ER_VIEW_SELECT_TMPTABLE eng "View's SELECT refers to a temporary table '%-.64s'" + ger "SELECT der View verweist auf eine temporäre Tabelle '%-.64s'" rus "View SELECT ÓÏÄÅÒÖÉÔ ÓÓÙÌËÕ ÎÁ ×ÒÅÍÅÎÎÕÀ ÔÁÂÌÉÃÕ '%-.64s'" ukr "View SELECT ×ÉËÏÒÉÓÔÏ×Õ¤ ÔÉÍÞÁÓÏ×Õ ÔÁÂÌÉÃÀ '%-.64s'" ER_VIEW_WRONG_LIST eng "View's SELECT and view's field list have different column counts" + ger "SELECT- und Feldliste der Views haben unterschiedliche Anzahlen von Spalten" rus "View SELECT É ÓÐÉÓÏË ÐÏÌÅÊ view ÉÍÅÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×" ukr "View SELECT ¦ ÐÅÒÅÌ¦Ë ÓÔÏ×ÂÃ¦× view ÍÁÀÔØ Ò¦ÚÎÕ Ë¦ÌØ˦ÓÔØ ÓËÏ×Âæ×" ER_WARN_VIEW_MERGE eng "View merge algorithm can't be used here for now (assumed undefined algorithm)" + ger "View-Merge-Algorithmus kann hier momentan nicht verwendet werden (undefinierter Algorithmus wird angenommen)" rus "áÌÇÏÒÉÔÍ ÓÌÉÑÎÉÑ view ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎ ÓÅÊÞÁÓ (ÁÌÇÏÒÉÔÍ ÂÕÄÅÔ ÎÅÏÐÅÒÅÄÅÌÅÎÎÙÍ)" ukr "áÌÇÏÒÉÔÍ ÚÌÉ×ÁÎÎÑ view ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÉÊ ÚÁÒÁÚ (ÁÌÇÏÒÉÔÍ ÂÕÄÅ ÎÅ×ÉÚÎÁÞÅÎÉÊ)" ER_WARN_VIEW_WITHOUT_KEY eng "View being updated does not have complete key of underlying table in it" + ger "Die aktualisierte View enthält nicht den vollständigen Schlüssel der zugrunde liegenden Tabelle" rus "ïÂÎÏ×ÌÑÅÍÙÊ view ÎÅ ÓÏÄÅÒÖÉÔ ËÌÀÞÁ ÉÓÐÏÌØÚÏ×ÁÎÎÙÈ(ÏÊ) × ÎÅÍ ÔÁÂÌÉÃ(Ù)" ukr "View, ÝÏ ÏÎÏ×ÌÀÅÔØÓÑ, ΊͦÓÔÉÔØ ÐÏ×ÎÏÇÏ ËÌÀÞÁ ÔÁÂÌÉæ(Ø), ÝÏ ×ÉËÏÒ¦ÓÔÁÎÁ × ÎØÀÏÍÕ" ER_VIEW_INVALID - eng "View '%-.64s.%-.64s' references invalid table(s) or column(s) or function(s)" - rus "View '%-.64s.%-.64s' ÓÓÙÌÁÅÔÓÑ ÎÁ ÎÅÓÕÝÅÓÔ×ÕÀÝÉÅ ÔÁÂÌÉÃÙ ÉÌÉ ÓÔÏÌÂÃÙ ÉÌÉ ÆÕÎËÃÉÉ" + eng "View '%-.64s.%-.64s' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them" ER_SP_NO_DROP_SP eng "Can't drop or alter a %s from within another stored routine" + ger "Kann eine %s nicht von innerhalb einer anderen gespeicherten Routine löschen oder ändern" ER_SP_GOTO_IN_HNDLR eng "GOTO is not allowed in a stored procedure handler" + ger "GOTO ist im Handler einer gespeicherten Prozedur nicht erlaubt" ER_TRG_ALREADY_EXISTS eng "Trigger already exists" + ger "Trigger existiert bereits" ER_TRG_DOES_NOT_EXIST eng "Trigger does not exist" + ger "Trigger existiert nicht" ER_TRG_ON_VIEW_OR_TEMP_TABLE eng "Trigger's '%-.64s' is view or temporary table" + ger "'%-.64s' des Triggers ist View oder temporäre Tabelle" ER_TRG_CANT_CHANGE_ROW eng "Updating of %s row is not allowed in %strigger" + ger "Aktualisieren einer %s-Zeile ist in einem %-Trigger nicht erlaubt" ER_TRG_NO_SUCH_ROW_IN_TRG eng "There is no %s row in %s trigger" + ger "Es gibt keine %s-Zeile im %s-Trigger" ER_NO_DEFAULT_FOR_FIELD eng "Field '%-.64s' doesn't have a default value" + ger "Feld '%-.64s' hat keinen Vorgabewert" ER_DIVISION_BY_ZERO 22012 eng "Division by 0" + ger "Division durch 0" ER_TRUNCATED_WRONG_VALUE_FOR_FIELD eng "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld" + ger "Falscher %-.32s-Wert: '%-.128s' für Feld '%.64s' in Zeile %ld" ER_ILLEGAL_VALUE_FOR_TYPE 22007 eng "Illegal %s '%-.64s' value found during parsing" + ger "Nicht zulässiger %s-Wert '%-.64s' beim Parsen gefunden" ER_VIEW_NONUPD_CHECK eng "CHECK OPTION on non-updatable view '%-.64s.%-.64s'" + ger "CHECK OPTION auf nicht-aktualisierbarem View '%-.64s.%-.64s'" rus "CHECK OPTION ÄÌÑ ÎÅÏÂÎÏ×ÌÑÅÍÏÇÏ VIEW '%-.64s.%-.64s'" ukr "CHECK OPTION ÄÌÑ VIEW '%-.64s.%-.64s' ÝÏ ÎÅ ÍÏÖÅ ÂÕÔÉ ÏÎÏ×ÌÅÎÎÉÍ" ER_VIEW_CHECK_FAILED eng "CHECK OPTION failed '%-.64s.%-.64s'" + ger "CHECK OPTION fehlgeschlagen: '%-.64s.%-.64s'" rus "ÐÒÏ×ÅÒËÁ CHECK OPTION ÄÌÑ VIEW '%-.64s.%-.64s' ÐÒÏ×ÁÌÉÌÁÓØ" ukr "ðÅÒÅצÒËÁ CHECK OPTION ÄÌÑ VIEW '%-.64s.%-.64s' ÎÅ ÐÒÏÊÛÌÁ" ER_PROCACCESS_DENIED_ERROR 42000 eng "%-.16s command denied to user '%-.32s'@'%-.64s' for routine '%-.64s'" + ger "Befehl %-.16s nicht zulässig für Benutzer '%-.32s'@'%-.64s' in Routine '%-.64s'" ER_RELAY_LOG_FAIL eng "Failed purging old relay logs: %s" + ger "Bereinigen alter Relais-Logs fehlgeschlagen: %s" ER_PASSWD_LENGTH eng "Password hash should be a %d-digit hexadecimal number" + ger "Passwort-Hash sollte eine Hexdaezimalzahl mit %d Stellen sein" ER_UNKNOWN_TARGET_BINLOG eng "Target log not found in binlog index" + ger "Ziel-Log im Binlog-Index nicht gefunden" ER_IO_ERR_LOG_INDEX_READ eng "I/O error reading log index file" + ger "Fehler beim Lesen der Log-Index-Datei" ER_BINLOG_PURGE_PROHIBITED eng "Server configuration does not permit binlog purge" + ger "Server-Konfiguration erlaubt keine Binlog-Bereinigung" ER_FSEEK_FAIL eng "Failed on fseek()" + ger "fseek() fehlgeschlagen" ER_BINLOG_PURGE_FATAL_ERR eng "Fatal error during log purge" + ger "Schwerwiegender Fehler bei der Log-Bereinigung" ER_LOG_IN_USE eng "A purgeable log is in use, will not purge" + ger "Ein zu bereinigendes Log wird gerade benutzt, daher keine Bereinigung" ER_LOG_PURGE_UNKNOWN_ERR eng "Unknown error during log purge" + ger "Unbekannter Fehler bei Log-Bereinigung" ER_RELAY_LOG_INIT eng "Failed initializing relay log position: %s" + ger "Initialisierung der Relais-Log-Position fehlgeschlagen: %s" ER_NO_BINARY_LOGGING eng "You are not using binary logging" + ger "Sie verwenden keine Binärlogs" ER_RESERVED_SYNTAX eng "The '%-.64s' syntax is reserved for purposes internal to the MySQL server" + ger "Die Schreibweise '%-.64s' ist für interne Zwecke des MySQL-Servers reserviert" ER_WSAS_FAILED eng "WSAStartup Failed" + ger "WSAStartup fehlgeschlagen" ER_DIFF_GROUPS_PROC - eng "Can't handle procedures with differents groups yet" + eng "Can't handle procedures with different groups yet" + ger "Kann Prozeduren mit unterschiedlichen Gruppen noch nicht verarbeiten" ER_NO_GROUP_FOR_PROC eng "Select must have a group with this procedure" + ger "SELECT muss bei dieser Prozedur ein GROUP BY haben" ER_ORDER_WITH_PROC eng "Can't use ORDER clause with this procedure" + ger "Kann bei dieser Prozedur keine ORDER-BY-Klausel verwenden" ER_LOGGING_PROHIBIT_CHANGING_OF eng "Binary logging and replication forbid changing the global server %s" + ger "Binärlogs und Replikation verhindern Wechsel des globalen Servers %s" ER_NO_FILE_MAPPING eng "Can't map file: %-.64s, errno: %d" + ger "Kann Datei nicht abbilden: %-.64s, Fehler: %d" ER_WRONG_MAGIC eng "Wrong magic in %-.64s" + ger "Falsche magische Zahlen in %-.64s" ER_PS_MANY_PARAM eng "Prepared statement contains too many placeholders" + ger "Vorbereitete Anweisung enthält zu viele Platzhalter" ER_KEY_PART_0 eng "Key part '%-.64s' length cannot be 0" + ger "Länge des Schlüsselteils '%-.64s' kann nicht 0 sein" ER_VIEW_CHECKSUM eng "View text checksum failed" + ger "View-Text-Prüfsumme fehlgeschlagen" rus "ðÒÏ×ÅÒËÁ ËÏÎÔÒÏÌØÎÏÊ ÓÕÍÍÙ ÔÅËÓÔÁ VIEW ÐÒÏ×ÁÌÉÌÁÓØ" ukr "ðÅÒÅצÒËÁ ËÏÎÔÒÏÌØÎϧ ÓÕÍÉ ÔÅËÓÔÕ VIEW ÎÅ ÐÒÏÊÛÌÁ" ER_VIEW_MULTIUPDATE eng "Can not modify more than one base table through a join view '%-.64s.%-.64s'" + ger "Kann nicht mehr als eine Basistabelle über Join-View '%-.64s.%-.64s' ändern" rus "îÅÌØÚÑ ÉÚÍÅÎÉÔØ ÂÏÌØÛÅ ÞÅÍ ÏÄÎÕ ÂÁÚÏ×ÕÀ ÔÁÂÌÉÃÕ ÉÓÐÏÌØÚÕÑ ÍÎÏÇÏÔÁÂÌÉÞÎÙÊ VIEW '%-.64s.%-.64s'" ukr "îÅÍÏÖÌÉ×Ï ÏÎÏ×ÉÔÉ Â¦ÌØÛ ÎÉÖ ÏÄÎÕ ÂÁÚÏ×Õ ÔÁÂÌÉÃÀ ×ÙËÏÒÉÓÔÏ×ÕÀÞÉ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔ¦ÔØ ÄÅ˦ÌØËÁ ÔÁÂÌÉÃØ" ER_VIEW_NO_INSERT_FIELD_LIST eng "Can not insert into join view '%-.64s.%-.64s' without fields list" + ger "Kann nicht ohne Feldliste in Join-View '%-.64s.%-.64s' einfügen" rus "îÅÌØÚÑ ×ÓÔÁ×ÌÑÔØ ÚÁÐÉÓÉ × ÍÎÏÇÏÔÁÂÌÉÞÎÙÊ VIEW '%-.64s.%-.64s' ÂÅÚ ÓÐÉÓËÁ ÐÏÌÅÊ" ukr "îÅÍÏÖÌÉ×Ï ÕÓÔÁ×ÉÔÉ ÒÑÄËÉ Õ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔÉÔØ ÄÅ˦ÌØËÁ ÔÁÂÌÉÃØ, ÂÅÚ ÓÐÉÓËÕ ÓÔÏ×Âæ×" ER_VIEW_DELETE_MERGE_VIEW eng "Can not delete from join view '%-.64s.%-.64s'" + ger "Kann nicht aus Join-View '%-.64s.%-.64s' löschen" rus "îÅÌØÚÑ ÕÄÁÌÑÔØ ÉÚ ÍÎÏÇÏÔÁÂÌÉÞÎÏÇÏ VIEW '%-.64s.%-.64s'" ukr "îÅÍÏÖÌÉ×Ï ×ÉÄÁÌÉÔÉ ÒÑÄËÉ Õ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔÉÔØ ÄÅ˦ÌØËÁ ÔÁÂÌÉÃØ" ER_CANNOT_USER eng "Operation %s failed for %.256s" - ger "Das Kommando %s scheiterte für %.256s" + ger "Operation %s schlug fehl für %.256s" norwegian-ny "Operation %s failed for '%.256s'" ER_XAER_NOTA XAE04 eng "XAER_NOTA: Unknown XID" + ger "XAER_NOTA: Unbekannte XID" ER_XAER_INVAL XAE05 eng "XAER_INVAL: Invalid arguments (or unsupported command)" + ger "XAER_INVAL: Ungültige Argumente (oder nicht unterstützter Befehl)" ER_XAER_RMFAIL XAE07 eng "XAER_RMFAIL: The command cannot be executed when global transaction is in the %.64s state" + ger "XAER_RMFAIL: DEr Befehl kann nicht ausgeführt werden, wenn die globale Transaktion im Zustand %.64s ist" rus "XAER_RMFAIL: ÜÔÕ ËÏÍÁÎÄÕ ÎÅÌØÚÑ ×ÙÐÏÌÎÑÔØ ËÏÇÄÁ ÇÌÏÂÁÌØÎÁÑ ÔÒÁÎÚÁËÃÉÑ ÎÁÈÏÄÉÔÓÑ × ÓÏÓÔÏÑÎÉÉ '%.64s'" ER_XAER_OUTSIDE XAE09 eng "XAER_OUTSIDE: Some work is done outside global transaction" + ger "XAER_OUTSIDE: Einige Arbeiten werden außerhalb der globalen Transaktion verrichtet" ER_XAER_RMERR XAE03 eng "XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency" + ger "XAER_RMERR: Schwerwiegender Fehler im Transaktionszweig - prüfen Sie Ihre Daten auf Konsistenz" ER_XA_RBROLLBACK XA100 eng "XA_RBROLLBACK: Transaction branch was rolled back" + ger "XA_RBROLLBACK: Transaktionszweig wurde zurückgerollt" ER_NONEXISTING_PROC_GRANT 42000 eng "There is no such grant defined for user '%-.32s' on host '%-.64s' on routine '%-.64s'" + ger "Es gibt diese Berechtigung für Benutzer '%-.32s' auf Host '%-.64s' für Routine '%-.64s' nicht" ER_PROC_AUTO_GRANT_FAIL eng "Failed to grant EXECUTE and ALTER ROUTINE privileges" + ger "Gewährung von EXECUTE- und ALTER-ROUTINE-Rechten fehlgeschlagen" ER_PROC_AUTO_REVOKE_FAIL eng "Failed to revoke all privileges to dropped routine" + ger "Rücknahme aller Rechte für die gelöschte Routine fehlgeschlagen" ER_DATA_TOO_LONG 22001 eng "Data too long for column '%s' at row %ld" + ger "Daten zu lang für Feld '%s' in Zeile %ld" ER_SP_BAD_SQLSTATE 42000 eng "Bad SQLSTATE: '%s'" + ger "Ungültiger SQLSTATE: '%s'" ER_STARTUP eng "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d %s" + ger "%s: bereit für Verbindungen.\nVersion: '%s' Socket: '%s' Port: %d %s" ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR eng "Can't load value from file with fixed size rows to variable" + ger "Kann Wert aus Datei mit Zeilen fester Größe nicht in Variable laden" ER_CANT_CREATE_USER_WITH_GRANT 42000 eng "You are not allowed to create a user with GRANT" + ger "Sie dürfen keinen Benutzer mit GRANT anlegen" ER_WRONG_VALUE_FOR_TYPE eng "Incorrect %-.32s value: '%-.128s' for function %-.32s" + ger "Falscher %-.32s-Wert: '%-.128s' für Funktion %-.32s" ER_TABLE_DEF_CHANGED eng "Table definition has changed, please retry transaction" + ger "Tabellendefinition wurde geändert, bitte starten Sie die Transaktion neu" ER_SP_DUP_HANDLER 42000 eng "Duplicate handler declared in the same block" + ger "Doppelter Handler im selben Block deklariert" ER_SP_NOT_VAR_ARG 42000 eng "OUT or INOUT argument %d for routine %s is not a variable" + ger "OUT- oder INOUT-Argument %d für Routine %s ist keine Variable" ER_SP_NO_RETSET 0A000 eng "Not allowed to return a result set from a %s" + ger "Rückgabe einer Ergebnismenge aus einer %s ist nicht erlaubt" ER_CANT_CREATE_GEOMETRY_OBJECT 22003 eng "Cannot get geometry object from data you send to the GEOMETRY field" + ger "Kann kein Geometrieobjekt aus den Daten machen, die Sie dem GEOMETRY-Feld übergeben haben" ER_FAILED_ROUTINE_BREAK_BINLOG eng "A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes" + ger "Eine Routine, die weder NO SQL noch READS SQL DATA in der Deklaration hat, schlug fehl und Binärlogging ist aktiv. Wenn Nicht-Transaktions-Tabellen aktualisiert wurden, enthält das Binärlog ihre Änderungen nicht" ER_BINLOG_UNSAFE_ROUTINE - eng "This routine has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)" + eng "This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)" + ger "Diese Routine hat weder DETERMINISTIC, NO SQL noch READS SQL DATA in der Deklaration und Binärlogging ist aktiv (*vielleicht* sollten Sie die weniger sichere Variable log_bin_trust_routine_creators verwenden)" ER_BINLOG_CREATE_ROUTINE_NEED_SUPER - eng "You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)" + eng "You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)" + ger "Sie haben keine SUPER-Berechtigung und Binärlogging ist aktiv (*vielleicht* sollten Sie die weniger sichere Variable log_bin_trust_routine_creators verwenden)" ER_EXEC_STMT_WITH_OPEN_CURSOR eng "You can't execute a prepared statement which has an open cursor associated with it. Reset the statement to re-execute it." + ger "Sie können keine vorbereitete Anweisung ausführen, die mit einem geöffneten Cursor verknüpft ist. Setzen Sie die Anweisung zurück, um sie neu auszuführen" ER_STMT_HAS_NO_OPEN_CURSOR eng "The statement (%lu) has no open cursor." + ger "Die Anweisung (%lu) hat keinen geöffneten Cursor" ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG eng "Explicit or implicit commit is not allowed in stored function or trigger." + ger "Explizites oder implizites Commit ist in gespeicherten Funktionen und in Triggern nicht erlaubt" ER_NO_DEFAULT_FOR_VIEW_FIELD eng "Field of view '%-.64s.%-.64s' underlying table doesn't have a default value" + ger "Ein Feld der dem View '%-.64s.%-.64s' zugrundeliegenden Tabelle hat keinen Vorgabewert" ER_SP_NO_RECURSION - eng "Recursive stored routines are not allowed." + eng "Recursive stored functions and triggers are not allowed." + ger "Rekursive gespeicherte Routinen und Triggers sind nicht erlaubt" ER_TOO_BIG_SCALE 42000 S1009 eng "Too big scale %d specified for column '%-.64s'. Maximum is %d." + ger "Zu großer Skalierungsfaktor %d für Feld '%-.64s' angegeben. Maximum ist %d" ER_TOO_BIG_PRECISION 42000 S1009 eng "Too big precision %d specified for column '%-.64s'. Maximum is %d." + ger "Zu große Genauigkeit %d für Feld '%-.64s' angegeben. Maximum ist %d" ER_M_BIGGER_THAN_D 42000 S1009 eng "For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column '%-.64s')." + ger "Für FLOAT(M,D), DOUBLE(M,D) oder DECIMAL(M,D) muss M >= D sein (Feld '%-.64s')" ER_WRONG_LOCK_OF_SYSTEM_TABLE eng "You can't combine write-locking of system '%-.64s.%-.64s' table with other tables" + ger "Sie können Schreibsperren auf der Systemtabelle '%-.64s.%-.64s' nicht mit anderen Tabellen kombinieren" ER_CONNECT_TO_FOREIGN_DATA_SOURCE - eng "Unable to connect to foreign data source - database '%.64s'!" + eng "Unable to connect to foreign data source: %.64s" + ger "Kann nicht mit Fremddatenquelle verbinden: %.64s" ER_QUERY_ON_FOREIGN_DATA_SOURCE - eng "There was a problem processing the query on the foreign data source. Data source error: '%-.64s'" + eng "There was a problem processing the query on the foreign data source. Data source error: %-.64" + ger "Bei der Verarbeitung der Abfrage ist in der Fremddatenquelle ein Problem aufgetreten. Datenquellenfehlermeldung: %-.64s" ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST - eng "The foreign data source you are trying to reference does not exist. Data source error : '%-.64s'" + eng "The foreign data source you are trying to reference does not exist. Data source error: %-.64s" + ger "Die Fremddatenquelle, auf die Sie zugreifen wollen, existiert nicht. Datenquellenfehlermeldung: %-.64s" ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE eng "Can't create federated table. The data source connection string '%-.64s' is not in the correct format" + ger "Kann föderierte Tabelle nicht erzeugen. Der Datenquellen-Verbindungsstring '%-.64s' hat kein korrektes Format" ER_FOREIGN_DATA_STRING_INVALID eng "The data source connection string '%-.64s' is not in the correct format" + ger "Der Datenquellen-Verbindungsstring '%-.64s' hat kein korrektes Format" ER_CANT_CREATE_FEDERATED_TABLE - eng "Can't create federated table. Foreign data src error : '%-.64s'" + eng "Can't create federated table. Foreign data src error: %-.64s" + ger "Kann föderierte Tabelle nicht erzeugen. Fremddatenquellenfehlermeldung: %-.64s" ER_TRG_IN_WRONG_SCHEMA eng "Trigger in wrong schema" + ger "Trigger im falschen Schema" ER_STACK_OVERRUN_NEED_MORE eng "Thread stack overrun: %ld bytes used of a %ld byte stack, and %ld bytes needed. Use 'mysqld -O thread_stack=#' to specify a bigger stack." + ger "Thread-Stack-Überlauf: %ld Bytes eines %ld-Byte-Stacks in Verwendung, und %ld Bytes benötigt. Verwenden Sie 'mysqld -O thread_stack=#', um einen größeren Stack anzugeben" ER_TOO_LONG_BODY 42000 S1009 eng "Routine body for '%-.100s' is too long" + ger "Routinen-Body für '%-.100s' ist zu lang" ER_WARN_CANT_DROP_DEFAULT_KEYCACHE eng "Cannot drop default keycache" - ger "Der Default-Keycache kann nicht gelöscht werden" + ger "Der vorgabemäßige Schlüssel-Cache kann nicht gelöscht werden" ER_TOO_BIG_DISPLAYWIDTH 42000 S1009 eng "Display width out of range for column '%-.64s' (max = %d)" + ger "Anzeigebreite außerhalb des zulässigen Bereichs für Spalte '%-.64s' (Maximum: %d)" ER_XAER_DUPID XAE08 eng "XAER_DUPID: The XID already exists" + ger "XAER_DUPID: Die XID existiert bereits" ER_DATETIME_FUNCTION_OVERFLOW 22008 eng "Datetime function: %-.32s field overflow" + ger "Datetime-Funktion: %-.32s Feldüberlauf" ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG eng "Can't update table '%-.64s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger." + ger "Kann Tabelle '%-.64s' in gespeicherter Funktion oder Trigger nicht aktualisieren, weil sie bereits von der Anweisung verwendet wird, die diese gespeicherte Funktion oder den Trigger aufrief" ER_VIEW_PREVENT_UPDATE eng "The definition of table '%-.64s' prevents operation %.64s on table '%-.64s'." + ger "Die Definition der Tabelle '%-.64s' verhindert die Operation %.64s auf Tabelle '%-.64s'" ER_PS_NO_RECURSION eng "The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner" + ger "Die vorbereitete Anweisung enthält einen Aufruf einer gespeicherten Routine, die auf eben dieselbe Anweisung verweist. Es ist nicht erlaubt, eine vorbereitete Anweisung in solch rekursiver Weise auszuführen" ER_SP_CANT_SET_AUTOCOMMIT eng "Not allowed to set autocommit from a stored function or trigger" -ER_NO_VIEW_USER - eng "View definer is not fully qualified" + ger "Es ist nicht erlaubt, innerhalb einer gespeicherten Funktion oder eines Triggers AUTOCOMMIT zu setzen" +ER_MALFORMED_DEFINER + eng "Definer is not fully qualified" + ger "Definierer des View ist nicht vollständig spezifiziert" ER_VIEW_FRM_NO_USER - eng "View %-.64s.%-.64s has not definer information (old table format). Current user is used as definer. Please recreate view!" + eng "View '%-.64s'.'%-.64s' has no definer information (old table format). Current user is used as definer. Please recreate the view!" + ger "View '%-.64s'.'%-.64s' hat keine Definierer-Information (altes Tabellenformat). Der aktuelle Benutzer wird als Definierer verwendet. Bitte erstellen Sie den View neu" ER_VIEW_OTHER_USER - eng "You need the SUPER privilege for creation view with %-.64s@%-.64s definer" + eng "You need the SUPER privilege for creation view with '%-.64s'@'%-.64s' definer" + ger "Sie brauchen die SUPER-Berechtigung, um einen View mit dem Definierer '%-.64s'@'%-.64s' zu erzeugen" ER_NO_SUCH_USER - eng "There is not %-.64s@%-.64s registered" + eng "There is no '%-.64s'@'%-.64s' registered" + ger "'%-.64s'@'%-.64s' ist nicht registriert" ER_FORBID_SCHEMA_CHANGE eng "Changing schema from '%-.64s' to '%-.64s' is not allowed." + ger "Wechsel des Schemas von '%-.64s' auf '%-.64s' ist nicht erlaubt" ER_ROW_IS_REFERENCED_2 23000 eng "Cannot delete or update a parent row: a foreign key constraint fails (%.192s)" + ger "Kann Eltern-Zeile nicht löschen oder aktualisieren: eine Fremdschlüsselbedingung schlägt fehl (%.192s)" ER_NO_REFERENCED_ROW_2 23000 eng "Cannot add or update a child row: a foreign key constraint fails (%.192s)" + ger "Kann Kind-Zeile nicht hinzufügen oder aktualisieren: eine Fremdschlüsselbedingung schlägt fehl (%.192s)" ER_SP_BAD_VAR_SHADOW 42000 eng "Variable '%-.64s' must be quoted with `...`, or renamed" + ger "Variable '%-.64s' muss mit `...` geschützt oder aber umbenannt werden" +ER_TRG_NO_DEFINER + eng "No definer attribute for trigger '%-.64s'.'%-.64s'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger." + ger "Kein Definierer-Attribut für Trigger '%-.64s'.'%-.64s'. Der Trigger wird mit der Autorisierung des Aufrufers aktiviert, der möglicherweise keine zureichenden Berechtigungen hat. Bitte legen Sie den Trigger neu an." +ER_OLD_FILE_FORMAT + eng "'%-.64s' has an old format, you should re-create the '%s' object(s)" + ger "'%-.64s' hat altes Format, Sie sollten die '%s'-Objekt(e) neu erzeugen" +ER_SP_RECURSION_LIMIT + eng "Recursive limit %d (as set by the max_sp_recursion_depth variable) was exceeded for routine %.64s" + ger "Rekursionsgrenze %d (durch Variable max_sp_recursion_depth gegeben) wurde für Routine %.64s überschritten" +ER_SP_PROC_TABLE_CORRUPT + eng "Failed to load routine %s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)" diff --git a/sql/slave.cc b/sql/slave.cc index f785bdcd4d7..5e1c838730c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -582,6 +582,20 @@ int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset, rli->slave_skip_counter=0; pthread_mutex_lock(&rli->data_lock); + + /* + we close the relay log fd possibly left open by the slave SQL thread, + to be able to delete it; the relay log fd possibly left open by the slave + I/O thread will be closed naturally in reset_logs() by the + close(LOG_CLOSE_TO_BE_OPENED) call + */ + if (rli->cur_log_fd >= 0) + { + end_io_cache(&rli->cache_buf); + my_close(rli->cur_log_fd, MYF(MY_WME)); + rli->cur_log_fd= -1; + } + if (rli->relay_log.reset_logs(thd)) { *errmsg = "Failed during log reset"; @@ -1383,7 +1397,7 @@ static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi) MYSQL_RES *master_res= 0; MYSQL_ROW master_row; - if (!mysql_real_query(mysql, "SELECT UNIX_TIMESTAMP()", 23) && + if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT UNIX_TIMESTAMP()")) && (master_res= mysql_store_result(mysql)) && (master_row= mysql_fetch_row(master_res))) { @@ -1409,7 +1423,8 @@ do not trust column Seconds_Behind_Master of SHOW SLAVE STATUS"); Note: we could have put a @@SERVER_ID in the previous SELECT UNIX_TIMESTAMP() instead, but this would not have worked on 3.23 masters. */ - if (!mysql_real_query(mysql, "SHOW VARIABLES LIKE 'SERVER_ID'", 31) && + if (!mysql_real_query(mysql, + STRING_WITH_LEN("SHOW VARIABLES LIKE 'SERVER_ID'")) && (master_res= mysql_store_result(mysql))) { if ((master_row= mysql_fetch_row(master_res)) && @@ -1444,7 +1459,8 @@ not always make sense; please check the manual before using it)."; goto err; if ((*mysql->server_version == '4') && - !mysql_real_query(mysql, "SELECT @@GLOBAL.COLLATION_SERVER", 32) && + !mysql_real_query(mysql, + STRING_WITH_LEN("SELECT @@GLOBAL.COLLATION_SERVER")) && (master_res= mysql_store_result(mysql))) { if ((master_row= mysql_fetch_row(master_res)) && @@ -1471,7 +1487,7 @@ be equal for replication to work"; those were alpha). */ if ((*mysql->server_version == '4') && - !mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) && + !mysql_real_query(mysql, STRING_WITH_LEN("SELECT @@GLOBAL.TIME_ZONE")) && (master_res= mysql_store_result(mysql))) { if ((master_row= mysql_fetch_row(master_res)) && @@ -3430,6 +3446,7 @@ slave_begin: THD_CHECK_SENTRY(thd); pthread_detach_this_thread(); + thd->thread_stack= (char*) &thd; // remember where our stack is if (init_slave_thread(thd, SLAVE_THD_IO)) { pthread_cond_broadcast(&mi->start_cond); @@ -3438,7 +3455,6 @@ slave_begin: goto err; } mi->io_thd = thd; - thd->thread_stack = (char*)&thd; // remember where our stack is pthread_mutex_lock(&LOCK_thread_count); threads.append(thd); pthread_mutex_unlock(&LOCK_thread_count); @@ -3692,14 +3708,6 @@ err: mi->slave_running = 0; mi->io_thd = 0; - /* Close log file and free buffers */ - if (mi->rli.cur_log_fd >= 0) - { - end_io_cache(&mi->rli.cache_buf); - my_close(mi->rli.cur_log_fd, MYF(MY_WME)); - mi->rli.cur_log_fd= -1; - } - /* Forget the relay log's format */ delete mi->rli.relay_log.description_event_for_queue; mi->rli.relay_log.description_event_for_queue= 0; @@ -3916,14 +3924,6 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ rli->cached_charset_invalidate(); rli->save_temporary_tables = thd->temporary_tables; - /* Close log file and free buffers if it's already open */ - if (rli->cur_log_fd >= 0) - { - end_io_cache(&rli->cache_buf); - my_close(rli->cur_log_fd, MYF(MY_WME)); - rli->cur_log_fd = -1; - } - /* TODO: see if we can do this conditionally in next_event() instead to avoid unneeded position re-init diff --git a/sql/sp.cc b/sql/sp.cc index 8386c5d58a2..a9b1a462d5f 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -29,6 +29,11 @@ create_string(THD *thd, String *buf, const char *returns, ulong returnslen, const char *body, ulong bodylen, st_sp_chistics *chistics); +static int +db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, + ulong sql_mode, const char *params, const char *returns, + const char *body, st_sp_chistics &chistics, + const char *definer, longlong created, longlong modified); /* * @@ -377,83 +382,83 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) close_proc_table(thd, &open_tables_state_backup); table= 0; - { - String defstr; - LEX *oldlex= thd->lex; - char olddb[128]; - bool dbchanged; - enum enum_sql_command oldcmd= thd->lex->sql_command; - ulong old_sql_mode= thd->variables.sql_mode; - ha_rows select_limit= thd->variables.select_limit; - - thd->variables.sql_mode= sql_mode; - thd->variables.select_limit= HA_POS_ERROR; - - defstr.set_charset(system_charset_info); - if (!create_string(thd, &defstr, - type, - name, - params, strlen(params), - returns, strlen(returns), - body, strlen(body), - &chistics)) - { - ret= SP_INTERNAL_ERROR; - goto done; - } + ret= db_load_routine(thd, type, name, sphp, + sql_mode, params, returns, body, chistics, + definer, created, modified); + + done: + if (table) + close_proc_table(thd, &open_tables_state_backup); + DBUG_RETURN(ret); +} - dbchanged= FALSE; - if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb), - 1, &dbchanged))) - goto done; - { - /* This is something of a kludge. We need to initialize some fields - * in thd->lex (the unit and master stuff), and the easiest way to - * do it is, is to call mysql_init_query(), but this unfortunately - * resets teh value_list where we keep the CALL parameters. So we - * copy the list and then restore it. (... and found_semicolon too). - */ - List<Item> tmpvals= thd->lex->value_list; - char *tmpfsc= thd->lex->found_semicolon; - - lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length()); - thd->lex->value_list= tmpvals; - thd->lex->found_semicolon= tmpfsc; - } +static int +db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, + ulong sql_mode, const char *params, const char *returns, + const char *body, st_sp_chistics &chistics, + const char *definer, longlong created, longlong modified) +{ + LEX *old_lex= thd->lex, newlex; + String defstr; + char olddb[128]; + bool dbchanged; + ulong old_sql_mode= thd->variables.sql_mode; + ha_rows old_select_limit= thd->variables.select_limit; + sp_rcontext *old_spcont= thd->spcont; + int ret; - if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL) - { - LEX *newlex= thd->lex; - sp_head *sp= newlex->sphead; + thd->variables.sql_mode= sql_mode; + thd->variables.select_limit= HA_POS_ERROR; - if (dbchanged && (ret= mysql_change_db(thd, olddb, 1))) - goto done; - if (sp) - { - delete sp; - newlex->sphead= NULL; - } - ret= SP_PARSE_ERROR; - } - else - { - if (dbchanged && (ret= mysql_change_db(thd, olddb, 1))) - goto done; - *sphp= thd->lex->sphead; - (*sphp)->set_info((char *)definer, (uint)strlen(definer), - created, modified, &chistics, sql_mode); - (*sphp)->optimize(); - } - thd->lex->sql_command= oldcmd; - thd->variables.sql_mode= old_sql_mode; - thd->variables.select_limit= select_limit; + thd->lex= &newlex; + newlex.current_select= NULL; + + defstr.set_charset(system_charset_info); + if (!create_string(thd, &defstr, + type, + name, + params, strlen(params), + returns, strlen(returns), + body, strlen(body), + &chistics)) + { + ret= SP_INTERNAL_ERROR; + goto end; } - done: - if (table) - close_proc_table(thd, &open_tables_state_backup); - DBUG_RETURN(ret); + dbchanged= FALSE; + if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb), + 1, &dbchanged))) + goto end; + + lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length()); + + thd->spcont= 0; + if (yyparse(thd) || thd->is_fatal_error || newlex.sphead == NULL) + { + sp_head *sp= newlex.sphead; + + if (dbchanged && (ret= mysql_change_db(thd, olddb, 1))) + goto end; + delete sp; + ret= SP_PARSE_ERROR; + } + else + { + if (dbchanged && (ret= mysql_change_db(thd, olddb, 1))) + goto end; + *sphp= newlex.sphead; + (*sphp)->set_definer((char*) definer, (uint) strlen(definer)); + (*sphp)->set_info(created, modified, &chistics, sql_mode); + (*sphp)->optimize(); + } +end: + thd->spcont= old_spcont; + thd->variables.sql_mode= old_sql_mode; + thd->variables.select_limit= old_select_limit; + thd->lex= old_lex; + return ret; } @@ -465,7 +470,7 @@ sp_returns_type(THD *thd, String &result, sp_head *sp) bzero(&table, sizeof(table)); table.in_use= thd; table.s = &table.share_not_to_be_used; - field= sp->make_field(0, 0, &table); + field= sp->create_result_field(0, 0, &table); field->sql_type(result); delete field; } @@ -551,12 +556,13 @@ db_create_routine(THD *thd, int type, sp_head *sp) store(sp->m_chistics->comment.str, sp->m_chistics->comment.length, system_charset_info); - if (!trust_routine_creators && mysql_bin_log.is_open()) + if ((sp->m_type == TYPE_ENUM_FUNCTION) && + !trust_function_creators && mysql_bin_log.is_open()) { if (!sp->m_chistics->detistic) { /* - Note that for a _function_ this test is not enough; one could use + Note that this test is not perfect; one could use a non-deterministic read-only function in an update statement. */ enum enum_sp_data_access access= @@ -898,45 +904,105 @@ err: ******************************************************************************/ /* - Obtain object representing stored procedure by its name from + Obtain object representing stored procedure/function by its name from stored procedures cache and looking into mysql.proc if needed. SYNOPSIS - sp_find_procedure() + sp_find_routine() thd - thread context + type - type of object (TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE) name - name of procedure + cp - hash to look routine in cache_only - if true perform cache-only lookup (Don't look in mysql.proc). - TODO - We should consider merging of sp_find_procedure() and - sp_find_function() into one sp_find_routine() function - (the same applies to other similarly paired functions). - RETURN VALUE Non-0 pointer to sp_head object for the procedure, or 0 - in case of error. */ sp_head * -sp_find_procedure(THD *thd, sp_name *name, bool cache_only) +sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, + bool cache_only) { sp_head *sp; - DBUG_ENTER("sp_find_procedure"); - DBUG_PRINT("enter", ("name: %.*s.%.*s", - name->m_db.length, name->m_db.str, - name->m_name.length, name->m_name.str)); + ulong depth= (type == TYPE_ENUM_PROCEDURE ? + thd->variables.max_sp_recursion_depth : + 0); + DBUG_ENTER("sp_find_routine"); + DBUG_PRINT("enter", ("name: %.*s.%.*s, type: %d, cache only %d", + name->m_db.length, name->m_db.str, + name->m_name.length, name->m_name.str, + type, cache_only)); + + if ((sp= sp_cache_lookup(cp, name))) + { + ulong level; + sp_head *new_sp; + const char *returns= ""; + char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2]; + String retstr(64); + + DBUG_PRINT("info", ("found: 0x%lx", (ulong)sp)); + if (sp->m_first_free_instance) + { + DBUG_PRINT("info", ("first free: 0x%lx, level: %lu, flags %x", + (ulong)sp->m_first_free_instance, + sp->m_first_free_instance->m_recursion_level, + sp->m_first_free_instance->m_flags)); + DBUG_ASSERT(!(sp->m_first_free_instance->m_flags & sp_head::IS_INVOKED)); + if (sp->m_first_free_instance->m_recursion_level > depth) + { + sp->recursion_level_error(thd); + DBUG_RETURN(0); + } + DBUG_RETURN(sp->m_first_free_instance); + } + level= sp->m_last_cached_sp->m_recursion_level + 1; + if (level > depth) + { + sp->recursion_level_error(thd); + DBUG_RETURN(0); + } - if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name)) && !cache_only) + strxmov(definer, sp->m_definer_user.str, "@", + sp->m_definer_host.str, NullS); + if (type == TYPE_ENUM_FUNCTION) + { + sp_returns_type(thd, retstr, sp); + returns= retstr.ptr(); + } + if (db_load_routine(thd, type, name, &new_sp, + sp->m_sql_mode, sp->m_params.str, returns, + sp->m_body.str, *sp->m_chistics, definer, + sp->m_created, sp->m_modified) == SP_OK) + { + sp->m_last_cached_sp->m_next_cached_sp= new_sp; + new_sp->m_recursion_level= level; + new_sp->m_first_instance= sp; + sp->m_last_cached_sp= sp->m_first_free_instance= new_sp; + DBUG_PRINT("info", ("added level: 0x%lx, level: %lu, flags %x", + (ulong)new_sp, new_sp->m_recursion_level, + new_sp->m_flags)); + DBUG_RETURN(new_sp); + } + DBUG_RETURN(0); + } + if (!cache_only) { - if (db_find_routine(thd, TYPE_ENUM_PROCEDURE, name, &sp) == SP_OK) - sp_cache_insert(&thd->sp_proc_cache, sp); + if (db_find_routine(thd, type, name, &sp) == SP_OK) + { + sp_cache_insert(cp, sp); + DBUG_PRINT("info", ("added new: 0x%lx, level: %lu, flags %x", + (ulong)sp, sp->m_recursion_level, + sp->m_flags)); + } } - DBUG_RETURN(sp); } + int sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error) { @@ -954,8 +1020,10 @@ sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error) lex_name.str= thd->strmake(table->table_name, lex_name.length); name= new sp_name(lex_db, lex_name); name->init_qname(thd); - if (sp_find_procedure(thd, name) != NULL || - sp_find_function(thd, name) != NULL) + if (sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name, + &thd->sp_proc_cache, FALSE) != NULL || + sp_find_routine(thd, TYPE_ENUM_FUNCTION, name, + &thd->sp_func_cache, FALSE) != NULL) { if (any) DBUG_RETURN(1); @@ -1023,7 +1091,8 @@ sp_show_create_procedure(THD *thd, sp_name *name) DBUG_ENTER("sp_show_create_procedure"); DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str)); - if ((sp= sp_find_procedure(thd, name))) + if ((sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name, + &thd->sp_proc_cache, FALSE))) { int ret= sp->show_create_procedure(thd); @@ -1049,42 +1118,6 @@ sp_show_status_procedure(THD *thd, const char *wild) FUNCTION ******************************************************************************/ -/* - Obtain object representing stored function by its name from - stored functions cache and looking into mysql.proc if needed. - - SYNOPSIS - sp_find_function() - thd - thread context - name - name of function - cache_only - if true perform cache-only lookup - (Don't look in mysql.proc). - - NOTE - See TODO section for sp_find_procedure(). - - RETURN VALUE - Non-0 pointer to sp_head object for the function, or - 0 - in case of error. -*/ - -sp_head * -sp_find_function(THD *thd, sp_name *name, bool cache_only) -{ - sp_head *sp; - DBUG_ENTER("sp_find_function"); - DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str)); - - if (!(sp= sp_cache_lookup(&thd->sp_func_cache, name)) && - !cache_only) - { - if (db_find_routine(thd, TYPE_ENUM_FUNCTION, name, &sp) == SP_OK) - sp_cache_insert(&thd->sp_func_cache, sp); - } - DBUG_RETURN(sp); -} - - int sp_create_function(THD *thd, sp_head *sp) { @@ -1132,7 +1165,8 @@ sp_show_create_function(THD *thd, sp_name *name) DBUG_ENTER("sp_show_create_function"); DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str)); - if ((sp= sp_find_function(thd, name))) + if ((sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, name, + &thd->sp_func_cache, FALSE))) { int ret= sp->show_create_function(thd); @@ -1167,6 +1201,12 @@ struct Sroutine_hash_entry for LEX::sroutine/sroutine_list and sp_head::m_sroutines. */ Sroutine_hash_entry *next; + /* + Uppermost view which directly or indirectly uses this routine. + 0 if routine is not used in view. Note that it also can be 0 if + statement uses routine both via view and directly. + */ + TABLE_LIST *belong_to_view; }; @@ -1221,9 +1261,11 @@ void sp_get_prelocking_info(THD *thd, bool *need_prelocking, SYNOPSIS add_used_routine() - lex - LEX representing statement - arena - arena in which memory for new element will be allocated - key - key for the hash representing set + lex LEX representing statement + arena Arena in which memory for new element will be allocated + key Key for the hash representing set + belong_to_view Uppermost view which uses this routine + (0 if routine is not used by view) NOTES Will also add element to end of 'LEX::sroutines_list' list. @@ -1246,7 +1288,8 @@ void sp_get_prelocking_info(THD *thd, bool *need_prelocking, */ static bool add_used_routine(LEX *lex, Query_arena *arena, - const LEX_STRING *key) + const LEX_STRING *key, + TABLE_LIST *belong_to_view) { if (!hash_search(&lex->sroutines, (byte *)key->str, key->length)) { @@ -1260,6 +1303,7 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, memcpy(rn->key.str, key->str, key->length); my_hash_insert(&lex->sroutines, (byte *)rn); lex->sroutines_list.link_in_list((byte *)rn, (byte **)&rn->next); + rn->belong_to_view= belong_to_view; return TRUE; } return FALSE; @@ -1290,7 +1334,7 @@ void sp_add_used_routine(LEX *lex, Query_arena *arena, sp_name *rt, char rt_type) { rt->set_routine_type(rt_type); - (void)add_used_routine(lex, arena, &rt->m_sroutines_key); + (void)add_used_routine(lex, arena, &rt->m_sroutines_key, 0); lex->sroutines_list_own_last= lex->sroutines_list.next; lex->sroutines_list_own_elements= lex->sroutines_list.elements; } @@ -1360,20 +1404,23 @@ void sp_update_sp_used_routines(HASH *dst, HASH *src) SYNOPSIS sp_update_stmt_used_routines() - thd - thread context - lex - LEX representing statement - src - hash representing set from which routines will be added + thd Thread context + lex LEX representing statement + src Hash representing set from which routines will be added + belong_to_view Uppermost view which uses these routines, 0 if none NOTE It will also add elements to end of 'LEX::sroutines_list' list. */ -static void sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src) +static void +sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src, + TABLE_LIST *belong_to_view) { for (uint i=0 ; i < src->records ; i++) { Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i); - (void)add_used_routine(lex, thd->stmt_arena, &rt->key); + (void)add_used_routine(lex, thd->stmt_arena, &rt->key, belong_to_view); } } @@ -1384,19 +1431,21 @@ static void sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src) SYNOPSIS sp_update_stmt_used_routines() - thd Thread context - lex LEX representing statement - src List representing set from which routines will be added + thd Thread context + lex LEX representing statement + src List representing set from which routines will be added + belong_to_view Uppermost view which uses these routines, 0 if none NOTE It will also add elements to end of 'LEX::sroutines_list' list. */ -static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src) +static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src, + TABLE_LIST *belong_to_view) { for (Sroutine_hash_entry *rt= (Sroutine_hash_entry *)src->first; rt; rt= rt->next) - (void)add_used_routine(lex, thd->stmt_arena, &rt->key); + (void)add_used_routine(lex, thd->stmt_arena, &rt->key, belong_to_view); } @@ -1414,21 +1463,23 @@ static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src) first_no_prelock - If true, don't add tables or cache routines used by the body of the first routine (i.e. *start) will be executed in non-prelocked mode. + tabs_changed - Set to TRUE some tables were added, FALSE otherwise NOTE If some function is missing this won't be reported here. Instead this fact will be discovered during query execution. RETURN VALUE - TRUE - some tables were added - FALSE - no tables were added. + 0 - success + non-0 - failure */ -static bool +static int sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, Sroutine_hash_entry *start, - bool first_no_prelock) + bool first_no_prelock, bool *tabs_changed) { - bool result= FALSE; + int ret= 0; + bool tabschnd= 0; /* Set if tables changed */ bool first= TRUE; DBUG_ENTER("sp_cache_routines_and_add_tables_aux"); @@ -1442,10 +1493,6 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, &thd->sp_func_cache : &thd->sp_proc_cache), &name))) { - LEX *oldlex= thd->lex; - LEX *newlex= new st_lex; - thd->lex= newlex; - newlex->current_select= NULL; name.m_name.str= strchr(name.m_qname.str, '.'); name.m_db.length= name.m_name.str - name.m_qname.str; name.m_db.str= strmake_root(thd->mem_root, name.m_qname.str, @@ -1453,27 +1500,68 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, name.m_name.str+= 1; name.m_name.length= name.m_qname.length - name.m_db.length - 1; - if (db_find_routine(thd, type, &name, &sp) == SP_OK) + switch ((ret= db_find_routine(thd, type, &name, &sp))) { - if (type == TYPE_ENUM_FUNCTION) - sp_cache_insert(&thd->sp_func_cache, sp); - else - sp_cache_insert(&thd->sp_proc_cache, sp); + case SP_OK: + { + if (type == TYPE_ENUM_FUNCTION) + sp_cache_insert(&thd->sp_func_cache, sp); + else + sp_cache_insert(&thd->sp_proc_cache, sp); + } + break; + case SP_KEY_NOT_FOUND: + ret= SP_OK; + break; + case SP_OPEN_TABLE_FAILED: + /* + Force it to attempt opening it again on subsequent calls; + otherwise we will get one error message the first time, and + then ER_SP_PROC_TABLE_CORRUPT (below) on subsequent tries. + */ + mysql_proc_table_exists= 1; + /* Fall through */ + default: + /* + Any error when loading an existing routine is either some problem + with the mysql.proc table, or a parse error because the contents + has been tampered with (in which case we clear that error). + */ + if (ret == SP_PARSE_ERROR) + thd->clear_error(); + /* + If we cleared the parse error, or when db_find_routine() flagged + an error with it's return value without calling my_error(), we + set the generic "mysql.proc table corrupt" error here. + */ + if (!thd->net.report_error) + { + char n[NAME_LEN*2+2]; + + /* m_qname.str is not always \0 terminated */ + memcpy(n, name.m_qname.str, name.m_qname.length); + n[name.m_qname.length]= '\0'; + my_error(ER_SP_PROC_TABLE_CORRUPT, MYF(0), n, ret); + } + break; } - delete newlex; - thd->lex= oldlex; } if (sp) { if (!(first && first_no_prelock)) { - sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines); - result|= sp->add_used_tables_to_table_list(thd, &lex->query_tables_last); + sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines, + rt->belong_to_view); + tabschnd|= + sp->add_used_tables_to_table_list(thd, &lex->query_tables_last, + rt->belong_to_view); } } first= FALSE; } - DBUG_RETURN(result); + if (tabs_changed) /* it can be NULL */ + *tabs_changed= tabschnd; + DBUG_RETURN(ret); } @@ -1488,18 +1576,20 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, lex - LEX representing statement first_no_prelock - If true, don't add tables or cache routines used by the body of the first routine (i.e. *start) + tabs_changed - Set to TRUE some tables were added, FALSE otherwise RETURN VALUE - TRUE - some tables were added - FALSE - no tables were added. + 0 - success + non-0 - failure */ -bool -sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock) +int +sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock, + bool *tabs_changed) { return sp_cache_routines_and_add_tables_aux(thd, lex, (Sroutine_hash_entry *)lex->sroutines_list.first, - first_no_prelock); + first_no_prelock, tabs_changed); } @@ -1510,19 +1600,25 @@ sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock) SYNOPSIS sp_cache_routines_and_add_tables_for_view() - thd - thread context - lex - LEX representing statement - aux_lex - LEX representing view + thd Thread context + lex LEX representing statement + view Table list element representing view + + RETURN VALUE + 0 - success + non-0 - failure */ -void -sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex) +int +sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, TABLE_LIST *view) { Sroutine_hash_entry **last_cached_routine_ptr= (Sroutine_hash_entry **)lex->sroutines_list.next; - sp_update_stmt_used_routines(thd, lex, &aux_lex->sroutines_list); - (void)sp_cache_routines_and_add_tables_aux(thd, lex, - *last_cached_routine_ptr, FALSE); + sp_update_stmt_used_routines(thd, lex, &view->view->sroutines_list, + view->top_table()); + return sp_cache_routines_and_add_tables_aux(thd, lex, + *last_cached_routine_ptr, FALSE, + NULL); } @@ -1533,16 +1629,23 @@ sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex) SYNOPSIS sp_cache_routines_and_add_tables_for_triggers() - thd - thread context - lex - LEX respresenting statement - triggers - triggers of the table + thd thread context + lex LEX respresenting statement + table Table list element for table with trigger + + RETURN VALUE + 0 - success + non-0 - failure */ -void +int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, - Table_triggers_list *triggers) + TABLE_LIST *table) { - if (add_used_routine(lex, thd->stmt_arena, &triggers->sroutines_key)) + int ret= 0; + Table_triggers_list *triggers= table->table->triggers; + if (add_used_routine(lex, thd->stmt_arena, &triggers->sroutines_key, + table->belong_to_view)) { Sroutine_hash_entry **last_cached_routine_ptr= (Sroutine_hash_entry **)lex->sroutines_list.next; @@ -1552,17 +1655,20 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, { if (triggers->bodies[i][j]) { - (void)triggers->bodies[i][j]->add_used_tables_to_table_list(thd, - &lex->query_tables_last); + (void)triggers->bodies[i][j]-> + add_used_tables_to_table_list(thd, &lex->query_tables_last, + table->belong_to_view); sp_update_stmt_used_routines(thd, lex, - &triggers->bodies[i][j]->m_sroutines); + &triggers->bodies[i][j]->m_sroutines, + table->belong_to_view); } } } - (void)sp_cache_routines_and_add_tables_aux(thd, lex, - *last_cached_routine_ptr, - FALSE); + ret= sp_cache_routines_and_add_tables_aux(thd, lex, + *last_cached_routine_ptr, + FALSE, NULL); } + return ret; } @@ -1584,30 +1690,30 @@ create_string(THD *thd, String *buf, chistics->comment.length)) return FALSE; - buf->append("CREATE ", 7); + buf->append(STRING_WITH_LEN("CREATE ")); if (type == TYPE_ENUM_FUNCTION) - buf->append("FUNCTION ", 9); + buf->append(STRING_WITH_LEN("FUNCTION ")); else - buf->append("PROCEDURE ", 10); + buf->append(STRING_WITH_LEN("PROCEDURE ")); append_identifier(thd, buf, name->m_name.str, name->m_name.length); buf->append('('); buf->append(params, paramslen); buf->append(')'); if (type == TYPE_ENUM_FUNCTION) { - buf->append(" RETURNS ", 9); + buf->append(STRING_WITH_LEN(" RETURNS ")); buf->append(returns, returnslen); } buf->append('\n'); switch (chistics->daccess) { case SP_NO_SQL: - buf->append(" NO SQL\n"); + buf->append(STRING_WITH_LEN(" NO SQL\n")); break; case SP_READS_SQL_DATA: - buf->append(" READS SQL DATA\n"); + buf->append(STRING_WITH_LEN(" READS SQL DATA\n")); break; case SP_MODIFIES_SQL_DATA: - buf->append(" MODIFIES SQL DATA\n"); + buf->append(STRING_WITH_LEN(" MODIFIES SQL DATA\n")); break; case SP_DEFAULT_ACCESS: case SP_CONTAINS_SQL: @@ -1615,12 +1721,12 @@ create_string(THD *thd, String *buf, break; } if (chistics->detistic) - buf->append(" DETERMINISTIC\n", 18); + buf->append(STRING_WITH_LEN(" DETERMINISTIC\n")); if (chistics->suid == SP_IS_NOT_SUID) - buf->append(" SQL SECURITY INVOKER\n", 25); + buf->append(STRING_WITH_LEN(" SQL SECURITY INVOKER\n")); if (chistics->comment.length) { - buf->append(" COMMENT "); + buf->append(STRING_WITH_LEN(" COMMENT ")); append_unescaped(buf, chistics->comment.str, chistics->comment.length); buf->append('\n'); } @@ -36,7 +36,8 @@ int sp_drop_db_routines(THD *thd, char *db); sp_head * -sp_find_procedure(THD *thd, sp_name *name, bool cache_only = 0); +sp_find_routine(THD *thd, int type, sp_name *name, + sp_cache **cp, bool cache_only); int sp_exists_routine(THD *thd, TABLE_LIST *procs, bool any, bool no_error); @@ -57,9 +58,6 @@ sp_show_create_procedure(THD *thd, sp_name *name); int sp_show_status_procedure(THD *thd, const char *wild); -sp_head * -sp_find_function(THD *thd, sp_name *name, bool cache_only = 0); - int sp_create_function(THD *thd, sp_head *sp); @@ -86,12 +84,13 @@ void sp_add_used_routine(LEX *lex, Query_arena *arena, sp_name *rt, char rt_type); void sp_remove_not_own_routines(LEX *lex); void sp_update_sp_used_routines(HASH *dst, HASH *src); -bool sp_cache_routines_and_add_tables(THD *thd, LEX *lex, - bool first_no_prelock); -void sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, - LEX *aux_lex); -void sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, - Table_triggers_list *triggers); +int sp_cache_routines_and_add_tables(THD *thd, LEX *lex, + bool first_no_prelock, + bool *tabs_changed); +int sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, + TABLE_LIST *view); +int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, + TABLE_LIST *table); extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index abc66ce0b21..12f9260e7b1 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -24,11 +24,17 @@ #include "sp_rcontext.h" #include "sp_cache.h" +/* + Sufficient max length of printed destinations and frame offsets (all uints). +*/ +#define SP_INSTR_UINT_MAXLEN 8 +#define SP_STMT_PRINT_MAXLEN 40 + + Item_result sp_map_result_type(enum enum_field_types type) { - switch (type) - { + switch (type) { case MYSQL_TYPE_TINY: case MYSQL_TYPE_SHORT: case MYSQL_TYPE_LONG: @@ -46,6 +52,81 @@ sp_map_result_type(enum enum_field_types type) } } + +Item::Type +sp_map_item_type(enum enum_field_types type) +{ + switch (type) { + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_INT24: + return Item::INT_ITEM; + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + return Item::DECIMAL_ITEM; + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + return Item::REAL_ITEM; + default: + return Item::STRING_ITEM; + } +} + + +/* + Return a string representation of the Item value. + + NOTE: this is a legacy-compatible implementation. It fails if the value + contains non-ordinary symbols, which should be escaped. + + SYNOPSIS + item a pointer to the Item + str string buffer for representation of the value + + RETURN + NULL on error + a pointer to valid a valid string on success +*/ + +static String * +sp_get_item_value(Item *item, String *str) +{ + Item_result result_type= item->result_type(); + + switch (item->result_type()) { + case REAL_RESULT: + case INT_RESULT: + case DECIMAL_RESULT: + return item->val_str(str); + + case STRING_RESULT: + { + char buf_holder[STRING_BUFFER_USUAL_SIZE]; + String buf(buf_holder, sizeof(buf_holder), &my_charset_latin1); + String *result= item->val_str(str); + + if (!result) + return NULL; + + buf.append('_'); + buf.append(result->charset()->csname); + buf.append('\''); + buf.append(*result); + buf.append('\''); + str->copy(buf); + + return str; + } + + case ROW_RESULT: + default: + return NULL; + } +} + + /* SYNOPSIS sp_get_flags_for_command() @@ -72,7 +153,11 @@ sp_get_flags_for_command(LEX *lex) } /* fallthrough */ case SQLCOM_ANALYZE: + case SQLCOM_OPTIMIZE: + case SQLCOM_PRELOAD_KEYS: + case SQLCOM_ASSIGN_TO_KEYCACHE: case SQLCOM_CHECKSUM: + case SQLCOM_CHECK: case SQLCOM_HA_READ: case SQLCOM_SHOW_BINLOGS: case SQLCOM_SHOW_BINLOG_EVENTS: @@ -105,6 +190,11 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_SHOW_TABLES: case SQLCOM_SHOW_VARIABLES: case SQLCOM_SHOW_WARNS: + case SQLCOM_SHOW_PROC_CODE: + case SQLCOM_SHOW_FUNC_CODE: + case SQLCOM_REPAIR: + case SQLCOM_BACKUP_TABLE: + case SQLCOM_RESTORE_TABLE: flags= sp_head::MULTI_RESULTS; break; /* @@ -120,6 +210,45 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_DEALLOCATE_PREPARE: flags= sp_head::CONTAINS_DYNAMIC_SQL; break; + case SQLCOM_CREATE_TABLE: + if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) + flags= 0; + else + flags= sp_head::HAS_COMMIT_OR_ROLLBACK; + break; + case SQLCOM_DROP_TABLE: + if (lex->drop_temporary) + flags= 0; + else + flags= sp_head::HAS_COMMIT_OR_ROLLBACK; + break; + case SQLCOM_CREATE_INDEX: + case SQLCOM_CREATE_DB: + case SQLCOM_CREATE_VIEW: + case SQLCOM_CREATE_TRIGGER: + case SQLCOM_CREATE_USER: + case SQLCOM_ALTER_TABLE: + case SQLCOM_BEGIN: + case SQLCOM_RENAME_TABLE: + case SQLCOM_RENAME_USER: + case SQLCOM_DROP_INDEX: + case SQLCOM_DROP_DB: + case SQLCOM_DROP_USER: + case SQLCOM_DROP_VIEW: + case SQLCOM_DROP_TRIGGER: + case SQLCOM_TRUNCATE: + case SQLCOM_COMMIT: + case SQLCOM_ROLLBACK: + case SQLCOM_LOAD_MASTER_DATA: + case SQLCOM_LOCK_TABLES: + case SQLCOM_CREATE_PROCEDURE: + case SQLCOM_CREATE_SPFUNCTION: + case SQLCOM_ALTER_PROCEDURE: + case SQLCOM_ALTER_FUNCTION: + case SQLCOM_DROP_PROCEDURE: + case SQLCOM_DROP_FUNCTION: + flags= sp_head::HAS_COMMIT_OR_ROLLBACK; + break; default: flags= 0; break; @@ -129,7 +258,7 @@ sp_get_flags_for_command(LEX *lex) /* - Prepare Item for execution (call of fix_fields) + Prepare an Item for evaluation (call of fix_fields). SYNOPSIS sp_prepare_func_item() @@ -141,14 +270,15 @@ sp_get_flags_for_command(LEX *lex) prepared item */ -static Item * +Item * sp_prepare_func_item(THD* thd, Item **it_addr) { - Item *it= *it_addr; DBUG_ENTER("sp_prepare_func_item"); - it_addr= it->this_item_addr(thd, it_addr); + it_addr= (*it_addr)->this_item_addr(thd, it_addr); - if (!it->fixed && (*it_addr)->fix_fields(thd, it_addr)) + if (!(*it_addr)->fixed && + ((*it_addr)->fix_fields(thd, it_addr) || + (*it_addr)->check_cols(1))) { DBUG_PRINT("info", ("fix_fields() failed")); DBUG_RETURN(NULL); @@ -157,202 +287,62 @@ sp_prepare_func_item(THD* thd, Item **it_addr) } -/* Macro to switch arena in sp_eval_func_item */ -#define CREATE_ON_CALLERS_ARENA(new_command, condition, backup_arena) \ - do \ - { \ - if (condition) \ - thd->set_n_backup_active_arena(thd->spcont->callers_arena, \ - backup_arena); \ - new_command; \ - if (condition) \ - thd->restore_active_arena(thd->spcont->callers_arena, \ - backup_arena); \ - } while(0) - /* - Evaluate an item and store it in the returned item + Evaluate an expression and store the result in the field. SYNOPSIS - sp_eval_func_item() - name - current thread object - it_addr - pointer to the item to evaluate - type - type of the item we evaluating - reuse - used if we would like to reuse existing item - instead of allocation of the new one - use_callers_arena - TRUE if we want to use caller's arena - rather then current one. - DESCRIPTION - We use this function to evaluate result for stored functions - and stored procedure parameters. It is also used to evaluate and - (re) allocate variables. + sp_eval_expr() + thd - current thread object + expr_item - the root item of the expression + result_field - the field to store the result RETURN VALUES - Evaluated item is returned + FALSE on success + TRUE on error */ -Item * -sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type, - Item *reuse, bool use_callers_arena) +bool +sp_eval_expr(THD *thd, Field *result_field, Item *expr_item) { - DBUG_ENTER("sp_eval_func_item"); - Item *it= sp_prepare_func_item(thd, it_addr); - uint rsize; - Query_arena backup_arena; - Item *old_item_next, *old_free_list, **p_free_list; - DBUG_PRINT("info", ("type: %d", type)); - - if (!it) - DBUG_RETURN(NULL); + DBUG_ENTER("sp_eval_expr"); - if (reuse) - { - old_item_next= reuse->next; - p_free_list= use_callers_arena ? &thd->spcont->callers_arena->free_list : - &thd->free_list; - old_free_list= *p_free_list; - } + if (!(expr_item= sp_prepare_func_item(thd, &expr_item))) + DBUG_RETURN(TRUE); - switch (sp_map_result_type(type)) { - case INT_RESULT: - { - longlong i= it->val_int(); - - if (it->null_value) - { - DBUG_PRINT("info", ("INT_RESULT: null")); - goto return_null_item; - } - DBUG_PRINT("info", ("INT_RESULT: %d", i)); - CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_int(i), - use_callers_arena, &backup_arena); - break; - } - case REAL_RESULT: - { - double d= it->val_real(); - uint8 decimals; - uint32 max_length; + bool err_status= FALSE; - if (it->null_value) - { - DBUG_PRINT("info", ("REAL_RESULT: null")); - goto return_null_item; - } + /* + Set THD flags to emit warnings/errors in case of overflow/type errors + during saving the item into the field. - /* - There's some difference between Item::new_item() and the - constructor; the former crashes, the latter works... weird. - */ - decimals= it->decimals; - max_length= it->max_length; - DBUG_PRINT("info", ("REAL_RESULT: %g", d)); - CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_float(d), - use_callers_arena, &backup_arena); - it->decimals= decimals; - it->max_length= max_length; - break; - } - case DECIMAL_RESULT: - { - my_decimal value, *val= it->val_decimal(&value); - if (it->null_value) - goto return_null_item; - CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_decimal(val), - use_callers_arena, &backup_arena); -#ifndef DBUG_OFF - { - char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; - DBUG_PRINT("info", ("DECIMAL_RESULT: %s", - dbug_decimal_as_string(dbug_buff, val))); - } -#endif - break; - } - case STRING_RESULT: - { - char buffer[MAX_FIELD_WIDTH]; - String tmp(buffer, sizeof(buffer), it->collation.collation); - String *s= it->val_str(&tmp); + Save original values and restore them after save. + */ + + enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; + bool save_abort_on_warning= thd->abort_on_warning; + bool save_no_trans_update= thd->no_trans_update; - if (type == MYSQL_TYPE_NULL || it->null_value) - { - DBUG_PRINT("info", ("STRING_RESULT: null")); - goto return_null_item; - } - DBUG_PRINT("info",("STRING_RESULT: %.*s", - s->length(), s->c_ptr_quick())); - /* - Reuse mechanism in sp_eval_func_item() is only employed for assignments - to local variables and OUT/INOUT SP parameters repsesented by - Item_splocal. Usually we have some expression, which needs - to be calculated and stored into the local variable. However in the - case if "it" equals to "reuse", there is no "calculation" step. So, - no reason to employ reuse mechanism to save variable into itself. - */ - if (it == reuse) - DBUG_RETURN(it); + thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; + thd->abort_on_warning= + thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES); + thd->no_trans_update= 0; - /* - For some functions, 's' is now pointing to an argument of the - function, which might be a local variable that is to be reused. - In this case, new(reuse, &rsize) below will call the destructor - and 's' ends up pointing to freed memory. - A somewhat ugly fix is to simply copy the string to our local one - (which is unused by most functions anyway), but only if 's' is - pointing somewhere else than to 'tmp' or 'it->str_value'. - */ - if (reuse && s != &tmp && s != &it->str_value) - { - if (tmp.copy((const String)(*s))) - DBUG_RETURN(NULL); - s= &tmp; - } + /* Save the value in the field. Convert the value if needed. */ - CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) - Item_string(it->collation.collation), - use_callers_arena, &backup_arena); - /* - We have to use special constructor and allocate string - on system heap here. This is because usual Item_string - constructor would allocate memory in the callers arena. - This would lead to the memory leak in SP loops. - See Bug #11333 "Stored Procedure: Memory blow up on - repeated SELECT ... INTO query" for sample of such SP. - TODO: Usage of the system heap gives significant overhead, - however usual "reuse" mechanism does not work here, as - Item_string has no max size. That is, if we have a loop, which - has string variable with constantly increasing size, we would have - to allocate new pieces of memory again and again on each iteration. - In future we should probably reserve some area of memory for - not-very-large strings and reuse it. But for large strings - we would have to use system heap anyway. - */ - ((Item_string*) it)->set_str_with_copy(s->ptr(), s->length()); - break; - } - case ROW_RESULT: - default: - DBUG_ASSERT(0); - } - goto end; + expr_item->save_in_field(result_field, 0); -return_null_item: - CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_null(), - use_callers_arena, &backup_arena); -end: - it->rsize= rsize; + thd->count_cuted_fields= save_count_cuted_fields; + thd->abort_on_warning= save_abort_on_warning; + thd->no_trans_update= save_no_trans_update; - if (reuse && it == reuse) + if (thd->net.report_error) { - /* - The Item constructor registered itself in the arena free list, - while the item slot is reused, so we have to restore the list. - */ - it->next= old_item_next; - *p_free_list= old_free_list; + /* Return error status if something went wrong. */ + err_status= TRUE; } - DBUG_RETURN(it); + + DBUG_RETURN(err_status); } @@ -437,8 +427,11 @@ sp_head::operator delete(void *ptr, size_t size) sp_head::sp_head() :Query_arena(&main_mem_root, INITIALIZED_FOR_SP), - m_flags(0), m_returns_cs(NULL) + m_flags(0), m_recursion_level(0), m_next_cached_sp(0), + m_first_instance(this), m_first_free_instance(this), m_last_cached_sp(this) { + m_return_field_def.charset = NULL; + extern byte * sp_table_key(const byte *ptr, uint *plen, my_bool first); DBUG_ENTER("sp_head::sp_head"); @@ -457,6 +450,7 @@ sp_head::init(LEX *lex) DBUG_ENTER("sp_head::init"); lex->spcont= m_pcont= new sp_pcontext(NULL); + /* Altough trg_table_fields list is used only in triggers we init for all types of stored procedures to simplify reset_lex()/restore_lex() code. @@ -468,7 +462,7 @@ sp_head::init(LEX *lex) m_body.str= m_defstr.str= 0; m_qname.length= m_db.length= m_name.length= m_params.length= m_body.length= m_defstr.length= 0; - m_returns_cs= NULL; + m_return_field_def.charset= NULL; DBUG_VOID_RETURN; } @@ -476,7 +470,7 @@ void sp_head::init_strings(THD *thd, LEX *lex, sp_name *name) { DBUG_ENTER("sp_head::init_strings"); - uint n; /* Counter for nul trimming */ + uchar *endp; /* Used to trim the end */ /* During parsing, we must use thd->mem_root */ MEM_ROOT *root= thd->mem_root; @@ -509,27 +503,31 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name) (char *)m_param_begin, m_params.length); } - m_body.length= lex->ptr - m_body_begin; - /* Trim nuls at the end */ - n= 0; - while (m_body.length && m_body_begin[m_body.length-1] == '\0') - { - m_body.length-= 1; - n+= 1; - } + /* If ptr has overrun end_of_query then end_of_query is the end */ + endp= (lex->ptr > lex->end_of_query ? lex->end_of_query : lex->ptr); + /* + Trim "garbage" at the end. This is sometimes needed with the + "/ * ! VERSION... * /" wrapper in dump files. + */ + while (m_body_begin < endp && + (endp[-1] <= ' ' || endp[-1] == '*' || + endp[-1] == '/' || endp[-1] == ';')) + endp-= 1; + + m_body.length= endp - m_body_begin; m_body.str= strmake_root(root, (char *)m_body_begin, m_body.length); - m_defstr.length= lex->ptr - lex->buf; - m_defstr.length-= n; + m_defstr.length= endp - lex->buf; m_defstr.str= strmake_root(root, (char *)lex->buf, m_defstr.length); DBUG_VOID_RETURN; } -TYPELIB * -sp_head::create_typelib(List<String> *src) + +static TYPELIB * +create_typelib(MEM_ROOT *mem_root, create_field *field_def, List<String> *src) { TYPELIB *result= NULL; - CHARSET_INFO *cs= m_returns_cs; - DBUG_ENTER("sp_head::clone_typelib"); + CHARSET_INFO *cs= field_def->charset; + DBUG_ENTER("create_typelib"); if (src->elements) { result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB)); @@ -574,6 +572,7 @@ sp_head::create_typelib(List<String> *src) return result; } + int sp_head::create(THD *thd) { @@ -615,6 +614,7 @@ sp_head::create(THD *thd) sp_head::~sp_head() { destroy(); + delete m_next_cached_sp; if (m_thd) restore_thd_mem_root(m_thd); } @@ -660,17 +660,30 @@ sp_head::destroy() */ Field * -sp_head::make_field(uint max_length, const char *name, TABLE *dummy) +sp_head::create_result_field(uint field_max_length, const char *field_name, + TABLE *table) { + uint field_length; Field *field; - DBUG_ENTER("sp_head::make_field"); - - field= ::make_field((char *)0, - !m_returns_len ? max_length : m_returns_len, - (uchar *)"", 0, m_returns_pack, m_returns, m_returns_cs, - m_geom_returns, Field::NONE, - m_returns_typelib, - name ? name : (const char *)m_name.str, dummy); + + DBUG_ENTER("sp_head::create_result_field"); + + field_length= !m_return_field_def.length ? + field_max_length : m_return_field_def.length; + + field= ::make_field((char*) 0, /* field ptr */ + field_length, /* field [max] length */ + (uchar*) "", /* null ptr */ + 0, /* null bit */ + m_return_field_def.pack_flag, + m_return_field_def.sql_type, + m_return_field_def.charset, + m_return_field_def.geom_type, + Field::NONE, /* unreg check */ + m_return_field_def.interval, + field_name ? field_name : (const char *) m_name.str, + table); + DBUG_RETURN(field); } @@ -768,12 +781,14 @@ int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b) variables with NAME_CONST('sp_var_name', value) calls. RETURN - 0 Ok, thd->query{_length} either has been appropriately replaced or - there is no need for replacements. - 1 Out of memory error. + FALSE on success + thd->query{_length} either has been appropriately replaced or there + is no need for replacements. + TRUE out of memory error. */ -static bool subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) +static bool +subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) { DBUG_ENTER("subst_spvars"); if (thd->prelocked_mode == NON_PRELOCKED && mysql_bin_log.is_open()) @@ -783,7 +798,7 @@ static bool subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) String qbuf(buffer, sizeof(buffer), &my_charset_bin); int prev_pos, res; - /* Find all instances of item_splocal used in this statement */ + /* Find all instances of Item_splocal used in this statement */ for (Item *item= instr->free_list; item; item= item->next) { if (item->is_splocal()) @@ -794,7 +809,7 @@ static bool subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) } } if (!sp_vars_uses.elements()) - DBUG_RETURN(0); + DBUG_RETURN(FALSE); /* Sort SP var refs by their occurences in the query */ sp_vars_uses.sort(cmp_splocal_locations); @@ -810,33 +825,72 @@ static bool subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) splocal < sp_vars_uses.back(); splocal++) { Item *val; - (*splocal)->thd= thd; // fix_fields() is not yet done + + char str_buffer[STRING_BUFFER_USUAL_SIZE]; + String str_value_holder(str_buffer, sizeof(str_buffer), + &my_charset_latin1); + String *str_value; + /* append the text between sp ref occurences */ res|= qbuf.append(cur + prev_pos, (*splocal)->pos_in_query - prev_pos); prev_pos= (*splocal)->pos_in_query + (*splocal)->m_name.length; /* append the spvar substitute */ - res|= qbuf.append(" NAME_CONST('"); + res|= qbuf.append(STRING_WITH_LEN(" NAME_CONST('")); res|= qbuf.append((*splocal)->m_name.str, (*splocal)->m_name.length); - res|= qbuf.append("',"); + res|= qbuf.append(STRING_WITH_LEN("',")); + res|= (*splocal)->fix_fields(thd, (Item **) splocal); + + if (res) + break; + val= (*splocal)->this_item(); DBUG_PRINT("info", ("print %p", val)); - val->print(&qbuf); + str_value= sp_get_item_value(val, &str_value_holder); + if (str_value) + res|= qbuf.append(*str_value); + else + res|= qbuf.append(STRING_WITH_LEN("NULL")); res|= qbuf.append(')'); if (res) break; } res|= qbuf.append(cur + prev_pos, query_str->length - prev_pos); if (res) - DBUG_RETURN(1); + DBUG_RETURN(TRUE); if (!(pbuf= thd->strmake(qbuf.ptr(), qbuf.length()))) - DBUG_RETURN(1); + DBUG_RETURN(TRUE); thd->query= pbuf; thd->query_length= qbuf.length(); } - DBUG_RETURN(0); + DBUG_RETURN(FALSE); +} + + +/* + Return appropriate error about recursion limit reaching + + SYNOPSIS + sp_head::recursion_level_error() + thd Thread handle + + NOTE + For functions and triggers we return error about prohibited recursion. + For stored procedures we return about reaching recursion limit. +*/ + +void sp_head::recursion_level_error(THD *thd) +{ + if (m_type == TYPE_ENUM_PROCEDURE) + { + my_error(ER_SP_RECURSION_LIMIT, MYF(0), + thd->variables.max_sp_recursion_depth, + m_name.str); + } + else + my_error(ER_SP_NO_RECURSION, MYF(0)); } @@ -845,17 +899,19 @@ static bool subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) Assume the parameters already set. RETURN - -1 on error + FALSE on success + TRUE on error */ -int sp_head::execute(THD *thd) +bool +sp_head::execute(THD *thd) { DBUG_ENTER("sp_head::execute"); char olddb[128]; bool dbchanged; sp_rcontext *ctx; - int ret= 0; + bool err_status= FALSE; uint ip= 0; ulong save_sql_mode; Query_arena *old_arena; @@ -869,41 +925,39 @@ int sp_head::execute(THD *thd) Item_change_list old_change_list; String old_packet; + /* Use some extra margin for possible SP recursion and functions */ + if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (char*)&old_packet)) + DBUG_RETURN(TRUE); + /* init per-instruction memroot */ init_alloc_root(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0); - - /* Use some extra margin for possible SP recursion and functions */ - if (check_stack_overrun(thd, 4*STACK_MIN_SIZE, olddb)) - { - DBUG_RETURN(-1); - } - - if (m_flags & IS_INVOKED) + DBUG_ASSERT(!(m_flags & IS_INVOKED)); + m_flags|= IS_INVOKED; + m_first_instance->m_first_free_instance= m_next_cached_sp; + if (m_next_cached_sp) { - /* - We have to disable recursion for stored routines since in - many cases LEX structure and many Item's can't be used in - reentrant way now. - - TODO: We can circumvent this problem by using separate - sp_head instances for each recursive invocation. - - NOTE: Theoretically arguments of procedure can be evaluated - before its invocation so there should be no problem with - recursion. But since we perform cleanup for CALL statement - as for any other statement only after its execution, its LEX - structure is not reusable for recursive calls. Thus we have - to prohibit recursion for stored procedures too. - */ - my_error(ER_SP_NO_RECURSION, MYF(0)); - DBUG_RETURN(-1); + DBUG_PRINT("info", + ("first free for 0x%lx ++: 0x%lx->0x%lx level: %lu flags %x", + (ulong)m_first_instance, (ulong) this, + (ulong) m_next_cached_sp, + m_next_cached_sp->m_recursion_level, + m_next_cached_sp->m_flags)); } - m_flags|= IS_INVOKED; + /* + Check that if there are not any instances after this one then + pointer to the last instance points on this instance or if there are + some instances after this one then recursion level of next instance + greater then recursion level of current instance on 1 + */ + DBUG_ASSERT((m_next_cached_sp == 0 && + m_first_instance->m_last_cached_sp == this) || + (m_recursion_level + 1 == m_next_cached_sp->m_recursion_level)); dbchanged= FALSE; if (m_db.length && - (ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, &dbchanged))) + (err_status= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, + &dbchanged))) goto done; if ((ctx= thd->spcont)) @@ -981,7 +1035,7 @@ int sp_head::execute(THD *thd) if (thd->prelocked_mode == NON_PRELOCKED) thd->user_var_events_alloc= thd->mem_root; - ret= i->execute(thd, &ip); + err_status= i->execute(thd, &ip); /* If this SP instruction have sent eof, it has caused no_send_error to be @@ -1004,16 +1058,15 @@ int sp_head::execute(THD *thd) } /* we should cleanup free_list and memroot, used by instruction */ - thd->free_items(); + thd->cleanup_after_query(); free_root(&execute_mem_root, MYF(0)); /* Check if an exception has occurred and a handler has been found - Note: We havo to check even if ret==0, since warnings (and some - errors don't return a non-zero value. - We also have to check even if thd->killed != 0, since some - errors return with this even when a handler has been found - (e.g. "bad data"). + Note: We have to check even if err_status == FALSE, since warnings (and + some errors) don't return a non-zero value. We also have to check even + if thd->killed != 0, since some errors return with this even when a + handler has been found (e.g. "bad data"). */ if (ctx) { @@ -1024,13 +1077,12 @@ int sp_head::execute(THD *thd) break; case SP_HANDLER_CONTINUE: thd->restore_active_arena(&execute_arena, &backup_arena); - ctx->save_variables(hf); thd->set_n_backup_active_arena(&execute_arena, &backup_arena); ctx->push_hstack(ip); // Fall through default: ip= hip; - ret= 0; + err_status= FALSE; ctx->clear_handler(); ctx->enter_handler(hip); thd->clear_error(); @@ -1038,7 +1090,7 @@ int sp_head::execute(THD *thd) continue; } } - } while (ret == 0 && !thd->killed); + } while (!err_status && !thd->killed); thd->restore_active_arena(&execute_arena, &backup_arena); @@ -1059,22 +1111,50 @@ int sp_head::execute(THD *thd) state= EXECUTED; done: - DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d", - ret, thd->killed, thd->query_error)); + DBUG_PRINT("info", ("err_status: %d killed: %d query_error: %d", + err_status, thd->killed, thd->query_error)); if (thd->killed) - ret= -1; - /* If the DB has changed, the pointer has changed too, but the - original thd->db will then have been freed */ + err_status= TRUE; + /* + If the DB has changed, the pointer has changed too, but the + original thd->db will then have been freed + */ if (dbchanged) { - /* No access check when changing back to where we came from. - (It would generate an error from mysql_change_db() when olddb=="") */ + /* + No access check when changing back to where we came from. + (It would generate an error from mysql_change_db() when olddb=="") + */ if (! thd->killed) - ret= mysql_change_db(thd, olddb, 1); + err_status|= mysql_change_db(thd, olddb, 1); } m_flags&= ~IS_INVOKED; - DBUG_RETURN(ret); + DBUG_PRINT("info", + ("first free for 0x%lx --: 0x%lx->0x%lx, level: %lu, flags %x", + (ulong) m_first_instance, + (ulong) m_first_instance->m_first_free_instance, + (ulong) this, m_recursion_level, m_flags)); + /* + Check that we have one of following: + + 1) there are not free instances which means that this instance is last + in the list of instances (pointer to the last instance point on it and + ther are not other instances after this one in the list) + + 2) There are some free instances which mean that first free instance + should go just after this one and recursion level of that free instance + should be on 1 more then recursion level of this instance. + */ + DBUG_ASSERT((m_first_instance->m_first_free_instance == 0 && + this == m_first_instance->m_last_cached_sp && + m_next_cached_sp == 0) || + (m_first_instance->m_first_free_instance != 0 && + m_first_instance->m_first_free_instance == m_next_cached_sp && + m_first_instance->m_first_free_instance->m_recursion_level == + m_recursion_level + 1)); + m_first_instance->m_first_free_instance= this; + DBUG_RETURN(err_status); } @@ -1086,33 +1166,41 @@ int sp_head::execute(THD *thd) SYNOPSIS sp_head::execute_function() - thd Thread handle - argp Passed arguments (these are items from containing statement?) - argcount Number of passed arguments. We need to check if this is - correct. - resp OUT Put result item here (q: is it a constant Item always?) + thd Thread handle + argp Passed arguments (these are items from containing + statement?) + argcount Number of passed arguments. We need to check if this is + correct. + return_value_fld Save result here. RETURN - 0 on OK - other on error + FALSE on success + TRUE on error */ -int -sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) +bool +sp_head::execute_function(THD *thd, Item **argp, uint argcount, + Field *return_value_fld) { - Item **param_values; + Item_cache **param_values; ulonglong binlog_save_options; bool need_binlog_call; - DBUG_ENTER("sp_head::execute_function"); - DBUG_PRINT("info", ("function %s", m_name.str)); - uint csize = m_pcont->max_pvars(); - uint params = m_pcont->current_pvars(); - uint hmax = m_pcont->max_handlers(); - uint cmax = m_pcont->max_cursors(); + uint params; sp_rcontext *octx = thd->spcont; sp_rcontext *nctx = NULL; - uint i; - int ret= -1; // Assume error + bool err_status= FALSE; + + DBUG_ENTER("sp_head::execute_function"); + DBUG_PRINT("info", ("function %s", m_name.str)); + + params = m_pcont->context_pvars(); + + /* + Check that the function is called with all specified arguments. + + If it is not, use my_error() to report an error, or it will not terminate + the invoking query properly. + */ if (argcount != params) { @@ -1122,34 +1210,56 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) */ my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0), "FUNCTION", m_qname.str, params, argcount); - goto end; + DBUG_RETURN(TRUE); } - if (!(param_values= (Item**)thd->alloc(sizeof(Item*)*argcount))) - DBUG_RETURN(-1); + /* Allocate param_values to be used for dumping the call into binlog. */ + + if (!(param_values= (Item_cache**)thd->alloc(sizeof(Item_cache*)*argcount))) + DBUG_RETURN(TRUE); // QQ Should have some error checking here? (types, etc...) - if (!(nctx= new sp_rcontext(octx, csize, hmax, cmax))) - goto end; - for (i= 0 ; i < argcount ; i++) - { - sp_pvar_t *pvar = m_pcont->find_pvar(i); - Item *it= sp_eval_func_item(thd, argp++, pvar->type, NULL, FALSE); - param_values[i]= it; - if (!it) - goto end; // EOM error - nctx->push_item(it); + if (!(nctx= new sp_rcontext(m_pcont, return_value_fld, octx)) || + nctx->init(thd)) + { + delete nctx; /* Delete nctx if it was init() that failed. */ + DBUG_RETURN(TRUE); } +#ifndef DBUG_OFF + nctx->sp= this; +#endif - /* - The rest of the frame are local variables which are all IN. - Push NULLs to get the right size (and make the reuse mechanism work) - - the will be initialized by set instructions in each frame. - */ - for (; i < csize ; i++) - nctx->push_item(NULL); + /* Pass arguments. */ + + { + uint i; + + for (i= 0 ; i < argcount ; i++) + { + if (!argp[i]->fixed && argp[i]->fix_fields(thd, &argp[i])) + { + err_status= TRUE; + break; + } + + param_values[i]= Item_cache::get_cache(argp[i]->result_type()); + param_values[i]->store(argp[i]); + + if (nctx->set_variable(thd, i, param_values[i])) + { + err_status= TRUE; + break; + } + } + } + + if (err_status) + { + delete nctx; + DBUG_RETURN(TRUE); + } thd->spcont= nctx; @@ -1162,7 +1272,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) } thd->options&= ~OPTION_BIN_LOG; - ret= execute(thd); + err_status= execute(thd); thd->options= binlog_save_options; if (need_binlog_call) @@ -1173,14 +1283,23 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) char buf[256]; String bufstr(buf, sizeof(buf), &my_charset_bin); bufstr.length(0); - bufstr.append("DO ", 3); + bufstr.append(STRING_WITH_LEN("DO ")); append_identifier(thd, &bufstr, m_name.str, m_name.length); bufstr.append('('); for (uint i=0; i < argcount; i++) { + String str_value_holder; + String *str_value; + if (i) bufstr.append(','); - param_values[i]->print(&bufstr); + + str_value= sp_get_item_value(param_values[i], &str_value_holder); + + if (str_value) + bufstr.append(*str_value); + else + bufstr.append(STRING_WITH_LEN("NULL")); } bufstr.append(')'); @@ -1196,26 +1315,22 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) reset_dynamic(&thd->user_var_events); } - if (m_type == TYPE_ENUM_FUNCTION && ret == 0) + if (m_type == TYPE_ENUM_FUNCTION && !err_status) { /* We need result only in function but not in trigger */ - Item *it= nctx->get_result(); - if (it) - *resp= sp_eval_func_item(thd, &it, m_returns, NULL, FALSE); - else + if (!nctx->is_return_value_set()) { my_error(ER_SP_NORETURNEND, MYF(0), m_name.str); - ret= -1; + err_status= TRUE; } } nctx->pop_all_cursors(); // To avoid memory leaks after an error - delete nctx; // Doesn't do anything + delete nctx; thd->spcont= octx; -end: - DBUG_RETURN(ret); + DBUG_RETURN(err_status); } @@ -1247,17 +1362,15 @@ static Item_func_get_user_var *item_is_user_var(Item *it) - copy back values of INOUT and OUT parameters RETURN - 0 Ok - -1 Error + FALSE on success + TRUE on error */ -int sp_head::execute_procedure(THD *thd, List<Item> *args) +bool +sp_head::execute_procedure(THD *thd, List<Item> *args) { - int ret= 0; - uint csize = m_pcont->max_pvars(); - uint params = m_pcont->current_pvars(); - uint hmax = m_pcont->max_handlers(); - uint cmax = m_pcont->max_cursors(); + bool err_status= FALSE; + uint params = m_pcont->context_pvars(); sp_rcontext *save_spcont, *octx; sp_rcontext *nctx = NULL; DBUG_ENTER("sp_head::execute_procedure"); @@ -1267,74 +1380,84 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args) { my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0), "PROCEDURE", m_qname.str, params, args->elements); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } save_spcont= octx= thd->spcont; if (! octx) { // Create a temporary old context - if (!(octx= new sp_rcontext(octx, csize, hmax, cmax))) - DBUG_RETURN(-1); + if (!(octx= new sp_rcontext(m_pcont, NULL, octx)) || + octx->init(thd)) + { + delete octx; /* Delete octx if it was init() that failed. */ + DBUG_RETURN(TRUE); + } + +#ifndef DBUG_OFF + octx->sp= 0; +#endif thd->spcont= octx; /* set callers_arena to thd, for upper-level function to work */ thd->spcont->callers_arena= thd; } - if (!(nctx= new sp_rcontext(octx, csize, hmax, cmax))) + if (!(nctx= new sp_rcontext(m_pcont, NULL, octx)) || + nctx->init(thd)) { + delete nctx; /* Delete nctx if it was init() that failed. */ thd->spcont= save_spcont; - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } +#ifndef DBUG_OFF + nctx->sp= this; +#endif - if (csize > 0 || hmax > 0 || cmax > 0) + if (params > 0) { - Item_null *nit= NULL; // Re-use this, and only create if needed - uint i; - List_iterator<Item> li(*args); - Item *it; + List_iterator<Item> it_args(*args); - /* Evaluate SP arguments (i.e. get the values passed as parameters) */ - // QQ: Should do type checking? DBUG_PRINT("info",(" %.*s: eval args", m_name.length, m_name.str)); - for (i = 0 ; (it= li++) && i < params ; i++) + + for (uint i= 0 ; i < params ; i++) { + Item *arg_item= it_args++; sp_pvar_t *pvar= m_pcont->find_pvar(i); - if (pvar) + if (!arg_item) + break; + + if (!pvar) + continue; + + if (pvar->mode != sp_param_in) { - if (pvar->mode != sp_param_in) - { - if (!it->is_splocal() && !item_is_user_var(it)) - { - my_error(ER_SP_NOT_VAR_ARG, MYF(0), i+1, m_qname.str); - ret= -1; - break; - } - } - if (pvar->mode == sp_param_out) - { - if (! nit) - { - if (!(nit= new Item_null())) - { - ret= -1; - break; - } - } - nctx->push_item(nit); // OUT - } - else - { - Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type, NULL, FALSE); - - if (!it2) - { - ret= -1; // Eval failed - break; - } - nctx->push_item(it2); // IN or INOUT - } + if (!arg_item->is_splocal() && !item_is_user_var(arg_item)) + { + my_error(ER_SP_NOT_VAR_ARG, MYF(0), i+1, m_qname.str); + err_status= TRUE; + break; + } + } + + if (pvar->mode == sp_param_out) + { + Item_null *null_item= new Item_null(); + + if (!null_item || + nctx->set_variable(thd, i, null_item)) + { + err_status= TRUE; + break; + } + } + else + { + if (nctx->set_variable(thd, i, *it_args.ref())) + { + err_status= TRUE; + break; + } } } @@ -1347,20 +1470,12 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args) close_thread_tables(thd, 0, 0); DBUG_PRINT("info",(" %.*s: eval args done", m_name.length, m_name.str)); - - /* - The rest of the frame are local variables which are all IN. - Push NULLs to get the right size (and make the reuse mechanism work) - - the will be initialized by set instructions in each frame. - */ - for (; i < csize ; i++) - nctx->push_item(NULL); } thd->spcont= nctx; - if (! ret) - ret= execute(thd); + if (!err_status) + err_status= execute(thd); /* In the case when we weren't able to employ reuse mechanism for @@ -1370,75 +1485,67 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args) */ thd->spcont->callers_arena= octx->callers_arena; - if (!ret && csize > 0) + if (!err_status && params > 0) { - List_iterator<Item> li(*args); - Item *it; + List_iterator<Item> it_args(*args); /* Copy back all OUT or INOUT values to the previous frame, or set global user variables */ - for (uint i = 0 ; (it= li++) && i < params ; i++) + for (uint i= 0 ; i < params ; i++) { + Item *arg_item= it_args++; + + if (!arg_item) + break; + sp_pvar_t *pvar= m_pcont->find_pvar(i); - if (pvar->mode != sp_param_in) + if (pvar->mode == sp_param_in) + continue; + + if (arg_item->is_splocal()) { - if (it->is_splocal()) - { - // Have to copy the item to the caller's mem_root - Item *copy; - uint offset= static_cast<Item_splocal *>(it)->get_offset(); - Item *val= nctx->get_item(i); - Item *orig= octx->get_item(offset); - - /* - We might need to allocate new item if we weren't able to - employ reuse mechanism. Then we should do it on the callers arena. - */ - copy= sp_eval_func_item(thd, &val, pvar->type, orig, TRUE); // Copy - - if (!copy) - { - ret= -1; - break; - } - if (copy != orig) - octx->set_item(offset, copy); - } - else + if (octx->set_variable(thd, + ((Item_splocal*) arg_item)->get_var_idx(), + nctx->get_item(i))) + { + err_status= TRUE; + break; + } + } + else + { + Item_func_get_user_var *guv= item_is_user_var(arg_item); + + if (guv) { - Item_func_get_user_var *guv= item_is_user_var(it); - - if (guv) - { - Item *item= nctx->get_item(i); - Item_func_set_user_var *suv; - - suv= new Item_func_set_user_var(guv->get_name(), item); - /* - we do not check suv->fixed, because it can't be fixed after - creation - */ - suv->fix_fields(thd, &item); - suv->fix_length_and_dec(); - suv->check(); - suv->update(); - } + Item *item= nctx->get_item(i); + Item_func_set_user_var *suv; + + suv= new Item_func_set_user_var(guv->get_name(), item); + /* + Item_func_set_user_var is not fixed after construction, + call fix_fields(). + */ + if ((err_status= test(!suv || suv->fix_fields(thd, &item) || + suv->check() || suv->update()))) + break; } } + } } if (!save_spcont) - delete octx; // Does nothing + delete octx; nctx->pop_all_cursors(); // To avoid memory leaks after an error - delete nctx; // Does nothing + delete nctx; thd->spcont= save_spcont; - DBUG_RETURN(ret); + DBUG_RETURN(err_status); } @@ -1474,6 +1581,15 @@ sp_head::reset_lex(THD *thd) sublex->trg_chistics= oldlex->trg_chistics; sublex->trg_table_fields.empty(); sublex->sp_lex_in_use= FALSE; + + /* Reset type info. */ + + sublex->charset= NULL; + sublex->length= NULL; + sublex->dec= NULL; + sublex->interval_list.empty(); + sublex->type= 0; + DBUG_VOID_RETURN; } @@ -1568,22 +1684,59 @@ sp_head::check_backpatch(THD *thd) return 0; } + +/* + Prepare an instance of create_field for field creation (fill all necessary + attributes). + + SYNOPSIS + sp_head::fill_field_definition() + thd [IN] Thread handle + lex [IN] Yacc parsing context + field_type [IN] Field type + field_def [OUT] An instance of create_field to be filled + + RETURN + FALSE on success + TRUE on error +*/ + +bool +sp_head::fill_field_definition(THD *thd, LEX *lex, + enum enum_field_types field_type, + create_field *field_def) +{ + LEX_STRING cmt = { 0, 0 }; + uint unused1= 0; + int unused2= 0; + + if (field_def->init(thd, (char*) "", field_type, lex->length, lex->dec, + lex->type, (Item*) 0, (Item*) 0, &cmt, 0, + &lex->interval_list, + (lex->charset ? lex->charset : default_charset_info), + lex->uint_geom_type)) + return TRUE; + + if (field_def->interval_list.elements) + field_def->interval= create_typelib(mem_root, field_def, + &field_def->interval_list); + + sp_prepare_create_field(thd, field_def); + + if (prepare_create_field(field_def, &unused1, &unused2, &unused2, + HA_CAN_GEOMETRY)) + { + return TRUE; + } + + return FALSE; +} + + void -sp_head::set_info(char *definer, uint definerlen, - longlong created, longlong modified, +sp_head::set_info(longlong created, longlong modified, st_sp_chistics *chistics, ulong sql_mode) { - char *p= strchr(definer, '@'); - uint len; - - if (! p) - p= definer; // Weird... - len= p-definer; - m_definer_user.str= strmake_root(mem_root, definer, len); - m_definer_user.length= len; - len= definerlen-len-1; - m_definer_host.str= strmake_root(mem_root, p+1, len); - m_definer_host.length= len; m_created= created; m_modified= modified; m_chistics= (st_sp_chistics *) memdup_root(mem_root, (char*) chistics, @@ -1597,6 +1750,34 @@ sp_head::set_info(char *definer, uint definerlen, m_sql_mode= sql_mode; } + +void + +sp_head::set_definer(const char *definer, uint definerlen) +{ + const char *p= strrchr(definer, '@'); + + if (!p) + { + m_definer_user.str= (char*) ""; + m_definer_user.length= 0; + m_definer_host.str= (char*) ""; + m_definer_host.length= 0; + } + else + { + const uint user_name_len= p - definer; + const uint host_name_len= definerlen - user_name_len - 1; + + m_definer_user.str= strmake_root(mem_root, definer, user_name_len); + m_definer_user.length= user_name_len; + + m_definer_host.str= strmake_root(mem_root, p + 1, host_name_len); + m_definer_host.length= host_name_len; + } +} + + void sp_head::reset_thd_mem_root(THD *thd) { @@ -1675,14 +1856,14 @@ sp_head::show_create_procedure(THD *thd) byte *sql_mode_str; ulong sql_mode_len; bool full_access; - DBUG_ENTER("sp_head::show_create_procedure"); DBUG_PRINT("info", ("procedure %s", m_name.str)); + LINT_INIT(sql_mode_str); LINT_INIT(sql_mode_len); if (check_show_routine_access(thd, this, &full_access)) - return 1; + DBUG_RETURN(1); sql_mode_str= sys_var_thd_sql_mode::symbolic_mode_representation(thd, @@ -1695,10 +1876,7 @@ sp_head::show_create_procedure(THD *thd) max(buffer.length(), 1024))); if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) - { - res= 1; - goto done; - } + DBUG_RETURN(1); protocol->prepare_for_resend(); protocol->store(m_name.str, m_name.length, system_charset_info); protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info); @@ -1707,7 +1885,6 @@ sp_head::show_create_procedure(THD *thd) res= protocol->write(); send_eof(thd); - done: DBUG_RETURN(res); } @@ -1752,7 +1929,7 @@ sp_head::show_create_function(THD *thd) LINT_INIT(sql_mode_len); if (check_show_routine_access(thd, this, &full_access)) - return 1; + DBUG_RETURN(1); sql_mode_str= sys_var_thd_sql_mode::symbolic_mode_representation(thd, @@ -1764,10 +1941,7 @@ sp_head::show_create_function(THD *thd) max(buffer.length(),1024))); if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) - { - res= 1; - goto done; - } + DBUG_RETURN(1); protocol->prepare_for_resend(); protocol->store(m_name.str, m_name.length, system_charset_info); protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info); @@ -1776,7 +1950,6 @@ sp_head::show_create_function(THD *thd) res= protocol->write(); send_eof(thd); - done: DBUG_RETURN(res); } @@ -1836,6 +2009,50 @@ sp_head::opt_mark(uint ip) } +#ifndef DBUG_OFF +int +sp_head::show_routine_code(THD *thd) +{ + Protocol *protocol= thd->protocol; + char buff[2048]; + String buffer(buff, sizeof(buff), system_charset_info); + List<Item> field_list; + sp_instr *i; + bool full_access; + int res= 0; + uint ip; + DBUG_ENTER("sp_head::show_routine_code"); + DBUG_PRINT("info", ("procedure: %s", m_name.str)); + + if (check_show_routine_access(thd, this, &full_access) || !full_access) + DBUG_RETURN(1); + + field_list.push_back(new Item_uint("Pos", 9)); + // 1024 is for not to confuse old clients + field_list.push_back(new Item_empty_string("Instruction", + max(buffer.length(), 1024))); + if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF)) + DBUG_RETURN(1); + + for (ip= 0; (i = get_instr(ip)) ; ip++) + { + protocol->prepare_for_resend(); + protocol->store((longlong)ip); + + buffer.set("", 0, system_charset_info); + i->print(&buffer); + protocol->store(buffer.ptr(), buffer.length(), system_charset_info); + if ((res= protocol->write())) + break; + } + send_eof(thd); + + DBUG_RETURN(res); +} +#endif // ifndef DBUG_OFF + + /* Prepare LEX and thread for execution of instruction, if requested open and lock LEX's tables, execute instruction's core function, perform @@ -1944,7 +2161,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, cleanup_items() is called in sp_head::execute() */ - return res; + return res || thd->net.report_error; } @@ -1994,12 +2211,36 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) DBUG_RETURN(res); } + void sp_instr_stmt::print(String *str) { - str->reserve(12); - str->append("stmt "); + uint i, len; + + /* stmt CMD "..." */ + if (str->reserve(SP_STMT_PRINT_MAXLEN+SP_INSTR_UINT_MAXLEN+8)) + return; + str->qs_append(STRING_WITH_LEN("stmt ")); str->qs_append((uint)m_lex_keeper.sql_command()); + str->qs_append(STRING_WITH_LEN(" \"")); + len= m_query.length; + /* + Print the query string (but not too much of it), just to indicate which + statement it is. + */ + if (len > SP_STMT_PRINT_MAXLEN) + len= SP_STMT_PRINT_MAXLEN-3; + /* Copy the query string and replace '\n' with ' ' in the process */ + for (i= 0 ; i < len ; i++) + { + char c= m_query.str[i]; + if (c == '\n') + c= ' '; + str->qs_append(c); + } + if (m_query.length > SP_STMT_PRINT_MAXLEN) + str->qs_append(STRING_WITH_LEN("...")); /* Indicate truncated string */ + str->qs_append('"'); } @@ -2029,7 +2270,27 @@ sp_instr_set::execute(THD *thd, uint *nextp) int sp_instr_set::exec_core(THD *thd, uint *nextp) { - int res= thd->spcont->set_item_eval(thd, m_offset, &m_value, m_type); + int res= thd->spcont->set_variable(thd, m_offset, m_value); + + if (res && thd->spcont->found_handler_here()) + { + /* + Failed to evaluate the value, and a handler has been found. Reset the + variable to NULL. + */ + + if (thd->spcont->set_variable(thd, m_offset, 0)) + { + /* If this also failed, let's abort. */ + + sp_rcontext *spcont= thd->spcont; + + thd->spcont= 0; /* Avoid handlers */ + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + spcont->clear_handler(); + thd->spcont= spcont; + } + } *nextp = m_ip+1; return res; @@ -2038,10 +2299,23 @@ sp_instr_set::exec_core(THD *thd, uint *nextp) void sp_instr_set::print(String *str) { - str->reserve(12); - str->append("set "); + /* set name@offset ... */ + int rsrv = SP_INSTR_UINT_MAXLEN+6; + sp_pvar_t *var = m_ctx->find_pvar(m_offset); + + /* 'var' should always be non-null, but just in case... */ + if (var) + rsrv+= var->name.length; + if (str->reserve(rsrv)) + return; + str->qs_append(STRING_WITH_LEN("set ")); + if (var) + { + str->qs_append(var->name.str, var->name.length); + str->qs_append('@'); + } str->qs_append(m_offset); - str->append(' '); + str->qs_append(' '); m_value->print(str); } @@ -2074,9 +2348,9 @@ sp_instr_set_trigger_field::exec_core(THD *thd, uint *nextp) void sp_instr_set_trigger_field::print(String *str) { - str->append("set ", 4); + str->append(STRING_WITH_LEN("set_trigger_field ")); trigger_field->print(str); - str->append(":=", 2); + str->append(STRING_WITH_LEN(":=")); value->print(str); } @@ -2098,8 +2372,10 @@ sp_instr_jump::execute(THD *thd, uint *nextp) void sp_instr_jump::print(String *str) { - str->reserve(12); - str->append("jump "); + /* jump dest */ + if (str->reserve(SP_INSTR_UINT_MAXLEN+5)) + return; + str->qs_append(STRING_WITH_LEN("jump ")); str->qs_append(m_dest); } @@ -2180,10 +2456,12 @@ sp_instr_jump_if::exec_core(THD *thd, uint *nextp) void sp_instr_jump_if::print(String *str) { - str->reserve(12); - str->append("jump_if "); + /* jump_if dest ... */ + if (str->reserve(SP_INSTR_UINT_MAXLEN+8+32)) // Add some for the expr. too + return; + str->qs_append(STRING_WITH_LEN("jump_if ")); str->qs_append(m_dest); - str->append(' '); + str->qs_append(' '); m_expr->print(str); } @@ -2241,10 +2519,12 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp) void sp_instr_jump_if_not::print(String *str) { - str->reserve(16); - str->append("jump_if_not "); + /* jump_if_not dest ... */ + if (str->reserve(SP_INSTR_UINT_MAXLEN+12+32)) // Add some for the expr. too + return; + str->qs_append(STRING_WITH_LEN("jump_if_not ")); str->qs_append(m_dest); - str->append(' '); + str->qs_append(' '); m_expr->print(str); } @@ -2280,29 +2560,33 @@ sp_instr_freturn::execute(THD *thd, uint *nextp) int sp_instr_freturn::exec_core(THD *thd, uint *nextp) { - Item *it; - int res; + /* + Change <next instruction pointer>, so that this will be the last + instruction in the stored function. + */ - it= sp_eval_func_item(thd, &m_value, m_type, NULL, TRUE); - if (! it) - res= -1; - else - { - res= 0; - thd->spcont->set_result(it); - } *nextp= UINT_MAX; - return res; + /* + Evaluate the value of return expression and store it in current runtime + context. + + NOTE: It's necessary to evaluate result item right here, because we must + do it in scope of execution the current context/block. + */ + + return thd->spcont->set_return_value(thd, m_value); } void sp_instr_freturn::print(String *str) { - str->reserve(12); - str->append("freturn "); + /* freturn type expr... */ + if (str->reserve(UINT_MAX+8+32)) // Add some for the expr. too + return; + str->qs_append(STRING_WITH_LEN("freturn ")); str->qs_append((uint)m_type); - str->append(' '); + str->qs_append(' '); m_value->print(str); } @@ -2324,20 +2608,38 @@ sp_instr_hpush_jump::execute(THD *thd, uint *nextp) DBUG_RETURN(0); } + void sp_instr_hpush_jump::print(String *str) { - str->reserve(32); - str->append("hpush_jump "); + /* hpush_jump dest fsize type */ + if (str->reserve(SP_INSTR_UINT_MAXLEN*2 + 21)) + return; + str->qs_append(STRING_WITH_LEN("hpush_jump ")); str->qs_append(m_dest); - str->append(" t="); - str->qs_append(m_type); - str->append(" f="); + str->qs_append(' '); str->qs_append(m_frame); - str->append(" h="); - str->qs_append(m_ip+1); + switch (m_type) { + case SP_HANDLER_NONE: + str->qs_append(STRING_WITH_LEN(" NONE")); // This would be a bug + break; + case SP_HANDLER_EXIT: + str->qs_append(STRING_WITH_LEN(" EXIT")); + break; + case SP_HANDLER_CONTINUE: + str->qs_append(STRING_WITH_LEN(" CONTINUE")); + break; + case SP_HANDLER_UNDO: + str->qs_append(STRING_WITH_LEN(" UNDO")); + break; + default: + // This would be a bug as well + str->qs_append(STRING_WITH_LEN(" UNKNOWN:")); + str->qs_append(m_type); + } } + uint sp_instr_hpush_jump::opt_mark(sp_head *sp) { @@ -2370,8 +2672,10 @@ sp_instr_hpop::execute(THD *thd, uint *nextp) void sp_instr_hpop::print(String *str) { - str->reserve(12); - str->append("hpop "); + /* hpop count */ + if (str->reserve(SP_INSTR_UINT_MAXLEN+5)) + return; + str->qs_append(STRING_WITH_LEN("hpop ")); str->qs_append(m_count); } @@ -2394,7 +2698,6 @@ sp_instr_hreturn::execute(THD *thd, uint *nextp) *nextp= m_dest; else { - thd->spcont->restore_variables(m_frame); *nextp= thd->spcont->pop_hstack(); } thd->spcont->exit_handler(); @@ -2405,12 +2708,14 @@ sp_instr_hreturn::execute(THD *thd, uint *nextp) void sp_instr_hreturn::print(String *str) { - str->reserve(16); - str->append("hreturn "); + /* hreturn framesize dest */ + if (str->reserve(SP_INSTR_UINT_MAXLEN*2 + 9)) + return; + str->qs_append(STRING_WITH_LEN("hreturn ")); str->qs_append(m_frame); if (m_dest) { - str->append(' '); + str->qs_append(' '); str->qs_append(m_dest); } } @@ -2458,7 +2763,22 @@ sp_instr_cpush::execute(THD *thd, uint *nextp) void sp_instr_cpush::print(String *str) { - str->append("cpush"); + LEX_STRING n; + my_bool found= m_ctx->find_cursor(m_cursor, &n); + /* cpush name@offset */ + uint rsrv= SP_INSTR_UINT_MAXLEN+7; + + if (found) + rsrv+= n.length; + if (str->reserve(rsrv)) + return; + str->qs_append(STRING_WITH_LEN("cpush ")); + if (found) + { + str->qs_append(n.str, n.length); + str->qs_append('@'); + } + str->qs_append(m_cursor); } @@ -2479,8 +2799,10 @@ sp_instr_cpop::execute(THD *thd, uint *nextp) void sp_instr_cpop::print(String *str) { - str->reserve(12); - str->append("cpop "); + /* cpop count */ + if (str->reserve(SP_INSTR_UINT_MAXLEN+5)) + return; + str->qs_append(STRING_WITH_LEN("cpop ")); str->qs_append(m_count); } @@ -2554,8 +2876,21 @@ sp_instr_copen::exec_core(THD *thd, uint *nextp) void sp_instr_copen::print(String *str) { - str->reserve(12); - str->append("copen "); + LEX_STRING n; + my_bool found= m_ctx->find_cursor(m_cursor, &n); + /* copen name@offset */ + uint rsrv= SP_INSTR_UINT_MAXLEN+7; + + if (found) + rsrv+= n.length; + if (str->reserve(rsrv)) + return; + str->qs_append(STRING_WITH_LEN("copen ")); + if (found) + { + str->qs_append(n.str, n.length); + str->qs_append('@'); + } str->qs_append(m_cursor); } @@ -2583,8 +2918,21 @@ sp_instr_cclose::execute(THD *thd, uint *nextp) void sp_instr_cclose::print(String *str) { - str->reserve(12); - str->append("cclose "); + LEX_STRING n; + my_bool found= m_ctx->find_cursor(m_cursor, &n); + /* cclose name@offset */ + uint rsrv= SP_INSTR_UINT_MAXLEN+8; + + if (found) + rsrv+= n.length; + if (str->reserve(rsrv)) + return; + str->qs_append(STRING_WITH_LEN("cclose ")); + if (found) + { + str->qs_append(n.str, n.length); + str->qs_append('@'); + } str->qs_append(m_cursor); } @@ -2613,14 +2961,29 @@ sp_instr_cfetch::print(String *str) { List_iterator_fast<struct sp_pvar> li(m_varlist); sp_pvar_t *pv; - - str->reserve(12); - str->append("cfetch "); + LEX_STRING n; + my_bool found= m_ctx->find_cursor(m_cursor, &n); + /* cfetch name@offset vars... */ + uint rsrv= SP_INSTR_UINT_MAXLEN+8; + + if (found) + rsrv+= n.length; + if (str->reserve(rsrv)) + return; + str->qs_append(STRING_WITH_LEN("cfetch ")); + if (found) + { + str->qs_append(n.str, n.length); + str->qs_append('@'); + } str->qs_append(m_cursor); while ((pv= li++)) { - str->reserve(8); - str->append(' '); + if (str->reserve(pv->name.length+SP_INSTR_UINT_MAXLEN+2)) + return; + str->qs_append(' '); + str->qs_append(pv->name.str, pv->name.length); + str->qs_append('@'); str->qs_append(pv->offset); } } @@ -2644,12 +3007,73 @@ sp_instr_error::execute(THD *thd, uint *nextp) void sp_instr_error::print(String *str) { - str->reserve(12); - str->append("error "); + /* error code */ + if (str->reserve(SP_INSTR_UINT_MAXLEN+6)) + return; + str->qs_append(STRING_WITH_LEN("error ")); str->qs_append(m_errcode); } +/************************************************************************** + sp_instr_set_case_expr class implementation +**************************************************************************/ + +int +sp_instr_set_case_expr::execute(THD *thd, uint *nextp) +{ + DBUG_ENTER("sp_instr_set_case_expr::execute"); + + DBUG_RETURN(m_lex_keeper.reset_lex_and_exec_core(thd, nextp, TRUE, this)); +} + + +int +sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp) +{ + int res= thd->spcont->set_case_expr(thd, m_case_expr_id, m_case_expr); + + if (res && + !thd->spcont->get_case_expr(m_case_expr_id) && + thd->spcont->found_handler_here()) + { + /* + Failed to evaluate the value, the case expression is still not + initialized, and a handler has been found. Set to NULL so we can continue. + */ + + Item *null_item= new Item_null(); + + if (!null_item || + thd->spcont->set_case_expr(thd, m_case_expr_id, null_item)) + { + /* If this also failed, we have to abort. */ + + sp_rcontext *spcont= thd->spcont; + + thd->spcont= 0; /* Avoid handlers */ + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + spcont->clear_handler(); + thd->spcont= spcont; + } + } + + *nextp = m_ip+1; + + return res; /* no error */ +} + + +void +sp_instr_set_case_expr::print(String *str) +{ + str->append(STRING_WITH_LEN("set_case_expr ")); + str->qs_append(m_case_expr_id); + str->append(' '); + m_case_expr->print(str); +} + + /* ------------------------------------------------------------------ */ /* @@ -2822,10 +3246,12 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) SYNOPSIS add_used_tables_to_table_list() - thd - thread context - query_tables_last_ptr - (in/out) pointer the next_global member of last - element of the list where tables will be added - (or to its root). + thd [in] Thread context + query_tables_last_ptr [in/out] Pointer to the next_global member of + last element of the list where tables + will be added (or to its root). + belong_to_view [in] Uppermost view which uses this routine, + 0 if none. DESCRIPTION Converts multi-set of tables used by this routine to table list and adds @@ -2840,7 +3266,8 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) bool sp_head::add_used_tables_to_table_list(THD *thd, - TABLE_LIST ***query_tables_last_ptr) + TABLE_LIST ***query_tables_last_ptr, + TABLE_LIST *belong_to_view) { uint i; Query_arena *arena, backup; @@ -2848,33 +3275,34 @@ sp_head::add_used_tables_to_table_list(THD *thd, DBUG_ENTER("sp_head::add_used_tables_to_table_list"); /* - Use persistent arena for table list allocation to be PS friendly. + Use persistent arena for table list allocation to be PS/SP friendly. + Note that we also have to copy database/table names and alias to PS/SP + memory since current instance of sp_head object can pass away before + next execution of PS/SP for which tables are added to prelocking list. + This will be fixed by introducing of proper invalidation mechanism + once new TDC is ready. */ arena= thd->activate_stmt_arena_if_needed(&backup); for (i=0 ; i < m_sptabs.records ; i++) { - char *tab_buff; + char *tab_buff, *key_buff; TABLE_LIST *table; SP_TABLE *stab= (SP_TABLE *)hash_element(&m_sptabs, i); if (stab->temp) continue; if (!(tab_buff= (char *)thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST)) * - stab->lock_count))) + stab->lock_count)) || + !(key_buff= (char*)thd->memdup(stab->qname.str, + stab->qname.length + 1))) DBUG_RETURN(FALSE); for (uint j= 0; j < stab->lock_count; j++) { table= (TABLE_LIST *)tab_buff; - /* - It's enough to just copy the pointers as the data will not change - during the lifetime of the SP. If the SP is used by PS, we assume - that the PS will be invalidated if the functions is deleted or - changed. - */ - table->db= stab->qname.str; + table->db= key_buff; table->db_length= stab->db_length; table->table_name= table->db + table->db_length + 1; table->table_name_length= stab->table_name_length; @@ -2882,6 +3310,7 @@ sp_head::add_used_tables_to_table_list(THD *thd, table->lock_type= stab->lock_type; table->cacheable_table= 1; table->prelocking_placeholder= 1; + table->belong_to_view= belong_to_view; /* Everyting else should be zeroed */ diff --git a/sql/sp_head.h b/sql/sp_head.h index ed0f3987e01..2eebd35f6dc 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -33,6 +33,9 @@ Item_result sp_map_result_type(enum enum_field_types type); +Item::Type +sp_map_item_type(enum enum_field_types type); + uint sp_get_flags_for_command(LEX *lex); @@ -115,17 +118,17 @@ public: MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s) CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE IS_INVOKED= 32, // Is set if this sp_head is being used - HAS_SET_AUTOCOMMIT_STMT = 64 // Is set if a procedure with 'set autocommit' + HAS_SET_AUTOCOMMIT_STMT= 64,// Is set if a procedure with 'set autocommit' + /* Is set if a procedure with COMMIT (implicit or explicit) | ROLLBACK */ + HAS_COMMIT_OR_ROLLBACK= 128 }; - int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE + /* TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */ + int m_type; uint m_flags; // Boolean attributes of a stored routine - enum enum_field_types m_returns; // For FUNCTIONs only - Field::geometry_type m_geom_returns; - CHARSET_INFO *m_returns_cs; // For FUNCTIONs only - TYPELIB *m_returns_typelib; // For FUNCTIONs only - uint m_returns_len; // For FUNCTIONs only - uint m_returns_pack; // For FUNCTIONs only + + create_field m_return_field_def; /* This is used for FUNCTIONs only. */ + uchar *m_tmp_query; // Temporary pointer to sub query string uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value st_sp_chistics *m_chistics; @@ -140,6 +143,32 @@ public: LEX_STRING m_definer_host; longlong m_created; longlong m_modified; + /* Recursion level of the current SP instance. The levels are numbered from 0 */ + ulong m_recursion_level; + /* + A list of diferent recursion level instances for the same procedure. + For every recursion level we have a sp_head instance. This instances + connected in the list. The list ordered by increasing recursion level + (m_recursion_level). + */ + sp_head *m_next_cached_sp; + /* + Pointer to the first element of the above list + */ + sp_head *m_first_instance; + /* + Pointer to the first free (non-INVOKED) routine in the list of + cached instances for this SP. This pointer is set only for the first + SP in the list of instences (see above m_first_cached_sp pointer). + The pointer equal to 0 if we have no free instances. + For non-first instance value of this pointer meanless (point to itself); + */ + sp_head *m_first_free_instance; + /* + Pointer to the last element in the list of instances of the SP. + For non-first instance value of this pointer meanless (point to itself); + */ + sp_head *m_last_cached_sp; /* Set containing names of stored routines used by this routine. Note that unlike elements of similar set for statement elements of this @@ -173,9 +202,6 @@ public: void init_strings(THD *thd, LEX *lex, sp_name *name); - TYPELIB * - create_typelib(List<String> *src); - int create(THD *thd); @@ -185,10 +211,10 @@ public: void destroy(); - int - execute_function(THD *thd, Item **args, uint argcount, Item **resp); + bool + execute_function(THD *thd, Item **args, uint argcount, Field *return_fld); - int + bool execute_procedure(THD *thd, List<Item> *args); int @@ -249,12 +275,18 @@ public: char *create_string(THD *thd, ulong *lenp); - Field *make_field(uint max_length, const char *name, TABLE *dummy); + Field *create_result_field(uint field_max_length, const char *field_name, + TABLE *table); - void set_info(char *definer, uint definerlen, - longlong created, longlong modified, + bool fill_field_definition(THD *thd, LEX *lex, + enum enum_field_types field_type, + create_field *field_def); + + void set_info(longlong created, longlong modified, st_sp_chistics *chistics, ulong sql_mode); + void set_definer(const char *definer, uint definerlen); + void reset_thd_mem_root(THD *thd); void restore_thd_mem_root(THD *thd); @@ -262,6 +294,8 @@ public: void optimize(); void opt_mark(uint ip); + void recursion_level_error(THD *thd); + inline sp_instr * get_instr(uint i) { @@ -276,7 +310,8 @@ public: /* Add tables used by routine to the table list. */ bool add_used_tables_to_table_list(THD *thd, - TABLE_LIST ***query_tables_last_ptr); + TABLE_LIST ***query_tables_last_ptr, + TABLE_LIST *belong_to_view); /* Check if this stored routine contains statements disallowed @@ -291,9 +326,21 @@ public: my_error(ER_SP_NO_RETSET, MYF(0), where); else if (m_flags & HAS_SET_AUTOCOMMIT_STMT) my_error(ER_SP_CANT_SET_AUTOCOMMIT, MYF(0)); + else if (m_type != TYPE_ENUM_PROCEDURE && + (m_flags & sp_head::HAS_COMMIT_OR_ROLLBACK)) + { + my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); + return TRUE; + } return test(m_flags & (CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT)); } + +#ifndef DBUG_OFF + int show_routine_code(THD *thd); +#endif + + private: MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root @@ -319,7 +366,7 @@ private: */ HASH m_sptabs; - int + bool execute(THD *thd); /* @@ -855,8 +902,8 @@ class sp_instr_cpush : public sp_instr public: - sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex) - : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE) + sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex, uint offset) + : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE), m_cursor(offset) {} virtual ~sp_instr_cpush() @@ -875,6 +922,7 @@ public: private: sp_lex_keeper m_lex_keeper; + uint m_cursor; /* Frame offset (for debugging) */ }; // class sp_instr_cpush : public sp_instr @@ -1029,6 +1077,31 @@ private: }; // class sp_instr_error : public sp_instr +class sp_instr_set_case_expr :public sp_instr +{ +public: + + sp_instr_set_case_expr(uint ip, sp_pcontext *ctx, uint case_expr_id, + Item *case_expr, LEX *lex) + :sp_instr(ip, ctx), m_case_expr_id(case_expr_id), m_case_expr(case_expr), + m_lex_keeper(lex, TRUE) + {} + + virtual int execute(THD *thd, uint *nextp); + + virtual int exec_core(THD *thd, uint *nextp); + + virtual void print(String *str); + +private: + + uint m_case_expr_id; + Item *m_case_expr; + sp_lex_keeper m_lex_keeper; + +}; // class sp_instr_set_case_expr : public sp_instr + + #ifndef NO_EMBEDDED_ACCESS_CHECKS bool sp_change_security_context(THD *thd, sp_head *sp, @@ -1041,8 +1114,10 @@ TABLE_LIST * sp_add_to_query_tables(THD *thd, LEX *lex, const char *db, const char *name, thr_lock_type locktype); +Item * +sp_prepare_func_item(THD* thd, Item **it_addr); -Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type, - Item *reuse, bool use_callers_arena); +bool +sp_eval_expr(THD *thd, Field *result_field, Item *expr_item); #endif /* _SP_HEAD_H_ */ diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index f873b676925..a8bd8cd2aa0 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -51,21 +51,26 @@ sp_cond_check(LEX_STRING *sqlstate) } sp_pcontext::sp_pcontext(sp_pcontext *prev) - : Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0), - m_handlers(0), m_parent(prev) + :Sql_alloc(), m_total_pvars(0), m_csubsize(0), m_hsubsize(0), + m_handlers(0), m_parent(prev), m_pboundary(0) { VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8)); + VOID(my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), 16, 8)); VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8)); VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8)); VOID(my_init_dynamic_array(&m_handler, sizeof(sp_cond_type_t *), 16, 8)); m_label.empty(); m_children.empty(); if (!prev) + { m_poffset= m_coffset= 0; + m_num_case_exprs= 0; + } else { - m_poffset= prev->current_pvars(); + m_poffset= prev->m_poffset + prev->m_total_pvars; m_coffset= prev->current_cursors(); + m_num_case_exprs= prev->get_num_case_exprs(); } } @@ -81,6 +86,7 @@ sp_pcontext::destroy() m_children.empty(); m_label.empty(); delete_dynamic(&m_pvar); + delete_dynamic(&m_case_expr_id_lst); delete_dynamic(&m_cond); delete_dynamic(&m_cursor); delete_dynamic(&m_handler); @@ -99,16 +105,19 @@ sp_pcontext::push_context() sp_pcontext * sp_pcontext::pop_context() { - uint submax= max_pvars(); + m_parent->m_total_pvars= m_parent->m_total_pvars + m_total_pvars; - if (submax > m_parent->m_psubsize) - m_parent->m_psubsize= submax; - submax= max_handlers(); + uint submax= max_handlers(); if (submax > m_parent->m_hsubsize) m_parent->m_hsubsize= submax; + submax= max_cursors(); if (submax > m_parent->m_csubsize) m_parent->m_csubsize= submax; + + if (m_num_case_exprs > m_parent->m_num_case_exprs) + m_parent->m_num_case_exprs= m_num_case_exprs; + return m_parent; } @@ -150,7 +159,7 @@ sp_pcontext::diff_cursors(sp_pcontext *ctx) sp_pvar_t * sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped) { - uint i= m_pvar.elements; + uint i= m_pvar.elements - m_pboundary; while (i--) { @@ -169,26 +178,51 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped) return NULL; } -void +/* + Find a variable by offset from the top. + This used for two things: + - When evaluating parameters at the beginning, and setting out parameters + at the end, of invokation. (Top frame only, so no recursion then.) + - For printing of sp_instr_set. (Debug mode only.) + */ +sp_pvar_t * +sp_pcontext::find_pvar(uint offset) +{ + if (m_poffset <= offset && offset < m_poffset + m_pvar.elements) + { // This frame + sp_pvar_t *p; + + get_dynamic(&m_pvar, (gptr)&p, offset - m_poffset); + return p; + } + if (m_parent) + return m_parent->find_pvar(offset); // Some previous frame + return NULL; // index out of bounds +} + +sp_pvar_t * sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type, sp_param_mode_t mode) { sp_pvar_t *p= (sp_pvar_t *)sql_alloc(sizeof(sp_pvar_t)); - if (p) - { - if (m_pvar.elements == m_psubsize) - m_psubsize+= 1; - p->name.str= name->str; - p->name.length= name->length; - p->type= type; - p->mode= mode; - p->offset= current_pvars(); - p->dflt= NULL; - insert_dynamic(&m_pvar, (gptr)&p); - } + if (!p) + return NULL; + + ++m_total_pvars; + + p->name.str= name->str; + p->name.length= name->length; + p->type= type; + p->mode= mode; + p->offset= current_pvars(); + p->dflt= NULL; + insert_dynamic(&m_pvar, (gptr)&p); + + return p; } + sp_label_t * sp_pcontext::push_label(char *name, uint ip) { @@ -331,3 +365,44 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped) return m_parent->find_cursor(name, poff, scoped); return FALSE; } + + +void +sp_pcontext::retrieve_field_definitions(List<create_field> *field_def_lst) +{ + /* Put local/context fields in the result list. */ + + for (uint i = 0; i < m_pvar.elements; ++i) + { + sp_pvar_t *var_def; + get_dynamic(&m_pvar, (gptr) &var_def, i); + + field_def_lst->push_back(&var_def->field_def); + } + + /* Put the fields of the enclosed contexts in the result list. */ + + List_iterator_fast<sp_pcontext> li(m_children); + sp_pcontext *ctx; + + while ((ctx = li++)) + ctx->retrieve_field_definitions(field_def_lst); +} + +/* + Find a cursor by offset from the top. + This is only used for debugging. + */ +my_bool +sp_pcontext::find_cursor(uint offset, LEX_STRING *n) +{ + if (m_coffset <= offset && offset < m_coffset + m_cursor.elements) + { // This frame + get_dynamic(&m_cursor, (gptr)n, offset - m_coffset); + return TRUE; + } + if (m_parent) + return m_parent->find_cursor(offset, n); // Some previous frame + return FALSE; // index out of bounds +} + diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index bd2259cb6fb..6d803362d86 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -34,8 +34,16 @@ typedef struct sp_pvar LEX_STRING name; enum enum_field_types type; sp_param_mode_t mode; - uint offset; // Offset in current frame + + /* + offset -- basically, this is an index of variable in the scope of root + parsing context. This means, that all variables in a stored routine + have distinct indexes/offsets. + */ + uint offset; + Item *dflt; + create_field field_def; } sp_pvar_t; @@ -114,9 +122,9 @@ class sp_pcontext : public Sql_alloc // inline uint - max_pvars() + total_pvars() { - return m_psubsize + m_pvar.elements; + return m_total_pvars; } inline uint @@ -155,32 +163,71 @@ class sp_pcontext : public Sql_alloc p->dflt= it; } - void + sp_pvar_t * push_pvar(LEX_STRING *name, enum enum_field_types type, sp_param_mode_t mode); - // Pop the last 'num' slots of the frame - inline void - pop_pvar(uint num = 1) - { - while (num--) - pop_dynamic(&m_pvar); - } + /* + Retrieve definitions of fields from the current context and its + children. + */ + void + retrieve_field_definitions(List<create_field> *field_def_lst); // Find by name sp_pvar_t * find_pvar(LEX_STRING *name, my_bool scoped=0); - // Find by index + // Find by offset sp_pvar_t * - find_pvar(uint i) + find_pvar(uint offset); + + /* + Set the current scope boundary (for default values). + The argument is the number of variables to skip. + */ + inline void + declare_var_boundary(uint n) + { + m_pboundary= n; + } + + /* + CASE expressions support. + */ + + inline int + register_case_expr() + { + return m_num_case_exprs++; + } + + inline int + get_num_case_exprs() const + { + return m_num_case_exprs; + } + + inline bool + push_case_expr_id(int case_expr_id) + { + return insert_dynamic(&m_case_expr_id_lst, (gptr) &case_expr_id); + } + + inline void + pop_case_expr_id() + { + pop_dynamic(&m_case_expr_id_lst); + } + + inline int + get_current_case_expr_id() const { - sp_pvar_t *p; + int case_expr_id; - if (i < m_pvar.elements) - get_dynamic(&m_pvar, (gptr)&p, i); - else - p= NULL; - return p; + get_dynamic((DYNAMIC_ARRAY*)&m_case_expr_id_lst, (gptr) &case_expr_id, + m_case_expr_id_lst.elements - 1); + + return case_expr_id; } // @@ -261,6 +308,10 @@ class sp_pcontext : public Sql_alloc my_bool find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0); + /* Find by offset (for debugging only) */ + my_bool + find_cursor(uint offset, LEX_STRING *n); + inline uint max_cursors() { @@ -275,8 +326,18 @@ class sp_pcontext : public Sql_alloc protected: + /* + m_total_pvars -- number of variables (including all types of arguments) + in this context including all children contexts. + + m_total_pvars >= m_pvar.elements. + + m_total_pvars of the root parsing context contains number of all + variables (including arguments) in all enclosed contexts. + */ + uint m_total_pvars; + // The maximum sub context's framesizes - uint m_psubsize; uint m_csubsize; uint m_hsubsize; uint m_handlers; // No. of handlers in this context @@ -285,10 +346,31 @@ private: sp_pcontext *m_parent; // Parent context - uint m_poffset; // Variable offset for this context + /* + m_poffset -- basically, this is an index of the first variable in this + parsing context. + + m_poffset is 0 for root context. + + Since now each variable is stored in separate place, no reuse is done, + so m_poffset is different for all enclosed contexts. + */ + uint m_poffset; + uint m_coffset; // Cursor offset for this context + /* + Boundary for finding variables in this context. This is the number + of variables currently "invisible" to default clauses. + This is normally 0, but will be larger during parsing of + DECLARE ... DEFAULT, to get the scope right for DEFAULT values. + */ + uint m_pboundary; + + int m_num_case_exprs; + DYNAMIC_ARRAY m_pvar; // Parameters/variables + DYNAMIC_ARRAY m_case_expr_id_lst; /* Stack of CASE expression ids. */ DYNAMIC_ARRAY m_cond; // Conditions DYNAMIC_ARRAY m_cursor; // Cursors DYNAMIC_ARRAY m_handler; // Handlers, for checking of duplicates diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index ccb38358049..eca87e69f8e 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -29,41 +29,137 @@ #include "sp_rcontext.h" #include "sp_pcontext.h" -sp_rcontext::sp_rcontext(sp_rcontext *prev, uint fsize, uint hmax, uint cmax) - : m_count(0), m_fsize(fsize), m_result(NULL), m_hcount(0), m_hsp(0), - m_ihsp(0), m_hfound(-1), m_ccount(0), m_prev_ctx(prev) + +sp_rcontext::sp_rcontext(sp_pcontext *root_parsing_ctx, + Field *return_value_fld, + sp_rcontext *prev_runtime_ctx) + :m_root_parsing_ctx(root_parsing_ctx), + m_var_table(0), + m_var_items(0), + m_return_value_fld(return_value_fld), + m_return_value_set(FALSE), + m_hcount(0), + m_hsp(0), + m_ihsp(0), + m_hfound(-1), + m_ccount(0), + m_case_expr_holders(0), + m_prev_runtime_ctx(prev_runtime_ctx) { - m_frame= (Item **)sql_alloc(fsize * sizeof(Item*)); - m_handler= (sp_handler_t *)sql_alloc(hmax * sizeof(sp_handler_t)); - m_hstack= (uint *)sql_alloc(hmax * sizeof(uint)); - m_in_handler= (uint *)sql_alloc(hmax * sizeof(uint)); - m_cstack= (sp_cursor **)sql_alloc(cmax * sizeof(sp_cursor *)); - m_saved.empty(); } -int -sp_rcontext::set_item_eval(THD *thd, uint idx, Item **item_addr, - enum_field_types type) +sp_rcontext::~sp_rcontext() +{ + if (m_var_table) + free_blobs(m_var_table); +} + + +/* + Initialize sp_rcontext instance. + + SYNOPSIS + thd Thread handle + RETURN + FALSE on success + TRUE on error +*/ + +bool sp_rcontext::init(THD *thd) +{ + if (init_var_table(thd) || init_var_items()) + return TRUE; + + return + !(m_handler= + (sp_handler_t*)thd->alloc(m_root_parsing_ctx->max_handlers() * + sizeof(sp_handler_t))) || + !(m_hstack= + (uint*)thd->alloc(m_root_parsing_ctx->max_handlers() * + sizeof(uint))) || + !(m_in_handler= + (uint*)thd->alloc(m_root_parsing_ctx->max_handlers() * + sizeof(uint))) || + !(m_cstack= + (sp_cursor**)thd->alloc(m_root_parsing_ctx->max_cursors() * + sizeof(sp_cursor*))) || + !(m_case_expr_holders= + (Item_cache**)thd->calloc(m_root_parsing_ctx->get_num_case_exprs() * + sizeof (Item_cache*))); +} + + +/* + Create and initialize a table to store SP-vars. + + SYNOPSIS + thd Thread handler. + RETURN + FALSE on success + TRUE on error +*/ + +bool +sp_rcontext::init_var_table(THD *thd) { - Item *it; - Item *reuse_it; - /* sp_eval_func_item will use callers_arena */ - int res; - - reuse_it= get_item(idx); - it= sp_eval_func_item(thd, item_addr, type, reuse_it, TRUE); - if (! it) - res= -1; - else + List<create_field> field_def_lst; + + if (!m_root_parsing_ctx->total_pvars()) + return FALSE; + + m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst); + + DBUG_ASSERT(field_def_lst.elements == m_root_parsing_ctx->total_pvars()); + + if (!(m_var_table= create_virtual_tmp_table(thd, field_def_lst))) + return TRUE; + + m_var_table->copy_blobs= TRUE; + m_var_table->alias= ""; + + return FALSE; +} + + +/* + Create and initialize an Item-adapter (Item_field) for each SP-var field. + + RETURN + FALSE on success + TRUE on error +*/ + +bool +sp_rcontext::init_var_items() +{ + uint idx; + uint num_vars= m_root_parsing_ctx->total_pvars(); + + if (!(m_var_items= (Item**) sql_alloc(num_vars * sizeof (Item *)))) + return TRUE; + + for (idx = 0; idx < num_vars; ++idx) { - res= 0; - set_item(idx, it); + if (!(m_var_items[idx]= new Item_field(m_var_table->field[idx]))) + return TRUE; } - return res; + return FALSE; } + +bool +sp_rcontext::set_return_value(THD *thd, Item *return_value_item) +{ + DBUG_ASSERT(m_return_value_fld); + + m_return_value_set = TRUE; + + return sp_eval_expr(thd, m_return_value_fld, return_value_item); +} + + bool sp_rcontext::find_handler(uint sql_errno, MYSQL_ERROR::enum_warning_level level) @@ -117,32 +213,14 @@ sp_rcontext::find_handler(uint sql_errno, } if (found < 0) { - if (m_prev_ctx) - return m_prev_ctx->find_handler(sql_errno, level); + if (m_prev_runtime_ctx) + return m_prev_runtime_ctx->find_handler(sql_errno, level); return FALSE; } m_hfound= found; return TRUE; } -void -sp_rcontext::save_variables(uint fp) -{ - while (fp < m_count) - { - m_saved.push_front(m_frame[fp]); - m_frame[fp++]= NULL; // Prevent reuse - } -} - -void -sp_rcontext::restore_variables(uint fp) -{ - uint i= m_count; - - while (i-- > fp) - m_frame[i]= m_saved.pop(); -} void sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i) @@ -150,6 +228,7 @@ sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i) m_cstack[m_ccount++]= new sp_cursor(lex_keeper, i); } + void sp_rcontext::pop_cursors(uint count) { @@ -160,6 +239,40 @@ sp_rcontext::pop_cursors(uint count) } +int +sp_rcontext::set_variable(THD *thd, uint var_idx, Item *value) +{ + return set_variable(thd, m_var_table->field[var_idx], value); +} + + +int +sp_rcontext::set_variable(THD *thd, Field *field, Item *value) +{ + if (!value) + { + field->set_null(); + return 0; + } + + return sp_eval_expr(thd, field, value); +} + + +Item * +sp_rcontext::get_item(uint var_idx) +{ + return m_var_items[var_idx]; +} + + +Item ** +sp_rcontext::get_item_addr(uint var_idx) +{ + return m_var_items + var_idx; +} + + /* * * sp_cursor @@ -263,6 +376,102 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars) } +/* + Create an instance of appropriate Item_cache class depending on the + specified type in the callers arena. + + SYNOPSIS + thd thread handler + result_type type of the expression + + RETURN + Pointer to valid object on success + NULL on error + + NOTE + We should create cache items in the callers arena, as they are used + between in several instructions. +*/ + +Item_cache * +sp_rcontext::create_case_expr_holder(THD *thd, Item_result result_type) +{ + Item_cache *holder; + Query_arena current_arena; + + thd->set_n_backup_active_arena(thd->spcont->callers_arena, ¤t_arena); + + holder= Item_cache::get_cache(result_type); + + thd->restore_active_arena(thd->spcont->callers_arena, ¤t_arena); + + return holder; +} + + +/* + Set CASE expression to the specified value. + + SYNOPSIS + thd thread handler + case_expr_id identifier of the CASE expression + case_expr_item a value of the CASE expression + + RETURN + FALSE on success + TRUE on error + + NOTE + The idea is to reuse Item_cache for the expression of the one CASE + statement. This optimization takes place when there is CASE statement + inside of a loop. So, in other words, we will use the same object on each + iteration instead of creating a new one for each iteration. + + TODO + Hypothetically, a type of CASE expression can be different for each + iteration. For instance, this can happen if the expression contains a + session variable (something like @@VAR) and its type is changed from one + iteration to another. + + In order to cope with this problem, we check type each time, when we use + already created object. If the type does not match, we re-create Item. + This also can (should?) be optimized. +*/ + +int +sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item) +{ + if (!(case_expr_item= sp_prepare_func_item(thd, &case_expr_item))) + return TRUE; + + if (!m_case_expr_holders[case_expr_id] || + m_case_expr_holders[case_expr_id]->result_type() != + case_expr_item->result_type()) + { + m_case_expr_holders[case_expr_id]= + create_case_expr_holder(thd, case_expr_item->result_type()); + } + + m_case_expr_holders[case_expr_id]->store(case_expr_item); + + return FALSE; +} + + +Item * +sp_rcontext::get_case_expr(int case_expr_id) +{ + return m_case_expr_holders[case_expr_id]; +} + + +Item ** +sp_rcontext::get_case_expr_addr(int case_expr_id) +{ + return (Item**) m_case_expr_holders + case_expr_id; +} + + /*************************************************************************** Select_fetch_into_spvars ****************************************************************************/ @@ -294,11 +503,8 @@ bool Select_fetch_into_spvars::send_data(List<Item> &items) */ for (; pv= pv_iter++, item= item_iter++; ) { - Item *reuse= thd->spcont->get_item(pv->offset); - /* Evaluate a new item on the arena of the calling instruction */ - Item *it= sp_eval_func_item(thd, &item, pv->type, reuse, TRUE); - - thd->spcont->set_item(pv->offset, it); + if (thd->spcont->set_variable(thd, pv->offset, item)) + return TRUE; } return FALSE; } diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index cae5c5467c9..c3c05228eef 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -43,12 +43,22 @@ typedef struct /* - This is a run context? of one SP ? - THis is - - a stack of cursors? - - a stack of handlers? - - a stack of Items ? - - a stack of instruction locations in SP? + This class is a runtime context of a Stored Routine. It is used in an + execution and is intended to contain all dynamic objects (i.e. objects, which + can be changed during execution), such as: + - stored routine variables; + - cursors; + - handlers; + + Runtime context is used with sp_head class. sp_head class is intended to + contain all static things, related to the stored routines (code, for example). + sp_head instance creates runtime context for the execution of a stored + routine. + + There is a parsing context (an instance of sp_pcontext class), which is used + on parsing stage. However, now it contains some necessary for an execution + things, such as definition of used stored routine variables. That's why + runtime context needs a reference to the parsing context. */ class sp_rcontext : public Sql_alloc @@ -66,56 +76,36 @@ class sp_rcontext : public Sql_alloc */ Query_arena *callers_arena; - sp_rcontext(sp_rcontext *prev, uint fsize, uint hmax, uint cmax); - - ~sp_rcontext() - { - // Not needed? - //sql_element_free(m_frame); - //m_saved.empty(); - } +#ifndef DBUG_OFF + /* + The routine for which this runtime context is created. Used for checking + if correct runtime context is used for variable handling. + */ + sp_head *sp; +#endif - inline void - push_item(Item *i) - { - if (m_count < m_fsize) - m_frame[m_count++]= i; - } + sp_rcontext(sp_pcontext *root_parsing_ctx, Field *return_value_fld, + sp_rcontext *prev_runtime_ctx); + bool init(THD *thd); - inline void - set_item(uint idx, Item *i) - { - if (idx < m_count) - m_frame[idx]= i; - } + ~sp_rcontext(); - /* Returns 0 on success, -1 on (eval) failure */ int - set_item_eval(THD *thd, uint idx, Item **i, enum_field_types type); + set_variable(THD *thd, uint var_idx, Item *value); - inline Item * - get_item(uint idx) - { - return m_frame[idx]; - } - - inline Item ** - get_item_addr(uint idx) - { - return m_frame + idx; - } + Item * + get_item(uint var_idx); + Item ** + get_item_addr(uint var_idx); - inline void - set_result(Item *it) - { - m_result= it; - } + bool + set_return_value(THD *thd, Item *return_value_item); - inline Item * - get_result() + inline bool + is_return_value_set() const { - return m_result; + return m_return_value_set; } inline void @@ -187,14 +177,6 @@ class sp_rcontext : public Sql_alloc m_ihsp-= 1; } - // Save variables starting at fp and up - void - save_variables(uint fp); - - // Restore variables down to fp - void - restore_variables(uint fp); - void push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i); @@ -213,13 +195,42 @@ class sp_rcontext : public Sql_alloc return m_cstack[i]; } + /* + CASE expressions support. + */ + + int + set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item); + + Item * + get_case_expr(int case_expr_id); + + Item ** + get_case_expr_addr(int case_expr_id); + private: + sp_pcontext *m_root_parsing_ctx; + + /* Virtual table for storing variables. */ + TABLE *m_var_table; - uint m_count; - uint m_fsize; - Item **m_frame; + /* + Collection of Item_field proxies, each of them points to the corresponding + field in m_var_table. + */ + Item **m_var_items; - Item *m_result; // For FUNCTIONs + /* + This is a pointer to a field, which should contain return value for stored + functions (only). For stored procedures, this pointer is NULL. + */ + Field *m_return_value_fld; + + /* + Indicates whether the return value (in m_return_value_fld) has been set + during execution. + */ + bool m_return_value_set; sp_handler_t *m_handler; // Visible handlers uint m_hcount; // Stack pointer for m_handler @@ -228,13 +239,22 @@ private: uint *m_in_handler; // Active handler, for recursion check uint m_ihsp; // Stack pointer for m_in_handler int m_hfound; // Set by find_handler; -1 if not found - List<Item> m_saved; // Saved variables during handler exec. sp_cursor **m_cstack; uint m_ccount; - sp_rcontext *m_prev_ctx; // Previous context (NULL if none) + Item_cache **m_case_expr_holders; + + /* Previous runtime context (NULL if none) */ + sp_rcontext *m_prev_runtime_ctx; + +private: + bool init_var_table(THD *thd); + bool init_var_items(); + + Item_cache *create_case_expr_holder(THD *thd, Item_result result_type); + int set_variable(THD *thd, Field *field, Item *value); }; // class sp_rcontext : public Sql_alloc diff --git a/sql/spatial.cc b/sql/spatial.cc index 176f1f2fbfe..e91653f79d5 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -121,24 +121,21 @@ Geometry::Class_info *Geometry::find_class(const char *name, uint32 len) return 0; } -Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer, - const char *data, uint32 data_len) + +Geometry *Geometry::construct(Geometry_buffer *buffer, + const char *data, uint32 data_len) { uint32 geom_type; Geometry *result; + char byte_order; - if (data_len < 1 + 4) + if (data_len < SRID_SIZE + WKB_HEADER_SIZE) // < 4 + (1 + 4) return NULL; - data++; - /* - FIXME: check byte ordering - Also check if we could replace this with one byte - */ - geom_type= uint4korr(data); - data+= 4; + byte_order= data[SRID_SIZE]; + geom_type= uint4korr(data + SRID_SIZE + 1); if (!(result= create_by_typeid(buffer, (int) geom_type))) return NULL; - result->m_data= data; + result->m_data= data+ SRID_SIZE + WKB_HEADER_SIZE; result->m_data_end= data + data_len; return result; } @@ -170,13 +167,73 @@ Geometry *Geometry::create_from_wkt(Geometry_buffer *buffer, return NULL; if (init_stream) { - result->init_from_wkb(wkt->ptr(), wkt->length()); + result->set_data_ptr(wkt->ptr(), wkt->length()); result->shift_wkb_header(); } return result; } +static double wkb_get_double(const char *ptr, Geometry::wkbByteOrder bo) +{ + double res; + if (bo != Geometry::wkb_xdr) + { + float8get(res, ptr); + } + else + { + char inv_array[8]; + inv_array[0]= ptr[7]; + inv_array[1]= ptr[6]; + inv_array[2]= ptr[5]; + inv_array[3]= ptr[4]; + inv_array[4]= ptr[3]; + inv_array[5]= ptr[2]; + inv_array[6]= ptr[1]; + inv_array[7]= ptr[0]; + float8get(res, inv_array); + } + return res; +} + + +static uint32 wkb_get_uint(const char *ptr, Geometry::wkbByteOrder bo) +{ + if (bo != Geometry::wkb_xdr) + return uint4korr(ptr); + /* else */ + { + char inv_array[4]; + inv_array[0]= ptr[3]; + inv_array[1]= ptr[2]; + inv_array[2]= ptr[1]; + inv_array[3]= ptr[0]; + return uint4korr(inv_array); + } +} + + +int Geometry::create_from_wkb(Geometry_buffer *buffer, + const char *wkb, uint32 len, String *res) +{ + uint32 geom_type; + Geometry *geom; + + if (len < WKB_HEADER_SIZE) + return 1; + geom_type= wkb_get_uint(wkb+1, (wkbByteOrder)wkb[0]); + if (!(geom= create_by_typeid(buffer, (int) geom_type)) || + res->reserve(WKB_HEADER_SIZE, 512)) + return 1; + + res->q_append((char) wkb_ndr); + res->q_append(geom_type); + return geom->init_from_wkb(wkb+WKB_HEADER_SIZE, len - WKB_HEADER_SIZE, + (wkbByteOrder) wkb[0], res); +} + + bool Geometry::envelope(String *result) const { MBR mbr; @@ -346,6 +403,20 @@ bool Gis_point::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_point::init_from_wkb(const char *wkb, uint len, + wkbByteOrder bo, String *res) +{ + double x, y; + if (len < POINT_DATA_SIZE || res->reserve(POINT_DATA_SIZE)) + return 0; + x= wkb_get_double(wkb, bo); + y= wkb_get_double(wkb + SIZEOF_STORED_DOUBLE, bo); + res->q_append(x); + res->q_append(y); + return POINT_DATA_SIZE; +} + + bool Gis_point::get_data_as_wkt(String *txt, const char **end) const { double x, y; @@ -415,6 +486,33 @@ bool Gis_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_line_string::init_from_wkb(const char *wkb, uint len, + wkbByteOrder bo, String *res) +{ + uint32 n_points, proper_length; + const char *wkb_end; + Gis_point p; + + if (len < 4) + return 0; + n_points= wkb_get_uint(wkb, bo); + proper_length= 4 + n_points * POINT_DATA_SIZE; + + if (len < proper_length || res->reserve(proper_length)) + return 0; + + res->q_append(n_points); + wkb_end= wkb + proper_length; + for (wkb+= 4; wkb<wkb_end; wkb+= POINT_DATA_SIZE) + { + if (!p.init_from_wkb(wkb, POINT_DATA_SIZE, bo, res)) + return 0; + } + + return proper_length; +} + + bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const { uint32 n_points; @@ -594,7 +692,7 @@ bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) trs->check_next_symbol(')')) return 1; - ls.init_from_wkb(wkb->ptr()+ls_pos, wkb->length()-ls_pos); + ls.set_data_ptr(wkb->ptr() + ls_pos, wkb->length() - ls_pos); if (ls.is_closed(&closed) || !closed) { trs->set_error_msg("POLYGON's linear ring isn't closed"); @@ -609,6 +707,43 @@ bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_polygon::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, + String *res) +{ + uint32 n_linear_rings; + const char *wkb_orig= wkb; + + if (len < 4) + return 0; + + n_linear_rings= wkb_get_uint(wkb, bo); + if (res->reserve(4, 512)) + return 0; + wkb+= 4; + len-= 4; + res->q_append(n_linear_rings); + + while (n_linear_rings--) + { + Gis_line_string ls; + uint32 ls_pos= res->length(); + int ls_len; + int closed; + + if (!(ls_len= ls.init_from_wkb(wkb, len, bo, res))) + return 0; + + ls.set_data_ptr(res->ptr() + ls_pos, res->length() - ls_pos); + + if (ls.is_closed(&closed) || !closed) + return 0; + wkb+= ls_len; + } + + return (uint) (wkb - wkb_orig); +} + + bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const { uint32 n_linear_rings; @@ -897,6 +1032,36 @@ bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, + String *res) +{ + uint32 n_points; + uint proper_size; + Gis_point p; + const char *wkb_end; + + if (len < 4) + return 0; + n_points= wkb_get_uint(wkb, bo); + proper_size= 4 + n_points * (WKB_HEADER_SIZE + POINT_DATA_SIZE); + + if (len < proper_size || res->reserve(proper_size)) + return 0; + + res->q_append(n_points); + wkb_end= wkb + proper_size; + for (wkb+=4; wkb < wkb_end; wkb+= (WKB_HEADER_SIZE + POINT_DATA_SIZE)) + { + res->q_append((char)wkb_ndr); + res->q_append((uint32)wkb_point); + if (!p.init_from_wkb(wkb + WKB_HEADER_SIZE, + POINT_DATA_SIZE, (wkbByteOrder) wkb[0], res)) + return 0; + } + return proper_size; +} + + bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const { uint32 n_points; @@ -1006,6 +1171,44 @@ bool Gis_multi_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_multi_line_string::init_from_wkb(const char *wkb, uint len, + wkbByteOrder bo, String *res) +{ + uint32 n_line_strings; + const char *wkb_orig= wkb; + + if (len < 4) + return 0; + n_line_strings= wkb_get_uint(wkb, bo); + + if (res->reserve(4, 512)) + return 0; + res->q_append(n_line_strings); + + wkb+= 4; + while (n_line_strings--) + { + Gis_line_string ls; + int ls_len; + + if ((len < WKB_HEADER_SIZE) || + res->reserve(WKB_HEADER_SIZE, 512)) + return 0; + + res->q_append((char) wkb_ndr); + res->q_append((uint32) wkb_linestring); + + if (!(ls_len= ls.init_from_wkb(wkb + WKB_HEADER_SIZE, len, + (wkbByteOrder) wkb[0], res))) + return 0; + ls_len+= WKB_HEADER_SIZE;; + wkb+= ls_len; + len-= ls_len; + } + return (uint) (wkb - wkb_orig); +} + + bool Gis_multi_line_string::get_data_as_wkt(String *txt, const char **end) const { @@ -1111,7 +1314,7 @@ int Gis_multi_line_string::length(double *len) const double ls_len; Gis_line_string ls; data+= WKB_HEADER_SIZE; - ls.init_from_wkb(data, (uint32) (m_data_end - data)); + ls.set_data_ptr(data, (uint32) (m_data_end - data)); if (ls.length(&ls_len)) return 1; *len+= ls_len; @@ -1140,7 +1343,7 @@ int Gis_multi_line_string::is_closed(int *closed) const Gis_line_string ls; if (no_data(data, 0)) return 1; - ls.init_from_wkb(data, (uint32) (m_data_end - data)); + ls.set_data_ptr(data, (uint32) (m_data_end - data)); if (ls.is_closed(closed)) return 1; if (!*closed) @@ -1222,6 +1425,43 @@ bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_multi_polygon::init_from_wkb(const char *wkb, uint len, + wkbByteOrder bo, String *res) +{ + uint32 n_poly; + const char *wkb_orig= wkb; + + if (len < 4) + return 0; + n_poly= wkb_get_uint(wkb, bo); + + if (res->reserve(4, 512)) + return 0; + res->q_append(n_poly); + + wkb+=4; + while (n_poly--) + { + Gis_polygon p; + int p_len; + + if (len < WKB_HEADER_SIZE || + res->reserve(WKB_HEADER_SIZE, 512)) + return 0; + res->q_append((char) wkb_ndr); + res->q_append((uint32) wkb_polygon); + + if (!(p_len= p.init_from_wkb(wkb + WKB_HEADER_SIZE, len, + (wkbByteOrder) wkb[0], res))) + return 0; + p_len+= WKB_HEADER_SIZE; + wkb+= p_len; + len-= p_len; + } + return (uint) (wkb - wkb_orig); +} + + bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const { uint32 n_polygons; @@ -1358,7 +1598,7 @@ int Gis_multi_polygon::area(double *ar, const char **end_of_data) const Gis_polygon p; data+= WKB_HEADER_SIZE; - p.init_from_wkb(data, (uint32) (m_data_end - data)); + p.set_data_ptr(data, (uint32) (m_data_end - data)); if (p.area(&p_area, &data)) return 1; result+= p_area; @@ -1390,7 +1630,7 @@ int Gis_multi_polygon::centroid(String *result) const while (n_polygons--) { data+= WKB_HEADER_SIZE; - p.init_from_wkb(data, (uint32) (m_data_end - data)); + p.set_data_ptr(data, (uint32) (m_data_end - data)); if (p.area(&cur_area, &data) || p.centroid_xy(&cur_cx, &cur_cy)) return 1; @@ -1444,7 +1684,7 @@ uint32 Gis_geometry_collection::get_data_size() const if (!(geom= create_by_typeid(&buffer, wkb_type))) return GET_SIZE_ERROR; - geom->init_from_wkb(data, (uint) (m_data_end - data)); + geom->set_data_ptr(data, (uint) (m_data_end - data)); if ((object_size= geom->get_data_size()) == GET_SIZE_ERROR) return GET_SIZE_ERROR; data+= object_size; @@ -1484,6 +1724,48 @@ bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb) } +uint Gis_geometry_collection::init_from_wkb(const char *wkb, uint len, + wkbByteOrder bo, String *res) +{ + uint32 n_geom; + const char *wkb_orig= wkb; + + if (len < 4) + return 0; + n_geom= wkb_get_uint(wkb, bo); + + if (res->reserve(4, 512)) + return 0; + res->q_append(n_geom); + + wkb+= 4; + while (n_geom--) + { + Geometry_buffer buffer; + Geometry *geom; + int g_len; + uint32 wkb_type; + + if (len < WKB_HEADER_SIZE || + res->reserve(WKB_HEADER_SIZE, 512)) + return 0; + + res->q_append((char) wkb_ndr); + wkb_type= wkb_get_uint(wkb+1, (wkbByteOrder) wkb[0]); + res->q_append(wkb_type); + + if (!(geom= create_by_typeid(&buffer, wkb_type)) || + !(g_len= geom->init_from_wkb(wkb + WKB_HEADER_SIZE, len, + (wkbByteOrder) wkb[0], res))) + return 0; + g_len+= WKB_HEADER_SIZE; + wkb+= g_len; + len-= g_len; + } + return (uint) (wkb - wkb_orig); +} + + bool Gis_geometry_collection::get_data_as_wkt(String *txt, const char **end) const { @@ -1508,10 +1790,10 @@ bool Gis_geometry_collection::get_data_as_wkt(String *txt, if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom->init_from_wkb(data, (uint) (m_data_end - data)); + geom->set_data_ptr(data, (uint) (m_data_end - data)); if (geom->as_wkt(txt, &data)) return 1; - if (txt->append(",", 1, 512)) + if (txt->append(STRING_WITH_LEN(","), 512)) return 1; } txt->length(txt->length() - 1); @@ -1543,7 +1825,7 @@ bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom->init_from_wkb(data, (uint32) (m_data_end - data)); + geom->set_data_ptr(data, (uint32) (m_data_end - data)); if (geom->get_mbr(mbr, &data)) return 1; } @@ -1584,7 +1866,7 @@ int Gis_geometry_collection::geometry_n(uint32 num, String *result) const if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom->init_from_wkb(data, (uint) (m_data_end - data)); + geom->set_data_ptr(data, (uint) (m_data_end - data)); if ((length= geom->get_data_size()) == GET_SIZE_ERROR) return 1; data+= length; @@ -1637,7 +1919,7 @@ bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const data+= WKB_HEADER_SIZE; if (!(geom= create_by_typeid(&buffer, wkb_type))) return 1; - geom->init_from_wkb(data, (uint32) (m_data_end - data)); + geom->set_data_ptr(data, (uint32) (m_data_end - data)); if (geom->dimension(&dim, &end_data)) return 1; set_if_bigger(*res_dim, dim); diff --git a/sql/spatial.h b/sql/spatial.h index b5ea7d641d1..4253689c078 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -207,6 +207,10 @@ public: virtual const Class_info *get_class_info() const=0; virtual uint32 get_data_size() const=0; virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb)=0; + + /* returns the length of the wkb that was read */ + virtual uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, + String *res)=0; virtual bool get_data_as_wkt(String *txt, const char **end) const=0; virtual bool get_mbr(MBR *mbr, const char **end) const=0; virtual bool dimension(uint32 *dim, const char **end) const=0; @@ -236,11 +240,13 @@ public: return my_reinterpret_cast(Geometry *)(buffer); } - static Geometry *create_from_wkb(Geometry_buffer *buffer, - const char *data, uint32 data_len); + static Geometry *construct(Geometry_buffer *buffer, + const char *data, uint32 data_len); static Geometry *create_from_wkt(Geometry_buffer *buffer, Gis_read_stream *trs, String *wkt, bool init_stream=1); + static int create_from_wkb(Geometry_buffer *buffer, + const char *wkb, uint32 len, String *res); int as_wkt(String *wkt, const char **end) { uint32 len= get_class_info()->m_name.length; @@ -254,7 +260,7 @@ public: return 0; } - inline void init_from_wkb(const char *data, uint32 data_len) + inline void set_data_ptr(const char *data, uint32 data_len) { m_data= data; m_data_end= data + data_len; @@ -298,6 +304,7 @@ class Gis_point: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); bool get_data_as_wkt(String *txt, const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; @@ -344,6 +351,7 @@ class Gis_line_string: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); bool get_data_as_wkt(String *txt, const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int length(double *len) const; @@ -369,6 +377,7 @@ class Gis_polygon: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); bool get_data_as_wkt(String *txt, const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int area(double *ar, const char **end) const; @@ -394,6 +403,7 @@ class Gis_multi_point: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); bool get_data_as_wkt(String *txt, const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int num_geometries(uint32 *num) const; @@ -415,6 +425,7 @@ class Gis_multi_line_string: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); bool get_data_as_wkt(String *txt, const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int num_geometries(uint32 *num) const; @@ -438,6 +449,7 @@ class Gis_multi_polygon: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); bool get_data_as_wkt(String *txt, const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int num_geometries(uint32 *num) const; @@ -461,6 +473,7 @@ class Gis_geometry_collection: public Geometry public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); + uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); bool get_data_as_wkt(String *txt, const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int num_geometries(uint32 *num) const; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 0691708f19b..061020e1952 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -68,6 +68,7 @@ static ulong get_access(TABLE *form,uint fieldnr, uint *next_field=0); static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b); static ulong get_sort(uint count,...); static void init_check_host(void); +static void rebuild_check_host(void); static ACL_USER *find_acl_user(const char *host, const char *user, my_bool exact); static bool update_user_table(THD *thd, TABLE *table, @@ -158,6 +159,7 @@ my_bool acl_init(bool dont_read_acl_tables) */ if (!(thd=new THD)) DBUG_RETURN(1); /* purecov: inspected */ + thd->thread_stack= (char*) &thd; thd->store_globals(); /* It is safe to call acl_reload() since acl_* arrays and hashes which @@ -934,6 +936,9 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host, ACL_USER *acl_user= 0; DBUG_ENTER("acl_getroot_no_password"); + DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', db: '%s'", + (host ? host : "(NULL)"), (ip ? ip : "(NULL)"), + (user ? user : "(NULL)"), (db ? db : "(NULL)"))); sctx->user= user; sctx->host= host; sctx->ip= ip; @@ -1091,10 +1096,8 @@ static void acl_insert_user(const char *user, const char *host, qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, sizeof(ACL_USER),(qsort_cmp) acl_compare); - /* We must free acl_check_hosts as its memory is mapped to acl_user */ - delete_dynamic(&acl_wild_hosts); - hash_free(&acl_check_hosts); - init_check_host(); + /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ + rebuild_check_host(); } @@ -1279,7 +1282,7 @@ static void init_check_host(void) if (j == acl_wild_hosts.elements) // If new (void) push_dynamic(&acl_wild_hosts,(char*) &acl_user->host); } - else if (!hash_search(&acl_check_hosts,(byte*) &acl_user->host, + else if (!hash_search(&acl_check_hosts,(byte*) acl_user->host.hostname, (uint) strlen(acl_user->host.hostname))) { if (my_hash_insert(&acl_check_hosts,(byte*) acl_user)) @@ -1296,6 +1299,22 @@ static void init_check_host(void) } +/* + Rebuild lists used for checking of allowed hosts + + We need to rebuild 'acl_check_hosts' and 'acl_wild_hosts' after adding, + dropping or renaming user, since they contain pointers to elements of + 'acl_user' array, which are invalidated by drop operation, and use + ACL_USER::host::hostname as a key, which is changed by rename. +*/ +void rebuild_check_host(void) +{ + delete_dynamic(&acl_wild_hosts); + hash_free(&acl_check_hosts); + init_check_host(); +} + + /* Return true if there is no users that can match the given host */ bool acl_check_host(const char *host, const char *ip) @@ -1808,19 +1827,22 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, /* We write down SSL related ACL stuff */ switch (lex->ssl_type) { case SSL_TYPE_ANY: - table->field[next_field]->store("ANY", 3, &my_charset_latin1); + table->field[next_field]->store(STRING_WITH_LEN("ANY"), + &my_charset_latin1); table->field[next_field+1]->store("", 0, &my_charset_latin1); table->field[next_field+2]->store("", 0, &my_charset_latin1); table->field[next_field+3]->store("", 0, &my_charset_latin1); break; case SSL_TYPE_X509: - table->field[next_field]->store("X509", 4, &my_charset_latin1); + table->field[next_field]->store(STRING_WITH_LEN("X509"), + &my_charset_latin1); table->field[next_field+1]->store("", 0, &my_charset_latin1); table->field[next_field+2]->store("", 0, &my_charset_latin1); table->field[next_field+3]->store("", 0, &my_charset_latin1); break; case SSL_TYPE_SPECIFIED: - table->field[next_field]->store("SPECIFIED", 9, &my_charset_latin1); + table->field[next_field]->store(STRING_WITH_LEN("SPECIFIED"), + &my_charset_latin1); table->field[next_field+1]->store("", 0, &my_charset_latin1); table->field[next_field+2]->store("", 0, &my_charset_latin1); table->field[next_field+3]->store("", 0, &my_charset_latin1); @@ -2222,14 +2244,14 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, char helping [NAME_LEN*2+USERNAME_LENGTH+3]; uint len; GRANT_NAME *grant_name,*found=0; + HASH_SEARCH_STATE state; len = (uint) (strmov(strmov(strmov(helping,user)+1,db)+1,tname)-helping)+ 1; - for (grant_name=(GRANT_NAME*) hash_search(name_hash, - (byte*) helping, - len) ; + for (grant_name= (GRANT_NAME*) hash_first(name_hash, (byte*) helping, + len, &state); grant_name ; grant_name= (GRANT_NAME*) hash_next(name_hash,(byte*) helping, - len)) + len, &state)) { if (exact) { @@ -2754,8 +2776,9 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, uint unused_field_idx= NO_CACHED_FIELD_INDEX; TABLE_LIST *dummy; Field *f=find_field_in_table_ref(thd, table_list, column->column.ptr(), + column->column.length(), column->column.ptr(), NULL, NULL, - column->column.length(), 0, 1, 1, 0, + NULL, TRUE, FALSE, &unused_field_idx, FALSE, &dummy); if (f == (Field*)0) { @@ -3257,6 +3280,7 @@ my_bool grant_init() if (!(thd= new THD)) DBUG_RETURN(1); /* purecov: deadcode */ + thd->thread_stack= (char*) &thd; thd->store_globals(); return_val= grant_reload(thd); delete thd; @@ -3512,17 +3536,38 @@ end: bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, uint show_table, uint number, bool no_errors) { - TABLE_LIST *table; + TABLE_LIST *table, *first_not_own_table= thd->lex->first_not_own_table(); Security_context *sctx= thd->security_ctx; + uint i; DBUG_ENTER("check_grant"); DBUG_ASSERT(number > 0); + /* + Walk through the list of tables that belong to the query and save the + requested access (orig_want_privilege) to be able to use it when + checking access rights to the underlying tables of a view. Our grant + system gradually eliminates checked bits from want_privilege and thus + after all checks are done we can no longer use it. + The check that first_not_own_table is not reached is for the case when + the given table list refers to the list for prelocking (contains tables + of other queries). For simple queries first_not_own_table is 0. + */ + for (i= 0, table= tables; + table != first_not_own_table && i < number; + table= table->next_global, i++) + { + /* Remove SHOW_VIEW_ACL, because it will be checked during making view */ + table->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); + } + want_access&= ~sctx->master_access; if (!want_access) DBUG_RETURN(0); // ok rw_rdlock(&LOCK_grant); - for (table= tables; table && number--; table= table->next_global) + for (table= tables; + table && number-- && table != first_not_own_table; + table= table->next_global) { GRANT_TABLE *grant_table; if (!(~table->grant.privilege & want_access) || @@ -3532,8 +3577,16 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, It is subquery in the FROM clause. VIEW set table->derived after table opening, but this function always called before table opening. */ - table->grant.want_privilege= 0; - continue; // Already checked + if (!table->referencing_view) + { + /* + If it's a temporary table created for a subquery in the FROM + clause, or an INFORMATION_SCHEMA table, drop the request for + a privilege. + */ + table->grant.want_privilege= 0; + } + continue; } if (!(grant_table= table_hash_search(sctx->host, sctx->ip, table->db, sctx->priv_user, @@ -3579,11 +3632,28 @@ err: } +/* + Check column rights in given security context + + SYNOPSIS + check_grant_column() + thd thread handler + grant grant information structure + db_name db name + table_name table name + name column name + length column name length + sctx security context + + RETURN + FALSE OK + TRUE access denied +*/ + bool check_grant_column(THD *thd, GRANT_INFO *grant, const char *db_name, const char *table_name, - const char *name, uint length, uint show_tables) + const char *name, uint length, Security_context *sctx) { - Security_context *sctx= thd->security_ctx; GRANT_TABLE *grant_table; GRANT_COLUMN *grant_column; ulong want_access= grant->want_privilege & ~grant->privilege; @@ -3614,28 +3684,74 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant, rw_unlock(&LOCK_grant); DBUG_RETURN(0); } -#ifdef NOT_USED - if (show_tables && (grant_column || grant->privilege & COL_ACLS)) - { - rw_unlock(&LOCK_grant); /* purecov: deadcode */ - DBUG_RETURN(0); /* purecov: deadcode */ - } -#endif err: rw_unlock(&LOCK_grant); - if (!show_tables) + char command[128]; + get_privilege_desc(command, sizeof(command), want_access); + my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), + command, + sctx->priv_user, + sctx->host_or_ip, + name, + table_name); + DBUG_RETURN(1); +} + + +/* + Check the access right to a column depending on the type of table. + + SYNOPSIS + check_column_grant_in_table_ref() + thd thread handler + table_ref table reference where to check the field + name name of field to check + length length of name + + DESCRIPTION + Check the access rights to a column depending on the type of table + reference where the column is checked. The function provides a + generic interface to check column access rights that hides the + heterogeneity of the column representation - whether it is a view + or a stored table colum. + + RETURN + FALSE OK + TRUE access denied +*/ + +bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref, + const char *name, uint length) +{ + GRANT_INFO *grant; + const char *db_name; + const char *table_name; + Security_context *sctx= test(table_ref->security_ctx) ? + table_ref->security_ctx : thd->security_ctx; + + if (table_ref->view || table_ref->field_translation) { - char command[128]; - get_privilege_desc(command, sizeof(command), want_access); - my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), - command, - sctx->priv_user, - sctx->host_or_ip, - name, - table_name); + /* View or derived information schema table. */ + grant= &(table_ref->grant); + db_name= table_ref->view_db.str; + table_name= table_ref->view_name.str; } - DBUG_RETURN(1); + else + { + /* Normal or temporary table. */ + TABLE *table= table_ref->table; + grant= &(table->grant); + db_name= table->s->db; + table_name= table->s->table_name; + } + + if (grant->want_privilege) + return check_grant_column(thd, grant, db_name, table_name, name, + length, sctx); + else + return FALSE; + } @@ -4024,13 +4140,13 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) { String global(buff,sizeof(buff),system_charset_info); global.length(0); - global.append("GRANT ",6); + global.append(STRING_WITH_LEN("GRANT ")); want_access= acl_user->access; if (test_all_bits(want_access, (GLOBAL_ACLS & ~ GRANT_ACL))) - global.append("ALL PRIVILEGES",14); + global.append(STRING_WITH_LEN("ALL PRIVILEGES")); else if (!(want_access & ~GRANT_ACL)) - global.append("USAGE",5); + global.append(STRING_WITH_LEN("USAGE")); else { bool found=0; @@ -4040,16 +4156,16 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (test_access & j) { if (found) - global.append(", ",2); + global.append(STRING_WITH_LEN(", ")); found=1; global.append(command_array[counter],command_lengths[counter]); } } } - global.append (" ON *.* TO '",12); + global.append (STRING_WITH_LEN(" ON *.* TO '")); global.append(lex_user->user.str, lex_user->user.length, system_charset_info); - global.append ("'@'",3); + global.append (STRING_WITH_LEN("'@'")); global.append(lex_user->host.str,lex_user->host.length, system_charset_info); global.append ('\''); @@ -4060,23 +4176,23 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) make_password_from_salt(passwd_buff, acl_user->salt); else make_password_from_salt_323(passwd_buff, (ulong *) acl_user->salt); - global.append(" IDENTIFIED BY PASSWORD '",25); + global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '")); global.append(passwd_buff); global.append('\''); } /* "show grants" SSL related stuff */ if (acl_user->ssl_type == SSL_TYPE_ANY) - global.append(" REQUIRE SSL",12); + global.append(STRING_WITH_LEN(" REQUIRE SSL")); else if (acl_user->ssl_type == SSL_TYPE_X509) - global.append(" REQUIRE X509",13); + global.append(STRING_WITH_LEN(" REQUIRE X509")); else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED) { int ssl_options = 0; - global.append(" REQUIRE ",9); + global.append(STRING_WITH_LEN(" REQUIRE ")); if (acl_user->x509_issuer) { ssl_options++; - global.append("ISSUER \'",8); + global.append(STRING_WITH_LEN("ISSUER \'")); global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); global.append('\''); } @@ -4084,7 +4200,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) { if (ssl_options++) global.append(' '); - global.append("SUBJECT \'",9); + global.append(STRING_WITH_LEN("SUBJECT \'")); global.append(acl_user->x509_subject,strlen(acl_user->x509_subject), system_charset_info); global.append('\''); @@ -4093,7 +4209,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) { if (ssl_options++) global.append(' '); - global.append("CIPHER '",8); + global.append(STRING_WITH_LEN("CIPHER '")); global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher), system_charset_info); global.append('\''); @@ -4105,9 +4221,9 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) acl_user->user_resource.conn_per_hour || acl_user->user_resource.user_conn)) { - global.append(" WITH",5); + global.append(STRING_WITH_LEN(" WITH")); if (want_access & GRANT_ACL) - global.append(" GRANT OPTION",13); + global.append(STRING_WITH_LEN(" GRANT OPTION")); add_user_option(&global, acl_user->user_resource.questions, "MAX_QUERIES_PER_HOUR"); add_user_option(&global, acl_user->user_resource.updates, @@ -4145,12 +4261,12 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) { String db(buff,sizeof(buff),system_charset_info); db.length(0); - db.append("GRANT ",6); + db.append(STRING_WITH_LEN("GRANT ")); if (test_all_bits(want_access,(DB_ACLS & ~GRANT_ACL))) - db.append("ALL PRIVILEGES",14); + db.append(STRING_WITH_LEN("ALL PRIVILEGES")); else if (!(want_access & ~GRANT_ACL)) - db.append("USAGE",5); + db.append(STRING_WITH_LEN("USAGE")); else { int found=0, cnt; @@ -4160,23 +4276,23 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (test_access & j) { if (found) - db.append(", ",2); + db.append(STRING_WITH_LEN(", ")); found = 1; db.append(command_array[cnt],command_lengths[cnt]); } } } - db.append (" ON ",4); + db.append (STRING_WITH_LEN(" ON ")); append_identifier(thd, &db, acl_db->db, strlen(acl_db->db)); - db.append (".* TO '",7); + db.append (STRING_WITH_LEN(".* TO '")); db.append(lex_user->user.str, lex_user->user.length, system_charset_info); - db.append ("'@'",3); + db.append (STRING_WITH_LEN("'@'")); db.append(lex_user->host.str, lex_user->host.length, system_charset_info); db.append ('\''); if (want_access & GRANT_ACL) - db.append(" WITH GRANT OPTION",18); + db.append(STRING_WITH_LEN(" WITH GRANT OPTION")); protocol->prepare_for_resend(); protocol->store(db.ptr(),db.length(),db.charset()); if (protocol->write()) @@ -4209,12 +4325,12 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) ulong test_access= (table_access | grant_table->cols) & ~GRANT_ACL; global.length(0); - global.append("GRANT ",6); + global.append(STRING_WITH_LEN("GRANT ")); if (test_all_bits(table_access, (TABLE_ACLS & ~GRANT_ACL))) - global.append("ALL PRIVILEGES",14); + global.append(STRING_WITH_LEN("ALL PRIVILEGES")); else if (!test_access) - global.append("USAGE",5); + global.append(STRING_WITH_LEN("USAGE")); else { /* Add specific column access */ @@ -4226,7 +4342,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (test_access & j) { if (found) - global.append(", ",2); + global.append(STRING_WITH_LEN(", ")); found= 1; global.append(command_array[counter],command_lengths[counter]); @@ -4250,14 +4366,14 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) */ if (table_access & j) { - global.append(", ", 2); + global.append(STRING_WITH_LEN(", ")); global.append(command_array[counter], command_lengths[counter]); } - global.append(" (",2); + global.append(STRING_WITH_LEN(" (")); } else - global.append(", ",2); + global.append(STRING_WITH_LEN(", ")); global.append(grant_column->column, grant_column->key_length, system_charset_info); @@ -4269,21 +4385,21 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) } } } - global.append(" ON ",4); + global.append(STRING_WITH_LEN(" ON ")); append_identifier(thd, &global, grant_table->db, strlen(grant_table->db)); global.append('.'); append_identifier(thd, &global, grant_table->tname, strlen(grant_table->tname)); - global.append(" TO '",5); + global.append(STRING_WITH_LEN(" TO '")); global.append(lex_user->user.str, lex_user->user.length, system_charset_info); - global.append("'@'",3); + global.append(STRING_WITH_LEN("'@'")); global.append(lex_user->host.str,lex_user->host.length, system_charset_info); global.append('\''); if (table_access & GRANT_ACL) - global.append(" WITH GRANT OPTION",18); + global.append(STRING_WITH_LEN(" WITH GRANT OPTION")); protocol->prepare_for_resend(); protocol->store(global.ptr(),global.length(),global.charset()); if (protocol->write()) @@ -4296,14 +4412,14 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) } if (show_routine_grants(thd, lex_user, &proc_priv_hash, - "PROCEDURE", 9, buff, sizeof(buff))) + STRING_WITH_LEN("PROCEDURE"), buff, sizeof(buff))) { error= -1; goto end; } if (show_routine_grants(thd, lex_user, &func_priv_hash, - "FUNCTION", 8, buff, sizeof(buff))) + STRING_WITH_LEN("FUNCTION"), buff, sizeof(buff))) { error= -1; goto end; @@ -4344,10 +4460,10 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash, ulong test_access= proc_access & ~GRANT_ACL; global.length(0); - global.append("GRANT ",6); + global.append(STRING_WITH_LEN("GRANT ")); if (!test_access) - global.append("USAGE",5); + global.append(STRING_WITH_LEN("USAGE")); else { /* Add specific procedure access */ @@ -4359,13 +4475,13 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash, if (test_access & j) { if (found) - global.append(", ",2); + global.append(STRING_WITH_LEN(", ")); found= 1; global.append(command_array[counter],command_lengths[counter]); } } } - global.append(" ON ",4); + global.append(STRING_WITH_LEN(" ON ")); global.append(type,typelen); global.append(' '); append_identifier(thd, &global, grant_proc->db, @@ -4373,15 +4489,15 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash, global.append('.'); append_identifier(thd, &global, grant_proc->tname, strlen(grant_proc->tname)); - global.append(" TO '",5); + global.append(STRING_WITH_LEN(" TO '")); global.append(lex_user->user.str, lex_user->user.length, system_charset_info); - global.append("'@'",3); + global.append(STRING_WITH_LEN("'@'")); global.append(lex_user->host.str,lex_user->host.length, system_charset_info); global.append('\''); if (proc_access & GRANT_ACL) - global.append(" WITH GRANT OPTION",18); + global.append(STRING_WITH_LEN(" WITH GRANT OPTION")); protocol->prepare_for_resend(); protocol->store(global.ptr(),global.length(),global.charset()); if (protocol->write()) @@ -5036,7 +5152,7 @@ static void append_user(String *str, LEX_USER *user) str->append(','); str->append('\''); str->append(user->user.str); - str->append("'@'"); + str->append(STRING_WITH_LEN("'@'")); str->append(user->host.str); str->append('\''); } @@ -5140,6 +5256,9 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) } } + /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ + rebuild_check_host(); + VOID(pthread_mutex_unlock(&acl_cache->lock)); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -5164,7 +5283,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) bool mysql_rename_user(THD *thd, List <LEX_USER> &list) { - int result= 0; + int result; String wrong_users; LEX_USER *user_from; LEX_USER *user_to; @@ -5196,6 +5315,9 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) } } + /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ + rebuild_check_host(); + VOID(pthread_mutex_unlock(&acl_cache->lock)); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -5618,7 +5740,8 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) strxmov(buff,"'",user,"'@'",host,"'",NullS); if (!(want_access & ~GRANT_ACL)) - update_schema_privilege(table, buff, 0, 0, 0, 0, "USAGE", 5, is_grantable); + update_schema_privilege(table, buff, 0, 0, 0, 0, + STRING_WITH_LEN("USAGE"), is_grantable); else { uint priv_id; @@ -5676,7 +5799,7 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) strxmov(buff,"'",user,"'@'",host,"'",NullS); if (!(want_access & ~GRANT_ACL)) update_schema_privilege(table, buff, acl_db->db, 0, 0, - 0, "USAGE", 5, is_grantable); + 0, STRING_WITH_LEN("USAGE"), is_grantable); else { int cnt; @@ -5736,7 +5859,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) strxmov(buff,"'",user,"'@'",grant_table->host.hostname,"'",NullS); if (!test_access) update_schema_privilege(table, buff, grant_table->db, grant_table->tname, - 0, 0, "USAGE", 5, is_grantable); + 0, 0, STRING_WITH_LEN("USAGE"), is_grantable); else { ulong j; @@ -5842,24 +5965,37 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, const char *db, const char *table) { Security_context *sctx= thd->security_ctx; + DBUG_ENTER("fill_effective_table_privileges"); + DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', table: `%s`.`%s`", + sctx->priv_host, (sctx->ip ? sctx->ip : "(NULL)"), + (sctx->priv_user ? sctx->priv_user : "(NULL)"), + db, table)); /* --skip-grants */ if (!initialized) { + DBUG_PRINT("info", ("skip grants")); grant->privilege= ~NO_ACCESS; // everything is allowed - return; + DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); + DBUG_VOID_RETURN; } /* global privileges */ grant->privilege= sctx->master_access; if (!sctx->priv_user) - return; // it is slave + { + DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); + DBUG_VOID_RETURN; // it is slave + } /* db privileges */ grant->privilege|= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, 0); if (!grant_option) - return; + { + DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); + DBUG_VOID_RETURN; + } /* table privileges */ if (grant->version != grant_version) @@ -5876,6 +6012,8 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, { grant->privilege|= grant->grant_table->privs; } + DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); + DBUG_VOID_RETURN; } #else /* NO_EMBEDDED_ACCESS_CHECKS */ diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 0e50737f84c..c8fadb73b0c 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -204,7 +204,9 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, uint show_command, uint number, bool dont_print_error); bool check_grant_column (THD *thd, GRANT_INFO *grant, const char *db_name, const char *table_name, - const char *name, uint length, uint show_command=0); + const char *name, uint length, Security_context *sctx); +bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref, + const char *name, uint length); bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant, const char* db_name, const char *table_name, Field_iterator *fields); diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 669f998cde5..0e4198a5114 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -466,7 +466,9 @@ void field_real::add() void field_decimal::add() { + /*TODO - remove rounding stuff after decimal_div returns proper frac */ my_decimal dec_buf, *dec= item->val_decimal(&dec_buf); + my_decimal rounded; uint length; TREE_ELEMENT *element; @@ -476,6 +478,9 @@ void field_decimal::add() return; } + my_decimal_round(E_DEC_FATAL_ERROR, dec, item->decimals, FALSE,&rounded); + dec= &rounded; + length= my_decimal_string_length(dec); if (decimal_is_zero(dec)) @@ -728,13 +733,13 @@ bool analyse::end_of_records() tree_info.found = 0; tree_info.item = (*f)->item; - tmp_str.set("ENUM(", 5,&my_charset_bin); + tmp_str.set(STRING_WITH_LEN("ENUM("),&my_charset_bin); tree_walk(&(*f)->tree, (*f)->collect_enum(), (char*) &tree_info, left_root_right); tmp_str.append(')'); if (!(*f)->nulls) - tmp_str.append(" NOT NULL"); + tmp_str.append(STRING_WITH_LEN(" NOT NULL")); output_str_length = tmp_str.length(); func_items[9]->set(tmp_str.ptr(), tmp_str.length(), tmp_str.charset()); if (result->send_data(result_fields)) @@ -744,35 +749,35 @@ bool analyse::end_of_records() ans.length(0); if (!(*f)->treemem && !(*f)->tree_elements) - ans.append("CHAR(0)", 7); + ans.append(STRING_WITH_LEN("CHAR(0)")); else if ((*f)->item->type() == Item::FIELD_ITEM) { switch (((Item_field*) (*f)->item)->field->real_type()) { case FIELD_TYPE_TIMESTAMP: - ans.append("TIMESTAMP", 9); + ans.append(STRING_WITH_LEN("TIMESTAMP")); break; case FIELD_TYPE_DATETIME: - ans.append("DATETIME", 8); + ans.append(STRING_WITH_LEN("DATETIME")); break; case FIELD_TYPE_DATE: case FIELD_TYPE_NEWDATE: - ans.append("DATE", 4); + ans.append(STRING_WITH_LEN("DATE")); break; case FIELD_TYPE_SET: - ans.append("SET", 3); + ans.append(STRING_WITH_LEN("SET")); break; case FIELD_TYPE_YEAR: - ans.append("YEAR", 4); + ans.append(STRING_WITH_LEN("YEAR")); break; case FIELD_TYPE_TIME: - ans.append("TIME", 4); + ans.append(STRING_WITH_LEN("TIME")); break; case FIELD_TYPE_DECIMAL: - ans.append("DECIMAL", 7); + ans.append(STRING_WITH_LEN("DECIMAL")); // if item is FIELD_ITEM, it _must_be_ Field_num in this case if (((Field_num*) ((Item_field*) (*f)->item)->field)->zerofill) - ans.append(" ZEROFILL"); + ans.append(STRING_WITH_LEN(" ZEROFILL")); break; default: (*f)->get_opt_type(&ans, rows); @@ -780,7 +785,7 @@ bool analyse::end_of_records() } } if (!(*f)->nulls) - ans.append(" NOT NULL"); + ans.append(STRING_WITH_LEN(" NOT NULL")); func_items[9]->set(ans.ptr(), ans.length(), ans.charset()); if (result->send_data(result_fields)) return -1; @@ -824,18 +829,18 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows) sprintf(buff, "BIGINT(%d)", num_info.integers); answer->append(buff, (uint) strlen(buff)); if (ev_num_info.llval >= 0 && ev_num_info.min_dval >= 0) - answer->append(" UNSIGNED"); + answer->append(STRING_WITH_LEN(" UNSIGNED")); if (num_info.zerofill) - answer->append(" ZEROFILL"); + answer->append(STRING_WITH_LEN(" ZEROFILL")); } else if (max_length < 256) { if (must_be_blob) { if (item->collation.collation == &my_charset_bin) - answer->append("TINYBLOB", 8); + answer->append(STRING_WITH_LEN("TINYBLOB")); else - answer->append("TINYTEXT", 8); + answer->append(STRING_WITH_LEN("TINYTEXT")); } else if ((max_length * (total_rows - nulls)) < (sum + total_rows)) { @@ -851,23 +856,23 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows) else if (max_length < (1L << 16)) { if (item->collation.collation == &my_charset_bin) - answer->append("BLOB", 4); + answer->append(STRING_WITH_LEN("BLOB")); else - answer->append("TEXT", 4); + answer->append(STRING_WITH_LEN("TEXT")); } else if (max_length < (1L << 24)) { if (item->collation.collation == &my_charset_bin) - answer->append("MEDIUMBLOB", 10); + answer->append(STRING_WITH_LEN("MEDIUMBLOB")); else - answer->append("MEDIUMTEXT", 10); + answer->append(STRING_WITH_LEN("MEDIUMTEXT")); } else { if (item->collation.collation == &my_charset_bin) - answer->append("LONGBLOB", 8); + answer->append(STRING_WITH_LEN("LONGBLOB")); else - answer->append("LONGTEXT", 8); + answer->append(STRING_WITH_LEN("LONGTEXT")); } } // field_str::get_opt_type @@ -897,14 +902,14 @@ void field_real::get_opt_type(String *answer, sprintf(buff, "BIGINT(%d)", len); answer->append(buff, (uint) strlen(buff)); if (min_arg >= 0) - answer->append(" UNSIGNED"); + answer->append(STRING_WITH_LEN(" UNSIGNED")); } else if (item->decimals == NOT_FIXED_DEC) { if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX) - answer->append("FLOAT", 5); + answer->append(STRING_WITH_LEN("FLOAT")); else - answer->append("DOUBLE", 6); + answer->append(STRING_WITH_LEN("DOUBLE")); } else { @@ -921,7 +926,7 @@ void field_real::get_opt_type(String *answer, // a single number shouldn't be zerofill (max_length - (item->decimals + 1)) != 1 && ((Field_num*) ((Item_field*) item)->field)->zerofill) - answer->append(" ZEROFILL"); + answer->append(STRING_WITH_LEN(" ZEROFILL")); } // field_real::get_opt_type @@ -945,14 +950,14 @@ void field_longlong::get_opt_type(String *answer, sprintf(buff, "BIGINT(%d)", (int) max_length); answer->append(buff, (uint) strlen(buff)); if (min_arg >= 0) - answer->append(" UNSIGNED"); + answer->append(STRING_WITH_LEN(" UNSIGNED")); // if item is FIELD_ITEM, it _must_be_ Field_num in this class if ((item->type() == Item::FIELD_ITEM) && // a single number shouldn't be zerofill max_length != 1 && ((Field_num*) ((Item_field*) item)->field)->zerofill) - answer->append(" ZEROFILL"); + answer->append(STRING_WITH_LEN(" ZEROFILL")); } // field_longlong::get_opt_type @@ -977,7 +982,7 @@ void field_ulonglong::get_opt_type(String *answer, // a single number shouldn't be zerofill max_length != 1 && ((Field_num*) ((Item_field*) item)->field)->zerofill) - answer->append(" ZEROFILL"); + answer->append(STRING_WITH_LEN(" ZEROFILL")); } //field_ulonglong::get_opt_type @@ -1021,10 +1026,16 @@ String *field_decimal::avg(String *s, ha_rows rows) s->set((double) 0.0, 1,my_thd_charset); return s; } - my_decimal num, avg_val; + my_decimal num, avg_val, rounded_avg; + int prec_increment= current_thd->variables.div_precincrement; + int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num); - my_decimal_div(E_DEC_FATAL_ERROR, &avg_val, sum+cur_sum, &num, 0); - my_decimal2string(E_DEC_FATAL_ERROR, &avg_val, 0, 0, '0', s); + my_decimal_div(E_DEC_FATAL_ERROR, &avg_val, sum+cur_sum, &num, prec_increment); + /* TODO remove this after decimal_div returns proper frac */ + my_decimal_round(E_DEC_FATAL_ERROR, &avg_val, + min(sum[cur_sum].frac + prec_increment, DECIMAL_MAX_SCALE), + FALSE,&rounded_avg); + my_decimal2string(E_DEC_FATAL_ERROR, &rounded_avg, 0, 0, '0', s); return s; } @@ -1036,13 +1047,19 @@ String *field_decimal::std(String *s, ha_rows rows) s->set((double) 0.0, 1,my_thd_charset); return s; } - my_decimal num, std_val, sum2, sum2d; + my_decimal num, tmp, sum2, sum2d; + double std_sqr; + int prec_increment= current_thd->variables.div_precincrement; + int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num); my_decimal_mul(E_DEC_FATAL_ERROR, &sum2, sum+cur_sum, sum+cur_sum); - my_decimal_div(E_DEC_FATAL_ERROR, &std_val, &sum2, &num, 0); - my_decimal_sub(E_DEC_FATAL_ERROR, &sum2, sum_sqr+cur_sum, &std_val); - my_decimal_div(E_DEC_FATAL_ERROR, &std_val, &sum2, &num, 0); - my_decimal2string(E_DEC_FATAL_ERROR, &std_val, 0, 0, '0', s); + my_decimal_div(E_DEC_FATAL_ERROR, &tmp, &sum2, &num, prec_increment); + my_decimal_sub(E_DEC_FATAL_ERROR, &sum2, sum_sqr+cur_sum, &tmp); + my_decimal_div(E_DEC_FATAL_ERROR, &tmp, &sum2, &num, prec_increment); + my_decimal2double(E_DEC_FATAL_ERROR, &tmp, &std_sqr); + s->set(((double) std_sqr <= 0.0 ? 0.0 : sqrt(std_sqr)), + min(item->decimals + prec_increment, NOT_FIXED_DEC), my_thd_charset); + return s; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 973fbca12f5..be3b64a5ef6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -37,11 +37,11 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, TABLE_LIST *table_list, MEM_ROOT *mem_root); static void free_cache_entry(TABLE *entry); static void mysql_rm_tmp_tables(void); -static my_bool open_new_frm(const char *path, const char *alias, - const char *db, const char *table_name, - uint db_stat, uint prgflag, - uint ha_open_flags, TABLE *outparam, - TABLE_LIST *table_desc, MEM_ROOT *mem_root); +static bool open_new_frm(THD *thd, const char *path, const char *alias, + const char *db, const char *table_name, + uint db_stat, uint prgflag, + uint ha_open_flags, TABLE *outparam, + TABLE_LIST *table_desc, MEM_ROOT *mem_root); extern "C" byte *table_cache_key(const byte *record,uint *length, my_bool not_used __attribute__((unused))) @@ -311,7 +311,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, thd->proc_info="Flushing tables"; close_old_data_files(thd,thd->open_tables,1,1); - mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL); + mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL, + TRUE); bool found=1; /* Wait until all threads has closed all the tables we had locked */ DBUG_PRINT("info", @@ -697,6 +698,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, SYNOPSIS unique_table() + thd thread handle table table which should be checked table_list list of tables @@ -722,7 +724,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, 0 if table is unique */ -TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list) +TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list) { TABLE_LIST *res; const char *d_name, *t_name; @@ -757,9 +759,10 @@ TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list) DBUG_PRINT("info", ("real table: %s.%s", d_name, t_name)); for (;;) { - if (!(res= find_table_in_global_list(table_list, d_name, t_name)) || - (!res->table || res->table != table->table) && - (res->select_lex && !res->select_lex->exclude_from_table_unique_test)) + if (((! (res= find_table_in_global_list(table_list, d_name, t_name))) && + (! (res= mysql_lock_have_duplicate(thd, table, table_list)))) || + ((!res->table || res->table != table->table) && + res->select_lex && !res->select_lex->exclude_from_table_unique_test)) break; /* If we found entry of this table or or table of SELECT which already @@ -1082,11 +1085,17 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, char key[MAX_DBKEY_LENGTH]; uint key_length; char *alias= table_list->alias; + HASH_SEARCH_STATE state; DBUG_ENTER("open_table"); /* find a unused table in the open table cache */ if (refresh) *refresh=0; + + /* an open table operation needs a lot of the stack space */ + if (check_stack_overrun(thd, STACK_MIN_SIZE_FOR_OPEN, (char *)&alias)) + return 0; + if (thd->killed) DBUG_RETURN(0); key_length= (uint) (strmov(strmov(key, table_list->db)+1, @@ -1193,22 +1202,22 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, */ { char path[FN_REFLEN]; + db_type not_used; strxnmov(path, FN_REFLEN, mysql_data_home, "/", table_list->db, "/", table_list->table_name, reg_ext, NullS); (void) unpack_filename(path, path); - if (mysql_frm_type(path) == FRMTYPE_VIEW) + if (mysql_frm_type(thd, path, ¬_used) == FRMTYPE_VIEW) { - TABLE tab;// will not be used (because it's VIEW) but have to be passed + /* + Will not be used (because it's VIEW) but has to be passed. + Also we will not free it (because it is a stack variable). + */ + TABLE tab; table= &tab; VOID(pthread_mutex_lock(&LOCK_open)); - if (open_unireg_entry(thd, table, table_list->db, - table_list->table_name, - alias, table_list, mem_root)) - { - table->next=table->prev=table; - free_cache_entry(table); - } - else + if (!open_unireg_entry(thd, table, table_list->db, + table_list->table_name, + alias, table_list, mem_root)) { DBUG_ASSERT(table_list->view != 0); VOID(pthread_mutex_unlock(&LOCK_open)); @@ -1237,11 +1246,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, /* close handler tables which are marked for flush */ if (thd->handler_tables) - mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE); + mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE); - for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; + for (table= (TABLE*) hash_first(&open_cache, (byte*) key, key_length, + &state); table && table->in_use ; - table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length, + &state)) { if (table->s->version != refresh_version) { @@ -1613,10 +1624,12 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock) { char *key= table->s->table_cache_key; uint key_length= table->s->key_length; - for (TABLE *search=(TABLE*) hash_search(&open_cache, - (byte*) key,key_length) ; + HASH_SEARCH_STATE state; + for (TABLE *search= (TABLE*) hash_first(&open_cache, (byte*) key, + key_length, &state); search ; - search = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + search= (TABLE*) hash_next(&open_cache, (byte*) key, + key_length, &state)) { if (search->locked_by_flush || search->locked_by_name && wait_for_name_lock || @@ -1641,7 +1654,7 @@ bool wait_for_tables(THD *thd) { thd->some_tables_deleted=0; close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0); - mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE); + mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE); if (!table_is_used(thd->open_tables,1)) break; (void) pthread_cond_wait(&COND_refresh,&LOCK_open); @@ -1755,7 +1768,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, thd->open_options, entry)) && (error != 5 || (fn_format(path, path, 0, reg_ext, MY_UNPACK_FILENAME), - open_new_frm(path, alias, db, name, + open_new_frm(thd, path, alias, db, name, (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX | HA_TRY_READ_ONLY), READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, @@ -1971,22 +1984,32 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) derived/information schema tables and views possible. Thus "counter" may be still zero for prelocked statement... - NOTE: The above notes may be out of date. Please wait for psergey to + NOTE: The above notes may be out of date. Please wait for psergey to document new prelocked behavior. */ - - if (!thd->prelocked_mode && !thd->lex->requires_prelocking() && + + if (!thd->prelocked_mode && !thd->lex->requires_prelocking() && thd->lex->sroutines_list.elements) { - bool first_no_prelocking, need_prelocking; + bool first_no_prelocking, need_prelocking, tabs_changed; TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last; DBUG_ASSERT(thd->lex->query_tables == *start); sp_get_prelocking_info(thd, &need_prelocking, &first_no_prelocking); - if ((sp_cache_routines_and_add_tables(thd, thd->lex, - first_no_prelocking) || - *start) && need_prelocking) + if (sp_cache_routines_and_add_tables(thd, thd->lex, + first_no_prelocking, + &tabs_changed)) + { + /* + Serious error during reading stored routines from mysql.proc table. + Something's wrong with the table or its contents, and an error has + been emitted; we must abort. + */ + result= -1; + goto err; + } + else if ((tabs_changed || *start) && need_prelocking) { query_tables_last_own= save_query_tables_last; *start= thd->lex->query_tables; @@ -2025,7 +2048,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) /* VIEW placeholder */ (*counter)--; - /* + /* tables->next_global list consists of two parts: 1) Query tables and underlying tables of views. 2) Tables used by all stored routines that this statement invokes on @@ -2110,9 +2133,18 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) tables->lock_type >= TL_WRITE_ALLOW_WRITE) { if (!query_tables_last_own) - query_tables_last_own= thd->lex->query_tables_last; - sp_cache_routines_and_add_tables_for_triggers(thd, thd->lex, - tables->table->triggers); + query_tables_last_own= thd->lex->query_tables_last; + if (sp_cache_routines_and_add_tables_for_triggers(thd, thd->lex, + tables)) + { + /* + Serious error during reading stored routines from mysql.proc table. + Something's wrong with the table or its contents, and an error has + been emitted; we must abort. + */ + result= -1; + goto err; + } } free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC)); } @@ -2133,9 +2165,20 @@ process_view_routines: /* We have at least one table in TL here. */ if (!query_tables_last_own) query_tables_last_own= thd->lex->query_tables_last; - sp_cache_routines_and_add_tables_for_view(thd, thd->lex, tables->view); + if (sp_cache_routines_and_add_tables_for_view(thd, thd->lex, tables)) + { + /* + Serious error during reading stored routines from mysql.proc table. + Something's wrong with the table or its contents, and an error has + been emitted; we must abort. + */ + result= -1; + goto err; + } } } + + err: thd->proc_info=0; free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block @@ -2634,7 +2677,7 @@ bool rm_temporary_table(enum db_type base, char *path) if (my_delete(path,MYF(0))) error=1; /* purecov: inspected */ *fn_ext(path)='\0'; // remove extension - handler *file=get_new_handler((TABLE*) 0, base); + handler *file= get_new_handler((TABLE*) 0, current_thd->mem_root, base); if (file && file->delete_table(path)) { error=1; @@ -2685,11 +2728,10 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table) thd thread handler table_list view to search for 'name' name name of field - item_name name of item if it will be created (VIEW) length length of name + item_name name of item if it will be created (VIEW) ref expression substituted in VIEW should be passed using this reference (return view_ref_found) - check_grants do check columns grants for view? register_tree_change TRUE if ref is not stack variable and we need register changes in item tree @@ -2701,8 +2743,8 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table) static Field * find_field_in_view(THD *thd, TABLE_LIST *table_list, - const char *name, const char *item_name, - uint length, Item **ref, bool check_grants, + const char *name, uint length, + const char *item_name, Item **ref, bool register_tree_change) { DBUG_ENTER("find_field_in_view"); @@ -2719,24 +2761,13 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, { if (!my_strcasecmp(system_charset_info, field_it.name(), name)) { - if (table_list->schema_table_reformed) - /* - Translation table items are always Item_fields and fixed already - ('mysql_schema_table' function). So we can return ->field. It is - used only for 'show & where' commands. - */ - DBUG_RETURN(((Item_field*) (field_it.item()))->field); -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (check_grants && - check_grant_column(thd, &table_list->grant, - table_list->view_db.str, - table_list->view_name.str, - name, length)) - DBUG_RETURN(WRONG_GRANT); -#endif // in PS use own arena or data will be freed after prepare if (register_tree_change) arena= thd->activate_stmt_arena_if_needed(&backup); + /* + create_item() may, or may not create a new Item, depending on + the column reference. See create_view_field() for details. + */ Item *item= field_it.create_item(thd); if (register_tree_change && arena) thd->restore_active_arena(arena, &backup); @@ -2778,7 +2809,6 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, length [in] length of name ref [in/out] if 'name' is resolved to a view field, ref is set to point to the found view field - check_grants [in] do check columns grants? register_tree_change [in] TRUE if ref is not stack variable and we need register changes in item tree actual_table [out] the original table reference where the field @@ -2799,8 +2829,7 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, static Field * find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, - uint length, Item **ref, bool check_grants, - bool register_tree_change, + uint length, Item **ref, bool register_tree_change, TABLE_LIST **actual_table) { List_iterator_fast<Natural_join_column> @@ -2825,23 +2854,16 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, break; } -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (check_grants && nj_col->check_grants(thd, name, length)) - DBUG_RETURN(WRONG_GRANT); -#endif - if (nj_col->view_field) { Item *item; - /* - The found field is a view field, we do as in find_field_in_view() - and return a pointer to pointer to the Item of that field. - */ if (register_tree_change) arena= thd->activate_stmt_arena_if_needed(&backup); - + /* + create_item() may, or may not create a new Item, depending on the + column reference. See create_view_field() for details. + */ item= nj_col->create_item(thd); - if (register_tree_change && arena) thd->restore_active_arena(arena, &backup); @@ -2887,7 +2909,6 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, table table where to search for the field name name of field length length of name - check_grants do check columns grants? allow_rowid do allow finding of "_rowid" field? cached_field_index_ptr cached position in field list (used to speedup lookup for fields in prepared tables) @@ -2899,8 +2920,7 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, Field * find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, - bool check_grants, bool allow_rowid, - uint *cached_field_index_ptr) + bool allow_rowid, uint *cached_field_index_ptr) { Field **field_ptr, *field; uint cached_field_index= *cached_field_index_ptr; @@ -2909,7 +2929,7 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, /* We assume here that table->field < NO_CACHED_FIELD_INDEX = UINT_MAX */ if (cached_field_index < table->s->fields && - !my_strcasecmp(system_charset_info, + !my_strcasecmp(system_charset_info, table->field[cached_field_index]->field_name, name)) field_ptr= table->field + cached_field_index; else if (table->s->name_hash.records) @@ -2939,12 +2959,6 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, update_field_dependencies(thd, field, table); -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (check_grants && check_grant_column(thd, &table->grant, - table->s->db, - table->s->table_name, name, length)) - field= WRONG_GRANT; -#endif DBUG_RETURN(field); } @@ -2957,14 +2971,13 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, thd [in] thread handler table_list [in] table reference to search name [in] name of field + length [in] field length of name item_name [in] name of item if it will be created (VIEW) - table_name [in] optional table name that qualifies the field db_name [in] optional database name that qualifies the - length [in] field length of name + table_name [in] optional table name that qualifies the field ref [in/out] if 'name' is resolved to a view field, ref is set to point to the found view field - check_grants_table [in] do check columns grants for table? - check_grants_view [in] do check columns grants for view? + check_privileges [in] check privileges allow_rowid [in] do allow finding of "_rowid" field? cached_field_index_ptr [in] cached position in field list (used to speedup lookup for fields in prepared tables) @@ -2994,11 +3007,11 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, Field * find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, - const char *name, const char *item_name, - const char *table_name, const char *db_name, - uint length, Item **ref, - bool check_grants_table, bool check_grants_view, - bool allow_rowid, uint *cached_field_index_ptr, + const char *name, uint length, + const char *item_name, const char *db_name, + const char *table_name, Item **ref, + bool check_privileges, bool allow_rowid, + uint *cached_field_index_ptr, bool register_tree_change, TABLE_LIST **actual_table) { Field *fld; @@ -3043,8 +3056,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, if (table_list->field_translation) { /* 'table_list' is a view or an information schema table. */ - if ((fld= find_field_in_view(thd, table_list, name, item_name, length, - ref, check_grants_view, + if ((fld= find_field_in_view(thd, table_list, name, length, item_name, ref, register_tree_change))) *actual_table= table_list; } @@ -3053,19 +3065,9 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, /* 'table_list' is a stored table. */ DBUG_ASSERT(table_list->table); if ((fld= find_field_in_table(thd, table_list->table, name, length, - check_grants_table, allow_rowid, + allow_rowid, cached_field_index_ptr))) *actual_table= table_list; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* check for views with temporary table algorithm */ - if (check_grants_view && table_list->view && - fld && fld != WRONG_GRANT && - check_grant_column(thd, &table_list->grant, - table_list->view_db.str, - table_list->view_name.str, - name, length)) - fld= WRONG_GRANT; -#endif } else { @@ -3082,11 +3084,10 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, TABLE_LIST *table; while ((table= it++)) { - if ((fld= find_field_in_table_ref(thd, table, name, item_name, - table_name, db_name, length, ref, - check_grants_table, - check_grants_view, - allow_rowid, cached_field_index_ptr, + if ((fld= find_field_in_table_ref(thd, table, name, length, item_name, + db_name, table_name, ref, + check_privileges, allow_rowid, + cached_field_index_ptr, register_tree_change, actual_table))) DBUG_RETURN(fld); } @@ -3099,11 +3100,16 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, directly the top-most NATURAL/USING join. */ fld= find_field_in_natural_join(thd, table_list, name, length, ref, - /* TIMOUR_TODO: check this with Sanja */ - check_grants_table || check_grants_view, register_tree_change, actual_table); } +#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* Check if there are sufficient access rights to the found field. */ + if (fld && check_privileges && + check_column_grant_in_table_ref(thd, *actual_table, name, length)) + fld= WRONG_GRANT; +#endif + DBUG_RETURN(fld); } @@ -3185,20 +3191,11 @@ find_field_in_tables(THD *thd, Item_ident *item, */ if (table_ref->table && !table_ref->view) found= find_field_in_table(thd, table_ref->table, name, length, - test(table_ref->table-> - grant.want_privilege) && - check_privileges, - 1, &(item->cached_field_index)); + TRUE, &(item->cached_field_index)); else - found= find_field_in_table_ref(thd, table_ref, name, item->name, - NULL, NULL, length, ref, - (table_ref->table && - test(table_ref->table->grant. - want_privilege) && - check_privileges), - (test(table_ref->grant.want_privilege) && - check_privileges), - 1, &(item->cached_field_index), + found= find_field_in_table_ref(thd, table_ref, name, length, item->name, + NULL, NULL, ref, check_privileges, + TRUE, &(item->cached_field_index), register_tree_change, &actual_table); if (found) @@ -3238,17 +3235,9 @@ find_field_in_tables(THD *thd, Item_ident *item, for (; cur_table != last_table ; cur_table= cur_table->next_name_resolution_table) { - Field *cur_field= find_field_in_table_ref(thd, cur_table, name, item->name, - table_name, db, - length, ref, - (cur_table->table && - test(cur_table->table->grant. - want_privilege) && - check_privileges), - (test(cur_table->grant. - want_privilege) - && check_privileges), - allow_rowid, + Field *cur_field= find_field_in_table_ref(thd, cur_table, name, length, + item->name, db, table_name, ref, + check_privileges, allow_rowid, &(item->cached_field_index), register_tree_change, &actual_table); @@ -3656,7 +3645,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, { bool is_created_1; bool found= FALSE; - if (!(nj_col_1= it_1.get_or_create_column_ref(thd, &is_created_1))) + if (!(nj_col_1= it_1.get_or_create_column_ref(&is_created_1))) goto err; field_name_1= nj_col_1->name(); @@ -3677,7 +3666,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, bool is_created_2; Natural_join_column *cur_nj_col_2; const char *cur_field_name_2; - if (!(cur_nj_col_2= it_2.get_or_create_column_ref(thd, &is_created_2))) + if (!(cur_nj_col_2= it_2.get_or_create_column_ref(&is_created_2))) goto err; cur_field_name_2= cur_nj_col_2->name(); @@ -3869,13 +3858,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, /* Append the columns of the first join operand. */ for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next()) { - if (!(nj_col_1= it_1.get_or_create_column_ref(thd, &is_created))) - goto err; - /* - The following assert checks that mark_common_columns() was run and - we created the list table_ref_1->join_columns. - */ - DBUG_ASSERT(!is_created); + nj_col_1= it_1.get_natural_column_ref(); if (nj_col_1->is_common) { natural_using_join->join_columns->push_back(nj_col_1); @@ -3921,13 +3904,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, /* Append the non-equi-join columns of the second join operand. */ for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next()) { - if (!(nj_col_2= it_2.get_or_create_column_ref(thd, &is_created))) - goto err; - /* - The following assert checks that mark_common_columns() was run and - we created the list table_ref_2->join_columns. - */ - DBUG_ASSERT(!is_created); + nj_col_2= it_2.get_natural_column_ref(); if (!nj_col_2->is_common) non_join_columns->push_back(nj_col_2); else @@ -4267,11 +4244,13 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, { reg2 Item *item; bool save_set_query_id= thd->set_query_id; + nesting_map save_allow_sum_func= thd->lex->allow_sum_func; List_iterator<Item> it(fields); DBUG_ENTER("setup_fields"); thd->set_query_id=set_query_id; - thd->allow_sum_func= allow_sum_func; + if (allow_sum_func) + thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; thd->where= THD::DEFAULT_WHERE; /* @@ -4294,6 +4273,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, if (!item->fixed && item->fix_fields(thd, it.ref()) || (item= *(it.ref()))->check_cols(1)) { + thd->lex->allow_sum_func= save_allow_sum_func; thd->set_query_id= save_set_query_id; DBUG_RETURN(TRUE); /* purecov: inspected */ } @@ -4304,6 +4284,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, item->split_sum_func(thd, ref_pointer_array, *sum_func_list); thd->used_tables|= item->used_tables(); } + thd->lex->allow_sum_func= save_allow_sum_func; thd->set_query_id= save_set_query_id; DBUG_RETURN(test(thd->net.report_error)); } @@ -4324,8 +4305,12 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables) { for (TABLE_LIST *table= tables; table; table= table->next_local) { - if (table->view && table->effective_algorithm == VIEW_ALGORITHM_MERGE) - list= make_leaves_list(list, table->ancestor); + if (table->merge_underlying_list) + { + DBUG_ASSERT(table->view && + table->effective_algorithm == VIEW_ALGORITHM_MERGE); + list= make_leaves_list(list, table->merge_underlying_list); + } else { *list= table; @@ -4425,16 +4410,17 @@ bool setup_tables(THD *thd, Name_resolution_context *context, table_list; table_list= table_list->next_local) { - if (table_list->ancestor) + if (table_list->merge_underlying_list) { - DBUG_ASSERT(table_list->view); + DBUG_ASSERT(table_list->view && + table_list->effective_algorithm == VIEW_ALGORITHM_MERGE); Query_arena *arena= thd->stmt_arena, backup; bool res; if (arena->is_conventional()) arena= 0; // For easier test else thd->set_n_backup_active_arena(arena, &backup); - res= table_list->setup_ancestor(thd); + res= table_list->setup_underlying(thd); if (arena) thd->restore_active_arena(arena, &backup); if (res) @@ -4656,8 +4642,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, because it was already created and stored with the natural join. */ Natural_join_column *nj_col; - if (!(nj_col= field_iterator.get_or_create_column_ref(thd, - &is_created))) + if (!(nj_col= field_iterator.get_or_create_column_ref(&is_created))) DBUG_RETURN(TRUE); DBUG_ASSERT(nj_col->table_field && !is_created); field_table= nj_col->table_ref->table; @@ -5079,15 +5064,17 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, bool result=0, signalled= 0; DBUG_ENTER("remove_table_from_cache"); - key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1; for (;;) { + HASH_SEARCH_STATE state; result= signalled= 0; - for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; + for (table= (TABLE*) hash_first(&open_cache, (byte*) key, key_length, + &state); table; - table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) + table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length, + &state)) { THD *in_use; table->s->version=0L; /* Free when thread is ready */ @@ -5208,6 +5195,7 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) SYNOPSIS open_new_frm() + THD thread handler path path to .frm alias alias for table db database @@ -5221,8 +5209,8 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) mem_root temporary MEM_ROOT for parsing */ -static my_bool -open_new_frm(const char *path, const char *alias, +static bool +open_new_frm(THD *thd, const char *path, const char *alias, const char *db, const char *table_name, uint db_stat, uint prgflag, uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc, @@ -5244,7 +5232,7 @@ open_new_frm(const char *path, const char *alias, my_error(ER_WRONG_OBJECT, MYF(0), db, table_name, "BASE TABLE"); goto err; } - if (mysql_make_view(parser, table_desc)) + if (mysql_make_view(thd, parser, table_desc)) goto err; } else diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index ed781e9bba3..cf3ba9c8c40 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -977,21 +977,31 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) goto err; } - /* - Test if the query is a SELECT - (pre-space is removed in dispatch_command). - - First '/' looks like comment before command it is not - frequently appeared in real lihe, consequently we can - check all such queries, too. - */ - if ((my_toupper(system_charset_info, sql[0]) != 'S' || - my_toupper(system_charset_info, sql[1]) != 'E' || - my_toupper(system_charset_info,sql[2]) !='L') && - sql[0] != '/') { - DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached")); - goto err; + uint i= 0; + /* + Skip '(' characters in queries like following: + (select a from t1) union (select a from t1); + */ + while (sql[i]=='(') + i++; + + /* + Test if the query is a SELECT + (pre-space is removed in dispatch_command) + + First '/' looks like comment before command it is not + frequently appeared in real lihe, consequently we can + check all such queries, too. + */ + if ((my_toupper(system_charset_info, sql[i]) != 'S' || + my_toupper(system_charset_info, sql[i + 1]) != 'E' || + my_toupper(system_charset_info, sql[i + 2]) != 'L') && + sql[i] != '/') + { + DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached")); + goto err; + } } STRUCT_LOCK(&structure_guard_mutex); @@ -2184,7 +2194,7 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used, tables_used; tables_used= tables_used->next_global, n++, block_table++) { - if (tables_used->derived) + if (tables_used->derived && !tables_used->view) { DBUG_PRINT("qcache", ("derived table skipped")); n--; @@ -2208,15 +2218,10 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used, tables_used->view_db.length + 1, HA_CACHE_TBL_NONTRANSACT, 0, 0)) DBUG_RETURN(0); - { - TABLE_COUNTER_TYPE inc= register_tables_from_list(tables_used->ancestor, - n + 1, - block_table + 1); - if (!inc) - DBUG_RETURN(0); - n+= inc; - block_table+= inc; - } + /* + We do not need to register view tables here because they are already + present in the global list. + */ } else { @@ -2832,13 +2837,6 @@ static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used, tables_used->view_name.str, tables_used->view_db.str)); *tables_type|= HA_CACHE_TBL_NONTRANSACT; - { - TABLE_COUNTER_TYPE subcount; - if (!(subcount= process_and_count_tables(tables_used->ancestor, - tables_type))) - DBUG_RETURN(0); - table_count+= subcount; - } } else { @@ -3052,6 +3050,7 @@ my_bool Query_cache::move_by_type(byte **border, } case Query_cache_block::TABLE: { + HASH_SEARCH_STATE record_idx; DBUG_PRINT("qcache", ("block 0x%lx TABLE", (ulong) block)); if (*border == 0) break; @@ -3069,7 +3068,7 @@ my_bool Query_cache::move_by_type(byte **border, byte *key; uint key_length; key=query_cache_table_get_key((byte*) block, &key_length, 0); - hash_search(&tables, (byte*) key, key_length); + hash_first(&tables, (byte*) key, key_length, &record_idx); block->destroy(); new_block->init(len); @@ -3103,7 +3102,7 @@ my_bool Query_cache::move_by_type(byte **border, /* Fix pointer to table name */ new_block->table()->table(new_block->table()->db() + tablename_offset); /* Fix hash to point at moved block */ - hash_replace(&tables, tables.current_record, (byte*) new_block); + hash_replace(&tables, &record_idx, (byte*) new_block); DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx", len, (ulong) new_block, (ulong) *border)); @@ -3111,6 +3110,7 @@ my_bool Query_cache::move_by_type(byte **border, } case Query_cache_block::QUERY: { + HASH_SEARCH_STATE record_idx; DBUG_PRINT("qcache", ("block 0x%lx QUERY", (ulong) block)); if (*border == 0) break; @@ -3128,7 +3128,7 @@ my_bool Query_cache::move_by_type(byte **border, byte *key; uint key_length; key=query_cache_query_get_key((byte*) block, &key_length, 0); - hash_search(&queries, (byte*) key, key_length); + hash_first(&queries, (byte*) key, key_length, &record_idx); // Move table of used tables memmove((char*) new_block->table(0), (char*) block->table(0), ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table))); @@ -3196,7 +3196,7 @@ my_bool Query_cache::move_by_type(byte **border, net->query_cache_query= (gptr) new_block; } /* Fix hash to point at moved block */ - hash_replace(&queries, queries.current_record, (byte*) new_block); + hash_replace(&queries, &record_idx, (byte*) new_block); DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx", len, (ulong) new_block, (ulong) *border)); break; diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 123d16b606d..69a0d6cd05d 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -410,7 +410,7 @@ protected: /* The following functions are only used when debugging - We don't protect these with ifndef DEBUG_OFF to not have to recompile + We don't protect these with ifndef DBUG_OFF to not have to recompile everything if we want to add checks of the cache at some places. */ void wreck(uint line, const char *message); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index fc9df020b6c..ed2089546da 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -183,6 +183,7 @@ THD::THD() spcont(NULL) { stmt_arena= this; + thread_stack= 0; db= 0; catalog= (char*)"std"; // the only catalog we have for now main_security_ctx.init(); @@ -376,7 +377,7 @@ void THD::cleanup(void) close_thread_tables(this); } mysql_ha_flush(this, (TABLE_LIST*) 0, - MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL); + MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL, FALSE); hash_free(&handler_tables_hash); delete_dynamic(&user_var_events); hash_free(&user_vars); @@ -472,10 +473,12 @@ void THD::awake(THD::killed_state state_to_set) killed= state_to_set; if (state_to_set != THD::KILL_QUERY) + { thr_alarm_kill(real_id); #ifdef SIGNAL_WITH_VIO_CLOSE - close_active_vio(); + close_active_vio(); #endif + } if (mysys_var) { pthread_mutex_lock(&mysys_var->mutex); @@ -517,6 +520,12 @@ void THD::awake(THD::killed_state state_to_set) bool THD::store_globals() { + /* + Assert that thread_stack is initialized: it's necessary to be able + to track stack overrun. + */ + DBUG_ASSERT(this->thread_stack); + if (my_pthread_setspecific_ptr(THR_THD, this) || my_pthread_setspecific_ptr(THR_MALLOC, &mem_root)) return 1; @@ -1495,7 +1504,13 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u) { my_var *mv= gl++; if (mv->local) - (void)local_vars.push_back(new Item_splocal(mv->s, mv->offset)); + { + Item_splocal *var= new Item_splocal(mv->s, mv->offset, mv->type); + (void)local_vars.push_back(var); +#ifndef DBUG_OFF + var->m_sp= mv->sp; +#endif + } else { Item_func_set_user_var *var= new Item_func_set_user_var(mv->s, item); @@ -1565,7 +1580,6 @@ Statement::Statement(enum enum_state state_arg, ulong id_arg, :Query_arena(&main_mem_root, state_arg), id(id_arg), set_query_id(1), - allow_sum_func(0), lex(&main_lex), query(0), query_length(0), @@ -1586,7 +1600,6 @@ void Statement::set_statement(Statement *stmt) { id= stmt->id; set_query_id= stmt->set_query_id; - allow_sum_func= stmt->allow_sum_func; lex= stmt->lex; query= stmt->query; query_length= stmt->query_length; @@ -1766,8 +1779,8 @@ bool select_dumpvar::send_data(List<Item> &items) { if ((yy=var_li++)) { - if (thd->spcont->set_item_eval(current_thd, - yy->get_offset(), it.ref(), zz->type)) + if (thd->spcont->set_variable(current_thd, yy->get_var_idx(), + *it.ref())) DBUG_RETURN(1); } } @@ -1802,6 +1815,7 @@ void TMP_TABLE_PARAM::init() group_parts= group_length= group_null_parts= 0; quick_group= 1; table_charset= 0; + precomputed_group_by= 0; } @@ -1916,6 +1930,7 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup) - Value for found_rows() is reset and restored - examined_row_count is added to the total - cuted_fields is added to the total + - new savepoint level is created and destroyed NOTES: Seed for random() is saved for the first! usage of RAND() @@ -1934,11 +1949,13 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, backup->last_insert_id= last_insert_id; backup->next_insert_id= next_insert_id; backup->insert_id_used= insert_id_used; + backup->clear_next_insert_id= clear_next_insert_id; backup->limit_found_rows= limit_found_rows; backup->examined_row_count= examined_row_count; backup->sent_row_count= sent_row_count; backup->cuted_fields= cuted_fields; backup->client_capabilities= client_capabilities; + backup->savepoints= transaction.savepoints; if (!lex->requires_prelocking() || is_update_query(lex->sql_command)) options&= ~OPTION_BIN_LOG; @@ -1951,6 +1968,7 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, examined_row_count= 0; sent_row_count= 0; cuted_fields= 0; + transaction.savepoints= 0; #ifndef EMBEDDED_LIBRARY /* Surpress OK packets in case if we will execute statements */ @@ -1961,6 +1979,21 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, void THD::restore_sub_statement_state(Sub_statement_state *backup) { + /* + To save resources we want to release savepoints which were created + during execution of function or trigger before leaving their savepoint + level. It is enough to release first savepoint set on this level since + all later savepoints will be released automatically. + */ + if (transaction.savepoints) + { + SAVEPOINT *sv; + for (sv= transaction.savepoints; sv->prev; sv= sv->prev) + {} + /* ha_release_savepoint() never returns error. */ + (void)ha_release_savepoint(this, sv); + } + transaction.savepoints= backup->savepoints; options= backup->options; in_sub_stmt= backup->in_sub_stmt; net.no_send_ok= backup->no_send_ok; @@ -1968,6 +2001,7 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) last_insert_id= backup->last_insert_id; next_insert_id= backup->next_insert_id; insert_id_used= backup->insert_id_used; + clear_next_insert_id= backup->clear_next_insert_id; limit_found_rows= backup->limit_found_rows; sent_row_count= backup->sent_row_count; client_capabilities= backup->client_capabilities; diff --git a/sql/sql_class.h b/sql/sql_class.h index 7ca168ec518..c025b4f0774 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -189,11 +189,10 @@ class MYSQL_LOG: public TC_LOG { private: /* LOCK_log and LOCK_index are inited by init_pthread_objects() */ - pthread_mutex_t LOCK_log, LOCK_index, LOCK_readers; + pthread_mutex_t LOCK_log, LOCK_index; + pthread_mutex_t LOCK_prep_xids; + pthread_cond_t COND_prep_xids; pthread_cond_t update_cond; - pthread_cond_t reset_cond; - bool reset_pending; - int readers_count; ulonglong bytes_written; time_t last_time,query_start; IO_CACHE log_file; @@ -201,21 +200,6 @@ class MYSQL_LOG: public TC_LOG char *name; char time_buff[20],db[NAME_LEN+1]; char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN]; - // current file sequence number for load data infile binary logging - uint file_id; - uint open_count; // For replication - volatile enum_log_type log_type; - enum cache_type io_cache_type; - bool write_error, inited; - bool need_start_event; - /* - no_auto_events means we don't want any of these automatic events : - Start/Rotate/Stop. That is, in 4.x when we rotate a relay log, we don't want - a Rotate_log event to be written to the relay log. When we start a relay log - etc. So in 4.x this is 1 for relay logs, 0 for binlogs. - In 5.0 it's 0 for relay logs too! - */ - bool no_auto_events; /* The max size before rotation (usable only if log_type == LOG_BIN: binary logs and relay logs). @@ -227,13 +211,37 @@ class MYSQL_LOG: public TC_LOG fix_max_relay_log_size). */ ulong max_size; - ulong prepared_xids; /* for tc log - number of xids to remember */ - pthread_mutex_t LOCK_prep_xids; - pthread_cond_t COND_prep_xids; + volatile enum_log_type log_type; + enum cache_type io_cache_type; + // current file sequence number for load data infile binary logging + uint file_id; + uint open_count; // For replication + int readers_count; + bool write_error, inited; + bool need_start_event; + /* + no_auto_events means we don't want any of these automatic events : + Start/Rotate/Stop. That is, in 4.x when we rotate a relay log, we don't + want a Rotate_log event to be written to the relay log. When we start a + relay log etc. So in 4.x this is 1 for relay logs, 0 for binlogs. + In 5.0 it's 0 for relay logs too! + */ + bool no_auto_events; friend class Log_event; public: + /* + These describe the log's format. This is used only for relay logs. + _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's + necessary to have 2 distinct objects, because the I/O thread may be reading + events in a different format from what the SQL thread is reading (consider + the case of a master which has been upgraded from 5.0 to 5.1 without doing + RESET MASTER, or from 4.x to 5.0). + */ + Format_description_log_event *description_event_for_exec, + *description_event_for_queue; + MYSQL_LOG(); /* note that there's no destructor ~MYSQL_LOG() ! @@ -246,18 +254,6 @@ public: int log(THD *thd, my_xid xid); void unlog(ulong cookie, my_xid xid); int recover(IO_CACHE *log, Format_description_log_event *fdle); - - /* - These describe the log's format. This is used only for relay logs. - _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's - necessary to have 2 distinct objects, because the I/O thread may be reading - events in a different format from what the SQL thread is reading (consider - the case of a master which has been upgraded from 5.0 to 5.1 without doing - RESET MASTER, or from 4.x to 5.0). - */ - Format_description_log_event *description_event_for_exec, - *description_event_for_queue; - void reset_bytes_written() { bytes_written = 0; @@ -337,9 +333,6 @@ public: int purge_logs_before_date(time_t purge_time); int purge_first_log(struct st_relay_log_info* rli, bool included); bool reset_logs(THD* thd); - inline bool is_reset_pending() { return reset_pending; } - void readers_addref(); - void readers_release(); void close(uint exiting); // iterating through the log index file @@ -536,6 +529,7 @@ struct system_variables ulong completion_type; /* Determines which non-standard SQL behaviour should be enabled */ ulong sql_mode; + ulong max_sp_recursion_depth; /* check of key presence in updatable view */ ulong updatable_views_with_limit; ulong default_week_format; @@ -785,19 +779,6 @@ public: field list can not contain duplicates. */ bool set_query_id; - /* - This variable is used in post-parse stage to declare that sum-functions, - or functions which have sense only if GROUP BY is present, are allowed. - For example in queries - SELECT MIN(i) FROM foo - SELECT GROUP_CONCAT(a, b, MIN(i)) FROM ... GROUP BY ... - MIN(i) have no sense. - Though it's grammar-related issue, it's hard to catch it out during the - parse stage because GROUP BY clause goes in the end of query. This - variable is mainly used in setup_fields/fix_fields. - See item_sum.cc for details. - */ - bool allow_sum_func; LEX_STRING name; /* name for named prepared statements */ LEX *lex; // parse tree descriptor @@ -1095,8 +1076,9 @@ public: ha_rows cuted_fields, sent_row_count, examined_row_count; ulong client_capabilities; uint in_sub_stmt; - bool enable_slow_log, insert_id_used; + bool enable_slow_log, insert_id_used, clear_next_insert_id; my_bool no_send_ok; + SAVEPOINT *savepoints; }; @@ -1234,14 +1216,16 @@ public: free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); #endif } -#ifdef USING_TRANSACTIONS st_transactions() { +#ifdef USING_TRANSACTIONS bzero((char*)this, sizeof(*this)); xid_state.xid.null(); init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0); - } +#else + xid_state.xa_state= XA_NOTR; #endif + } } transaction; Field *dupp_field; #ifndef __WIN__ @@ -1824,11 +1808,18 @@ public: uint convert_blob_length; CHARSET_INFO *table_charset; bool schema_table; + /* + True if GROUP BY and its aggregate functions are already computed + by a table access method (e.g. by loose index scan). In this case + query execution should not perform aggregation and should treat + aggregate functions as normal functions. + */ + bool precomputed_group_by; TMP_TABLE_PARAM() :copy_field(0), group_parts(0), group_length(0), group_null_parts(0), convert_blob_length(0), - schema_table(0) + schema_table(0), precomputed_group_by(0) {} ~TMP_TABLE_PARAM() { @@ -2090,6 +2081,13 @@ public: class my_var : public Sql_alloc { public: LEX_STRING s; +#ifndef DBUG_OFF + /* + Routine to which this Item_splocal belongs. Used for checking if correct + runtime context is used for variable handling. + */ + sp_head *sp; +#endif bool local; uint offset; enum_field_types type; diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index e8da691ea18..89c160cd70a 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -558,6 +558,25 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused))) result->prepare(item_list, &fake_unit) || table->file->ha_rnd_init(TRUE)); thd->restore_active_arena(this, &backup_arena); + if (rc == 0) + { + /* + Now send the result set metadata to the client. We need to + do it here, as in Select_materialize::send_fields the items + for column types are not yet created (send_fields requires + a list of items). The new types may differ from the original + ones sent at prepare if some of them were altered by MySQL + HEAP tables mechanism -- used when create_tmp_field_from_item + may alter the original column type. + + We can't simply supply SEND_EOF flag to send_fields, because + send_fields doesn't flush the network buffer. + */ + rc= result->send_fields(item_list, Protocol::SEND_NUM_ROWS); + thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; + result->send_eof(); + thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; + } return rc; } @@ -642,19 +661,10 @@ Materialized_cursor::~Materialized_cursor() bool Select_materialize::send_fields(List<Item> &list, uint flags) { - bool rc; DBUG_ASSERT(table == 0); if (create_result_table(unit->thd, unit->get_unit_column_types(), FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, "")) return TRUE; - /* - We can't simply supply SEND_EOF flag to send_fields, because send_fields - doesn't flush the network buffer. - */ - rc= result->send_fields(list, Protocol::SEND_NUM_ROWS); - thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; - result->send_eof(); - thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; - return rc; + return FALSE; } diff --git a/sql/sql_db.cc b/sql/sql_db.cc index a5dabc8140c..2500b213f4c 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1162,9 +1162,20 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) DBUG_RETURN(1); } end: - x_free(thd->db); - thd->db=dbname; // THD::~THD will free this - thd->db_length=db_length; + if (!(thd->slave_thread)) + x_free(thd->db); + if (dbname && dbname[0] == 0) + { + if (!(thd->slave_thread)) + x_free(dbname); + thd->db= NULL; + thd->db_length= 0; + } + else + { + thd->db= dbname; // THD::~THD will free this + thd->db_length= db_length; + } #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!no_access_check) sctx->db_access= db_access; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 83f50ba3ac5..d8a8f28b92b 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -158,14 +158,16 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE), MYF(MY_FAE | MY_ZEROFILL)); - if ( !(sortorder=make_unireg_sortorder((ORDER*) order->first, &length)) || + if (!(sortorder= make_unireg_sortorder((ORDER*) order->first, + &length)) || (table->sort.found_records = filesort(thd, table, sortorder, length, - select, HA_POS_ERROR, - &examined_rows)) + select, HA_POS_ERROR, + &examined_rows)) == HA_POS_ERROR) { delete select; free_underlaid_joins(thd, &thd->lex->select_lex); + DBUG_RETURN(TRUE); } /* Filesort has already found and selected the rows we want to delete, @@ -291,6 +293,7 @@ cleanup: if (!transactional_table) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } + free_underlaid_joins(thd, select_lex); if (transactional_table) { if (ha_autocommit_or_rollback(thd,error >= 0)) @@ -302,7 +305,6 @@ cleanup: mysql_unlock_tables(thd, thd->lock); thd->lock=0; } - free_underlaid_joins(thd, select_lex); if (error < 0) { thd->row_count_func= deleted; @@ -331,7 +333,7 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) SELECT_LEX *select_lex= &thd->lex->select_lex; DBUG_ENTER("mysql_prepare_delete"); - thd->allow_sum_func= 0; + thd->lex->allow_sum_func= 0; if (setup_tables(thd, &thd->lex->select_lex.context, &thd->lex->select_lex.top_join_list, table_list, conds, &select_lex->leaf_tables, @@ -346,7 +348,7 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) } { TABLE_LIST *duplicate; - if ((duplicate= unique_table(table_list, table_list->next_global))) + if ((duplicate= unique_table(thd, table_list, table_list->next_global))) { update_non_unique_table_error(table_list, "DELETE", duplicate); DBUG_RETURN(TRUE); @@ -414,8 +416,9 @@ bool mysql_multi_delete_prepare(THD *thd) if (!(target_tbl->table= target_tbl->correspondent_table->table)) { DBUG_ASSERT(target_tbl->correspondent_table->view && - target_tbl->correspondent_table->ancestor && - target_tbl->correspondent_table->ancestor->next_local); + target_tbl->correspondent_table->merge_underlying_list && + target_tbl->correspondent_table->merge_underlying_list-> + next_local); my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), target_tbl->correspondent_table->view_db.str, target_tbl->correspondent_table->view_name.str); @@ -435,7 +438,7 @@ bool mysql_multi_delete_prepare(THD *thd) */ { TABLE_LIST *duplicate; - if ((duplicate= unique_table(target_tbl->correspondent_table, + if ((duplicate= unique_table(thd, target_tbl->correspondent_table, lex->query_tables))) { update_non_unique_table_error(target_tbl->correspondent_table, @@ -830,7 +833,8 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) if (!dont_send_ok) { db_type table_type; - if ((table_type=get_table_type(thd, path)) == DB_TYPE_UNKNOWN) + mysql_frm_type(thd, path, &table_type); + if (table_type == DB_TYPE_UNKNOWN) { my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->table_name); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 74b239e1637..e1817985cbd 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -35,14 +35,14 @@ processor procedure of derived table processing RETURN - 0 ok - 1 Error and error message given + FALSE OK + TRUE Error */ -int -mysql_handle_derived(LEX *lex, int (*processor)(THD*, LEX*, TABLE_LIST*)) +bool +mysql_handle_derived(LEX *lex, bool (*processor)(THD*, LEX*, TABLE_LIST*)) { - int res= 0; + bool res= FALSE; if (lex->derived_tables) { lex->thd->derived_tables_processing= TRUE; @@ -95,16 +95,16 @@ out: close_thread_tables() RETURN - 0 ok - 1 Error and an error message was given + FALSE OK + TRUE Error */ -int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) +bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) { SELECT_LEX_UNIT *unit= orig_table_list->derived; - int res= 0; ulonglong create_options; DBUG_ENTER("mysql_derived_prepare"); + bool res= FALSE; if (unit) { SELECT_LEX *first_select= unit->first_select(); @@ -118,7 +118,7 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) sl->context.outer_context= 0; if (!(derived_result= new select_union)) - DBUG_RETURN(1); // out of memory + DBUG_RETURN(TRUE); // out of memory // st_select_lex_unit::prepare correctly work for single select if ((res= unit->prepare(thd, derived_result, 0))) @@ -184,7 +184,10 @@ exit: table->derived_select_number= first_select->select_number; table->s->tmp_table= TMP_TABLE; #ifndef NO_EMBEDDED_ACCESS_CHECKS - table->grant.privilege= SELECT_ACL; + if (orig_table_list->referencing_view) + table->grant= orig_table_list->grant; + else + table->grant.privilege= SELECT_ACL; #endif orig_table_list->db= (char *)""; orig_table_list->db_length= 0; @@ -195,8 +198,8 @@ exit: thd->derived_tables= table; } } - else if (orig_table_list->ancestor) - orig_table_list->set_ancestor(); + else if (orig_table_list->merge_underlying_list) + orig_table_list->set_underlying_merge(); DBUG_RETURN(res); } @@ -220,15 +223,15 @@ exit: Due to evaluation of LIMIT clause it can not be used at prepared stage. RETURN - 0 ok - 1 Error and an error message was given + FALSE OK + TRUE Error */ -int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) +bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) { TABLE *table= orig_table_list->table; SELECT_LEX_UNIT *unit= orig_table_list->derived; - int res= 0; + bool res= FALSE; /*check that table creation pass without problem and it is derived table */ if (table && unit) @@ -271,7 +274,7 @@ int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) there were no derived tables */ if (derived_result->flush()) - res= 1; + res= TRUE; if (!lex->describe) unit->cleanup(); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index cc45a7001cd..fae48c7d164 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -227,6 +227,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) /* add to hash */ if (my_hash_insert(&thd->handler_tables_hash, (byte*) hash_tables)) { + my_free((char*) hash_tables, MYF(0)); mysql_ha_close(thd, tables); goto err; } @@ -336,6 +337,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ha_rows select_limit_cnt, ha_rows offset_limit_cnt) { TABLE_LIST *hash_tables; + TABLE **table_ptr; TABLE *table; MYSQL_LOCK *lock; List<Item> list; @@ -412,6 +414,13 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, } tables->table=table; + HANDLER_TABLES_HACK(thd); + lock= mysql_lock_tables(thd, &tables->table, 1, 0, ¬_used); + HANDLER_TABLES_HACK(thd); + + if (!lock) + goto err0; // mysql_lock_tables() printed error message already + if (cond && ((!cond->fixed && cond->fix_fields(thd, &cond)) || cond->check_cols(1))) goto err0; @@ -431,13 +440,6 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); - HANDLER_TABLES_HACK(thd); - lock= mysql_lock_tables(thd, &tables->table, 1, 0, ¬_used); - HANDLER_TABLES_HACK(thd); - - if (!lock) - goto err0; // mysql_lock_tables() printed error message already - /* In ::external_lock InnoDB resets the fields which tell it that the handle is used in the HANDLER interface. Tell it again that @@ -594,6 +596,7 @@ err0: MYSQL_HA_REOPEN_ON_USAGE mark for reopen. MYSQL_HA_FLUSH_ALL flush all tables, not only those marked for flush. + is_locked If LOCK_open is locked. DESCRIPTION The list of HANDLER tables may be NULL, in which case all HANDLER @@ -601,7 +604,6 @@ err0: If 'tables' is NULL and MYSQL_HA_FLUSH_ALL is not set, all HANDLER tables marked for flush are closed. Broadcasts a COND_refresh condition, for every table closed. - The caller must lock LOCK_open. NOTE Since mysql_ha_flush() is called when the base table has to be closed, @@ -611,10 +613,12 @@ err0: 0 ok */ -int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags) +int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags, + bool is_locked) { TABLE_LIST *tmp_tables; TABLE **table_ptr; + bool did_lock= FALSE; DBUG_ENTER("mysql_ha_flush"); DBUG_PRINT("enter", ("tables: %p mode_flags: 0x%02x", tables, mode_flags)); @@ -640,6 +644,12 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags) (*table_ptr)->s->db, (*table_ptr)->s->table_name, (*table_ptr)->alias)); + /* The first time it is required, lock for close_thread_table(). */ + if (! did_lock && ! is_locked) + { + VOID(pthread_mutex_lock(&LOCK_open)); + did_lock= TRUE; + } mysql_ha_flush_table(thd, table_ptr, mode_flags); continue; } @@ -658,6 +668,12 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags) if ((mode_flags & MYSQL_HA_FLUSH_ALL) || ((*table_ptr)->s->version != refresh_version)) { + /* The first time it is required, lock for close_thread_table(). */ + if (! did_lock && ! is_locked) + { + VOID(pthread_mutex_lock(&LOCK_open)); + did_lock= TRUE; + } mysql_ha_flush_table(thd, table_ptr, mode_flags); continue; } @@ -665,6 +681,10 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags) } } + /* Release the lock if it was taken by this function. */ + if (did_lock) + VOID(pthread_mutex_unlock(&LOCK_open)); + DBUG_RETURN(0); } @@ -696,8 +716,8 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags) table->alias, mode_flags)); if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, - (byte*) (*table_ptr)->alias, - strlen((*table_ptr)->alias) + 1))) + (byte*) table->alias, + strlen(table->alias) + 1))) { if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE)) { @@ -711,7 +731,9 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags) } } + safe_mutex_assert_owner(&LOCK_open); (*table_ptr)->file->ha_index_or_rnd_end(); + safe_mutex_assert_owner(&LOCK_open); if (close_thread_table(thd, table_ptr)) { /* Tell threads waiting for refresh that something has happened */ diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 088b55c2fd8..736be2310cb 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -108,11 +108,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, { // Part field list SELECT_LEX *select_lex= &thd->lex->select_lex; Name_resolution_context *context= &select_lex->context; - TABLE_LIST *save_next_local; - TABLE_LIST *save_table_list; - TABLE_LIST *save_first_name_resolution_table; - TABLE_LIST *save_next_name_resolution_table; - bool save_resolve_in_select_list; + Name_resolution_context_state ctx_state; int res; if (fields.elements != values.elements) @@ -125,14 +121,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, select_lex->no_wrap_view_item= TRUE; /* Save the state of the current name resolution context. */ - save_table_list= context->table_list; - save_first_name_resolution_table= context->first_name_resolution_table; - save_next_name_resolution_table= (context->first_name_resolution_table) ? - context->first_name_resolution_table-> - next_name_resolution_table : - NULL; - save_resolve_in_select_list= context->resolve_in_select_list; - save_next_local= table_list->next_local; + ctx_state.save_state(context, table_list); /* Perform name resolution only in the first table - 'table_list', @@ -143,13 +132,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, res= setup_fields(thd, 0, fields, 1, 0, 0); /* Restore the current context. */ - table_list->next_local= save_next_local; - context->table_list= save_table_list; - context->first_name_resolution_table= save_first_name_resolution_table; - if (context->first_name_resolution_table) - context->first_name_resolution_table-> - next_name_resolution_table= save_next_name_resolution_table; - context->resolve_in_select_list= save_resolve_in_select_list; + ctx_state.restore_state(context, table_list); thd->lex->select_lex.no_wrap_view_item= FALSE; if (res) @@ -274,19 +257,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, */ bool log_on= (thd->options & OPTION_BIN_LOG) || (!(thd->security_ctx->master_access & SUPER_ACL)); - bool transactional_table; + bool transactional_table, joins_freed= FALSE; uint value_count; ulong counter = 1; ulonglong id; COPY_INFO info; TABLE *table= 0; - TABLE_LIST *save_table_list; - TABLE_LIST *save_next_local; - TABLE_LIST *save_first_name_resolution_table; - TABLE_LIST *save_next_name_resolution_table; List_iterator_fast<List_item> its(values_list); List_item *values; Name_resolution_context *context; + Name_resolution_context_state ctx_state; #ifndef EMBEDDED_LIBRARY char *query= thd->query; #endif @@ -367,13 +347,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, context= &thd->lex->select_lex.context; /* Save the state of the current name resolution context. */ - save_table_list= context->table_list; - save_first_name_resolution_table= context->first_name_resolution_table; - save_next_name_resolution_table= (context->first_name_resolution_table) ? - context->first_name_resolution_table-> - next_name_resolution_table : - NULL; - save_next_local= table_list->next_local; + ctx_state.save_state(context, table_list); /* Perform name resolution only in the first table - 'table_list', @@ -397,16 +371,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, its.rewind (); /* Restore the current context. */ - table_list->next_local= save_next_local; - context->first_name_resolution_table= save_first_name_resolution_table; - if (context->first_name_resolution_table) - context->first_name_resolution_table-> - next_name_resolution_table= save_next_name_resolution_table; + ctx_state.restore_state(context, table_list); /* Fill in the given fields and dump it to the table file */ - info.records= info.deleted= info.copied= info.updated= 0; info.ignore= ignore; info.handle_duplicates=duplic; @@ -544,6 +513,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->row_count++; } + free_underlaid_joins(thd, &thd->lex->select_lex); + joins_freed= TRUE; + /* Now all rows are inserted. Time to update logs and sends response to user @@ -642,7 +614,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->row_count_func= info.copied+info.deleted+info.updated; ::send_ok(thd, (ulong) thd->row_count_func, id, buff); } - free_underlaid_joins(thd, &thd->lex->select_lex); thd->abort_on_warning= 0; DBUG_RETURN(FALSE); @@ -651,7 +622,8 @@ abort: if (lock_type == TL_WRITE_DELAYED) end_delayed_insert(thd); #endif - free_underlaid_joins(thd, &thd->lex->select_lex); + if (!joins_freed) + free_underlaid_joins(thd, &thd->lex->select_lex); thd->abort_on_warning= 0; DBUG_RETURN(TRUE); } @@ -814,11 +786,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, { SELECT_LEX *select_lex= &thd->lex->select_lex; Name_resolution_context *context= &select_lex->context; - TABLE_LIST *save_table_list; - TABLE_LIST *save_next_local; - TABLE_LIST *save_first_name_resolution_table; - TABLE_LIST *save_next_name_resolution_table; - bool save_resolve_in_select_list; + Name_resolution_context_state ctx_state; bool insert_into_view= (table_list->view != 0); bool res= 0; DBUG_ENTER("mysql_prepare_insert"); @@ -858,15 +826,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(TRUE); /* Save the state of the current name resolution context. */ - save_table_list= context->table_list; - /* Here first_name_resolution_table points to the first select table. */ - save_first_name_resolution_table= context->first_name_resolution_table; - save_next_name_resolution_table= (context->first_name_resolution_table) ? - context->first_name_resolution_table-> - next_name_resolution_table : - NULL; - save_resolve_in_select_list= context->resolve_in_select_list; - save_next_local= table_list->next_local; + ctx_state.save_state(context, table_list); /* Perform name resolution only in the first table - 'table_list', @@ -891,23 +851,17 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, */ if (select_lex->group_list.elements == 0) { - context->table_list->next_local= save_next_local; + context->table_list->next_local= ctx_state.save_next_local; /* first_name_resolution_table was set by resolve_in_table_list_only() */ context->first_name_resolution_table-> - next_name_resolution_table= save_next_local; + next_name_resolution_table= ctx_state.save_next_local; } if (!res) res= setup_fields(thd, 0, update_values, 1, 0, 0); } /* Restore the current context. */ - table_list->next_local= save_next_local; - context->table_list= save_table_list; - context->first_name_resolution_table= save_first_name_resolution_table; - if (context->first_name_resolution_table) - context->first_name_resolution_table-> - next_name_resolution_table= save_next_name_resolution_table; - context->resolve_in_select_list= save_resolve_in_select_list; + ctx_state.restore_state(context, table_list); if (res) DBUG_RETURN(res); @@ -919,7 +873,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, { Item *fake_conds= 0; TABLE_LIST *duplicate; - if ((duplicate= unique_table(table_list, table_list->next_global))) + if ((duplicate= unique_table(thd, table_list, table_list->next_global))) { update_non_unique_table_error(table_list, "INSERT", duplicate); DBUG_RETURN(TRUE); @@ -1723,6 +1677,7 @@ pthread_handler_t handle_delayed_insert(void *arg) #endif DBUG_ENTER("handle_delayed_insert"); + thd->thread_stack= (char*) &thd; if (init_thr_lock() || thd->store_globals()) { thd->fatal_error(); @@ -2175,17 +2130,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) { /* Save the state of the current name resolution context. */ Name_resolution_context *context= &lex->select_lex.context; - TABLE_LIST *save_table_list; - TABLE_LIST *save_next_local; - TABLE_LIST *save_first_name_resolution_table; - TABLE_LIST *save_next_name_resolution_table; - save_table_list= context->table_list; - save_first_name_resolution_table= context->first_name_resolution_table; - save_next_name_resolution_table= (context->first_name_resolution_table) ? - context->first_name_resolution_table-> - next_name_resolution_table : - NULL; - save_next_local= table_list->next_local; + Name_resolution_context_state ctx_state; + + /* Save the state of the current name resolution context. */ + ctx_state.save_state(context, table_list); /* Perform name resolution only in the first table - 'table_list'. */ table_list->next_local= 0; @@ -2201,20 +2149,15 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) */ if (lex->select_lex.group_list.elements == 0) { - context->table_list->next_local= save_next_local; + context->table_list->next_local= ctx_state.save_next_local; /* first_name_resolution_table was set by resolve_in_table_list_only() */ context->first_name_resolution_table-> - next_name_resolution_table= save_next_local; + next_name_resolution_table= ctx_state.save_next_local; } res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0); /* Restore the current context. */ - table_list->next_local= save_next_local; - context->first_name_resolution_table= save_first_name_resolution_table; - if (context->first_name_resolution_table) - context->first_name_resolution_table-> - next_name_resolution_table= save_next_name_resolution_table; - + ctx_state.restore_state(context, table_list); } lex->current_select= lex_current_select_save; @@ -2231,7 +2174,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) query */ if (!(lex->current_select->options & OPTION_BUFFER_RESULT) && - unique_table(table_list, table_list->next_global)) + unique_table(thd, table_list, table_list->next_global)) { /* Using same table for INSERT and SELECT */ lex->current_select->options|= OPTION_BUFFER_RESULT; @@ -2491,7 +2434,11 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) } /* First field to copy */ - field=table->field+table->s->fields - values.elements; + field= table->field+table->s->fields - values.elements; + + /* Mark all fields that are given values */ + for (Field **f= field ; *f ; f++) + (*f)->query_id= thd->query_id; /* Don't set timestamp if used */ table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 11f056d6510..946b6a28430 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -182,6 +182,9 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->sroutines_list.empty(); lex->sroutines_list_own_last= lex->sroutines_list.next; lex->sroutines_list_own_elements= 0; + lex->nest_level=0 ; + lex->allow_sum_func= 0; + lex->in_sum_func= NULL; DBUG_VOID_RETURN; } @@ -1127,6 +1130,11 @@ void st_select_lex::init_query() /* Add the name resolution context of the current (sub)query to the stack of contexts for the whole query. + TODO: + push_context may return an error if there is no memory for a new + element in the stack, however this method has no return value, + thus push_context should be moved to a place where query + initialization is checked for failure. */ parent_lex->push_context(&context); cond_count= with_wild= 0; @@ -1139,6 +1147,7 @@ void st_select_lex::init_query() first_cond_optimization= 1; parsing_place= NO_MATTER; exclude_from_table_unique_test= no_wrap_view_item= FALSE; + nest_level= 0; link_next= 0; } @@ -1158,6 +1167,7 @@ void st_select_lex::init_select() interval_list.empty(); use_index.empty(); ftfunc_list_alloc.empty(); + inner_sum_func_list= 0; ftfunc_list= &ftfunc_list_alloc; linkage= UNSPECIFIED_TYPE; order_list.elements= 0; @@ -1526,9 +1536,9 @@ void st_select_lex_unit::print(String *str) { if (sl != first_select()) { - str->append(" union ", 7); + str->append(STRING_WITH_LEN(" union ")); if (union_all) - str->append("all ", 4); + str->append(STRING_WITH_LEN("all ")); else if (union_distinct == sl) union_all= TRUE; } @@ -1542,7 +1552,7 @@ void st_select_lex_unit::print(String *str) { if (fake_select_lex->order_list.elements) { - str->append(" order by ", 10); + str->append(STRING_WITH_LEN(" order by ")); fake_select_lex->print_order(str, (ORDER *) fake_select_lex-> order_list.first); @@ -1565,7 +1575,7 @@ void st_select_lex::print_order(String *str, ORDER *order) else (*order->item)->print(str); if (!order->asc) - str->append(" desc", 5); + str->append(STRING_WITH_LEN(" desc")); if (order->next) str->append(','); } @@ -1588,7 +1598,7 @@ void st_select_lex::print_limit(THD *thd, String *str) if (explicit_limit) { - str->append(" limit ", 7); + str->append(STRING_WITH_LEN(" limit ")); if (offset_limit) { offset_limit->print(str); @@ -2038,6 +2048,35 @@ void st_lex::cleanup_after_one_table_open() /* + Do end-of-prepare fixup for list of tables and their merge-VIEWed tables + + SYNOPSIS + fix_prepare_info_in_table_list() + thd Thread handle + tbl List of tables to process + + DESCRIPTION + Perform end-end-of prepare fixup for list of tables, if any of the tables + is a merge-algorithm VIEW, recursively fix up its underlying tables as + well. + +*/ + +static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl) +{ + for (; tbl; tbl= tbl->next_local) + { + if (tbl->on_expr) + { + tbl->prep_on_expr= tbl->on_expr; + tbl->on_expr= tbl->on_expr->copy_andor_structure(thd); + } + fix_prepare_info_in_table_list(thd, tbl->merge_underlying_list); + } +} + + +/* fix some structures at the end of preparation SYNOPSIS @@ -2056,16 +2095,7 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds) prep_where= *conds; *conds= where= prep_where->copy_andor_structure(thd); } - for (TABLE_LIST *tbl= (TABLE_LIST *)table_list.first; - tbl; - tbl= tbl->next_local) - { - if (tbl->on_expr) - { - tbl->prep_on_expr= tbl->on_expr; - tbl->on_expr= tbl->on_expr->copy_andor_structure(thd); - } - } + fix_prepare_info_in_table_list(thd, (TABLE_LIST *)table_list.first); } } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 1bf346eafb1..5ba47d768fb 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -90,6 +90,7 @@ enum enum_sql_command { SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER, SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE, SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER, + SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE, /* This should be the last !!! */ SQLCOM_END @@ -361,8 +362,8 @@ public: friend class st_select_lex_unit; friend bool mysql_new_select(struct st_lex *lex, bool move_down); - friend my_bool mysql_make_view (File_parser *parser, - TABLE_LIST *table); + friend bool mysql_make_view(THD *thd, File_parser *parser, + TABLE_LIST *table); private: void fast_exclude(); }; @@ -527,6 +528,8 @@ public: ulong table_join_options; uint in_sum_expr; uint select_number; /* number of select (used for EXPLAIN) */ + int nest_level; /* nesting level of select */ + Item_sum *inner_sum_func_list; /* list of sum func in nested selects */ uint with_wild; /* item list contain '*' */ bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */ /* TRUE when having fix field called in processing of this SELECT */ @@ -737,9 +740,14 @@ typedef struct st_lex TABLE_LIST **query_tables_last; /* store original leaf_tables for INSERT SELECT and PS/SP */ TABLE_LIST *leaf_tables_insert; - st_lex_user *create_view_definer; - char *create_view_start; - char *create_view_select_start; + /* Position (first character index) of SELECT of CREATE VIEW statement */ + uint create_view_select_start; + + /* + The definer of the object being created (view, trigger, stored routine). + I.e. the value of DEFINER clause. + */ + LEX_USER *definer; List<key_part_spec> col_list; List<key_part_spec> ref_list; @@ -770,12 +778,23 @@ typedef struct st_lex SQL_LIST proc_list, auxilliary_table_list, save_list; create_field *last_field; + Item_sum *in_sum_func; udf_func udf; HA_CHECK_OPT check_opt; // check/repair options HA_CREATE_INFO create_info; LEX_MASTER_INFO mi; // used by CHANGE MASTER USER_RESOURCES mqh; ulong type; + /* + This variable is used in post-parse stage to declare that sum-functions, + or functions which have sense only if GROUP BY is present, are allowed. + For example in a query + SELECT ... FROM ...WHERE MIN(i) == 1 GROUP BY ... HAVING MIN(i) > 2 + MIN(i) in the WHERE clause is not allowed in the opposite to MIN(i) + in the HAVING clause. Due to possible nesting of select construct + the variable can contain 0 or 1 for each nest level. + */ + nesting_map allow_sum_func; enum_sql_command sql_command, orig_sql_command; thr_lock_type lock_option; enum SSL_type ssl_type; /* defined in violite.h */ @@ -794,6 +813,7 @@ typedef struct st_lex uint grant, grant_tot_col, which_columns; uint fk_delete_opt, fk_update_opt, fk_match_option; uint slave_thd_opt, start_transaction_opt; + int nest_level; /* In LEX representing update which were transformed to multi-update stores total number of tables. For LEX representing multi-delete @@ -801,6 +821,11 @@ typedef struct st_lex */ uint table_count; uint8 describe; + /* + A flag that indicates what kinds of derived tables are present in the + query (0 if no derived tables, otherwise a combination of flags + DERIVED_SUBQUERY and DERIVED_VIEW). + */ uint8 derived_tables; uint8 create_view_algorithm; uint8 create_view_check; @@ -883,6 +908,14 @@ typedef struct st_lex SQL_LIST trg_table_fields; /* + trigger_definition_begin points to the beginning of the word "TRIGGER" in + CREATE TRIGGER statement. This is used to add possibly omitted DEFINER + clause to the trigger definition statement before dumping it to the + binlog. + */ + const char *trigger_definition_begin; + + /* If non-0 then indicates that query requires prelocking and points to next_global member of last own element in query table list (i.e. last table which was not added to it as part of preparation to prelocking). @@ -987,9 +1020,9 @@ typedef struct st_lex } void cleanup_after_one_table_open(); - void push_context(Name_resolution_context *context) + bool push_context(Name_resolution_context *context) { - context_stack.push_front(context); + return context_stack.push_front(context); } void pop_context() diff --git a/sql/sql_list.h b/sql/sql_list.h index 285f1d6e501..b2bcc4ea401 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -266,10 +266,21 @@ protected: ls.elements= elm; } public: - base_list_iterator(base_list &list_par) - :list(&list_par), el(&list_par.first), prev(0), current(0) + base_list_iterator() + :list(0), el(0), prev(0), current(0) {} + base_list_iterator(base_list &list_par) + { init(list_par); } + + inline void init(base_list &list_par) + { + list= &list_par; + el= &list_par.first; + prev= 0; + current= 0; + } + inline void *next(void) { prev=el; @@ -364,6 +375,8 @@ template <class T> class List_iterator :public base_list_iterator { public: List_iterator(List<T> &a) : base_list_iterator(a) {} + List_iterator() : base_list_iterator() {} + inline void init(List<T> &a) { base_list_iterator::init(a); } inline T* operator++(int) { return (T*) base_list_iterator::next(); } inline T *replace(T *a) { return (T*) base_list_iterator::replace(a); } inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); } @@ -385,6 +398,8 @@ protected: public: inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {} + inline List_iterator_fast() : base_list_iterator() {} + inline void init(List<T> &a) { base_list_iterator::init(a); } inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); } inline void rewind(void) { base_list_iterator::rewind(); } void sublist(List<T> &list_arg, uint el_arg) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index ff2be0ae6fb..4f3bfee5d3a 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -178,7 +178,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table is marked to be 'used for insert' in which case we should never mark this table as as 'const table' (ie, one that has only one row). */ - if (unique_table(table_list, table_list->next_global)) + if (unique_table(thd, table_list, table_list->next_global)) { my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name); DBUG_RETURN(TRUE); @@ -680,7 +680,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, length=(uint) (read_info.row_end-pos); if (!read_info.enclosed && - (enclosed_length && length == 4 && !memcmp(pos,"NULL",4)) || + (enclosed_length && length == 4 && + !memcmp(pos, STRING_WITH_LEN("NULL"))) || (length == 1 && read_info.found_null)) { if (item->type() == Item::FIELD_ITEM) @@ -1014,8 +1015,20 @@ int READ_INFO::read_field() *to++= (byte) escape_char; goto found_eof; } - *to++ = (byte) unescape((char) chr); - continue; + /* + When escape_char == enclosed_char, we treat it like we do for + handling quotes in SQL parsing -- you can double-up the + escape_char to include it literally, but it doesn't do escapes + like \n. This allows: LOAD DATA ... ENCLOSED BY '"' ESCAPED BY '"' + with data like: "fie""ld1", "field2" + */ + if (escape_char != enclosed_char || chr == escape_char) + { + *to++ = (byte) unescape((char) chr); + continue; + } + PUSH(chr); + chr= escape_char; } #ifdef ALLOW_LINESEPARATOR_IN_STRINGS if (chr == line_term_char) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 33020fccd8e..9cdb288c045 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -194,6 +194,18 @@ inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables) #endif +static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables) +{ + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + DBUG_ASSERT(table->db && table->table_name); + if (table->updating && + !find_temporary_table(thd, table->db, table->table_name)) + return 1; + } + return 0; +} + static HASH hash_user_connections; static int get_or_create_user_conn(THD *thd, const char *user, @@ -785,6 +797,9 @@ static int check_connection(THD *thd) DBUG_PRINT("info", ("New connection received on %s", vio_description(net->vio))); +#ifdef SIGNAL_WITH_VIO_CLOSE + thd->set_active_vio(net->vio); +#endif if (!thd->main_security_ctx.host) // If TCP/IP connection { @@ -1085,6 +1100,7 @@ pthread_handler_t handle_one_connection(void *arg) VOID(sigemptyset(&set)); // Get mask in use VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals)); #endif + thd->thread_stack= (char*) &thd; if (thd->store_globals()) { close_connection(thd, ER_OUT_OF_RESOURCES, 1); @@ -1098,7 +1114,6 @@ pthread_handler_t handle_one_connection(void *arg) int error; NET *net= &thd->net; Security_context *sctx= thd->security_ctx; - thd->thread_stack= (char*) &thd; net->no_send_error= 0; if ((error=check_connection(thd))) @@ -1170,6 +1185,7 @@ end_thread: or this thread has been schedule to handle the next query */ thd= current_thd; + thd->thread_stack= (char*) &thd; } while (!(test_flags & TEST_NO_THREADS)); /* The following is only executed if we are not using --one-thread */ return(0); /* purecov: deadcode */ @@ -1189,6 +1205,7 @@ pthread_handler_t handle_bootstrap(void *arg) char *buff; /* The following must be called before DBUG_ENTER */ + thd->thread_stack= (char*) &thd; if (my_thread_init() || thd->store_globals()) { #ifndef EMBEDDED_LIBRARY @@ -1767,6 +1784,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Saved variable value */ my_bool old_innodb_table_locks= IF_INNOBASE_DB(thd->variables.innodb_table_locks, FALSE); + /* used as fields initializator */ + lex_start(thd, 0, 0); statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS], @@ -2363,7 +2382,7 @@ mysql_execute_command(THD *thd) mysql_reset_errors(thd, 0); #ifdef HAVE_REPLICATION - if (thd->slave_thread) + if (unlikely(thd->slave_thread)) { /* Check if statment should be skipped because of slave filtering @@ -2389,29 +2408,21 @@ mysql_execute_command(THD *thd) reset_one_shot_variables(thd); DBUG_RETURN(0); } -#ifndef TO_BE_DELETED - /* - This is a workaround to deal with the shortcoming in 3.23.44-3.23.46 - masters in RELEASE_LOCK() logging. We re-write SELECT RELEASE_LOCK() - as DO RELEASE_LOCK() - */ - if (lex->sql_command == SQLCOM_SELECT) - { - lex->sql_command = SQLCOM_DO; - lex->insert_list = &select_lex->item_list; - } -#endif } + else #endif /* HAVE_REPLICATION */ /* - When option readonly is set deny operations which change tables. - Except for the replication thread and the 'super' users. + When option readonly is set deny operations which change non-temporary + tables. Except for the replication thread and the 'super' users. */ if (opt_readonly && - !(thd->slave_thread || - (thd->security_ctx->master_access & SUPER_ACL)) && - uc_update_queries[lex->sql_command]) + !(thd->security_ctx->master_access & SUPER_ACL) && + uc_update_queries[lex->sql_command] && + !((lex->sql_command == SQLCOM_CREATE_TABLE) && + (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) && + ((lex->sql_command != SQLCOM_UPDATE_MULTI) && + some_non_temp_table_to_be_updated(thd, all_tables))) { my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); DBUG_RETURN(-1); @@ -2607,7 +2618,8 @@ mysql_execute_command(THD *thd) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res = mysql_backup_table(thd, first_table); - + select_lex->table_list.first= (byte*) first_table; + lex->query_tables=all_tables; break; } case SQLCOM_RESTORE_TABLE: @@ -2619,6 +2631,8 @@ mysql_execute_command(THD *thd) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res = mysql_restore_table(thd, first_table); + select_lex->table_list.first= (byte*) first_table; + lex->query_tables=all_tables; break; } case SQLCOM_ASSIGN_TO_KEYCACHE: @@ -2822,7 +2836,7 @@ mysql_execute_command(THD *thd) if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) { TABLE_LIST *duplicate; - if ((duplicate= unique_table(create_table, select_tables))) + if ((duplicate= unique_table(thd, create_table, select_tables))) { update_non_unique_table_error(create_table, "CREATE", duplicate); res= 1; @@ -2838,7 +2852,7 @@ mysql_execute_command(THD *thd) tab= tab->next_local) { TABLE_LIST *duplicate; - if ((duplicate= unique_table(tab, select_tables))) + if ((duplicate= unique_table(thd, tab, select_tables))) { update_non_unique_table_error(tab, "CREATE", duplicate); res= 1; @@ -3121,6 +3135,8 @@ end_with_restore_list: mysql_bin_log.write(&qinfo); } } + select_lex->table_list.first= (byte*) first_table; + lex->query_tables=all_tables; break; } case SQLCOM_CHECK: @@ -3131,6 +3147,8 @@ end_with_restore_list: goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res = mysql_check_table(thd, first_table, &lex->check_opt); + select_lex->table_list.first= (byte*) first_table; + lex->query_tables=all_tables; break; } case SQLCOM_ANALYZE: @@ -3151,6 +3169,8 @@ end_with_restore_list: mysql_bin_log.write(&qinfo); } } + select_lex->table_list.first= (byte*) first_table; + lex->query_tables=all_tables; break; } @@ -3174,6 +3194,8 @@ end_with_restore_list: mysql_bin_log.write(&qinfo); } } + select_lex->table_list.first= (byte*) first_table; + lex->query_tables=all_tables; break; } case SQLCOM_UPDATE: @@ -3210,13 +3232,24 @@ end_with_restore_list: #ifdef HAVE_REPLICATION /* Check slave filtering rules */ - if (thd->slave_thread && all_tables_not_ok(thd, all_tables)) + if (unlikely(thd->slave_thread)) { - /* we warn the slave SQL thread */ - my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); - break; + if (all_tables_not_ok(thd, all_tables)) + { + /* we warn the slave SQL thread */ + my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); + break; + } } + else #endif /* HAVE_REPLICATION */ + if (opt_readonly && + !(thd->security_ctx->master_access & SUPER_ACL) && + some_non_temp_table_to_be_updated(thd, all_tables)) + { + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); + break; + } res= mysql_multi_update(thd, all_tables, &select_lex->item_list, @@ -3665,7 +3698,8 @@ end_with_restore_list: if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0)) break; #ifdef HAVE_DLOPEN - if (sp_find_function(thd, lex->spname)) + if (sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, + &thd->sp_func_cache, FALSE)) { my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str); goto error; @@ -4016,8 +4050,8 @@ end_with_restore_list: break; } case SQLCOM_SAVEPOINT: - if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) || - !opt_using_transactions) + if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) || + thd->in_sub_stmt) || !opt_using_transactions) send_ok(thd); else { @@ -4070,7 +4104,7 @@ end_with_restore_list: if (!lex->sphead->m_db.str || !lex->sphead->m_db.str[0]) { - if (! thd->db) + if (!thd->db) { my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); delete lex->sphead; @@ -4111,14 +4145,6 @@ end_with_restore_list: } } #endif - if (lex->sphead->m_type == TYPE_ENUM_FUNCTION && - !(lex->sphead->m_flags & sp_head::HAS_RETURN)) - { - my_error(ER_SP_NORETURN, MYF(0), name); - delete lex->sphead; - lex->sphead= 0; - goto error; - } /* We need to copy name and db in order to use them for @@ -4199,7 +4225,8 @@ end_with_restore_list: By this moment all needed SPs should be in cache so no need to look into DB. */ - if (!(sp= sp_find_procedure(thd, lex->spname, TRUE))) + if (!(sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname, + &thd->sp_proc_cache, TRUE))) { my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE", lex->spname->m_qname.str); @@ -4289,18 +4316,6 @@ end_with_restore_list: So just execute the statement. */ res= sp->execute_procedure(thd, &lex->value_list); - if (mysql_bin_log.is_open() && - (sp->m_chistics->daccess == SP_CONTAINS_SQL || - sp->m_chistics->daccess == SP_MODIFIES_SQL_DATA)) - { - if (res) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_FAILED_ROUTINE_BREAK_BINLOG, - ER(ER_FAILED_ROUTINE_BREAK_BINLOG)); - else - thd->clear_error(); - } - /* If warnings have been cleared, we have to clear total_warn_count too, otherwise the clients get confused. @@ -4335,9 +4350,11 @@ end_with_restore_list: memcpy(&chistics, &lex->sp_chistics, sizeof(chistics)); if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) - sp= sp_find_procedure(thd, lex->spname); + sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname, + &thd->sp_proc_cache, FALSE); else - sp= sp_find_function(thd, lex->spname); + sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, + &thd->sp_func_cache, FALSE); mysql_reset_errors(thd, 0); if (! sp) { @@ -4359,7 +4376,8 @@ end_with_restore_list: if (end_active_trans(thd)) goto error; memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics)); - if (!trust_routine_creators && mysql_bin_log.is_open() && + if ((sp->m_type == TYPE_ENUM_FUNCTION) && + !trust_function_creators && mysql_bin_log.is_open() && !sp->m_chistics->detistic && (chistics.daccess == SP_CONTAINS_SQL || chistics.daccess == SP_MODIFIES_SQL_DATA)) @@ -4370,6 +4388,12 @@ end_with_restore_list: } else { + /* + Note that if you implement the capability of ALTER FUNCTION to + alter the body of the function, this command should be made to + follow the restrictions that log-bin-trust-function-creators=0 + already puts on CREATE FUNCTION. + */ if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics); else @@ -4406,9 +4430,11 @@ end_with_restore_list: char *db, *name; if (lex->sql_command == SQLCOM_DROP_PROCEDURE) - sp= sp_find_procedure(thd, lex->spname); + sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname, + &thd->sp_proc_cache, FALSE); else - sp= sp_find_function(thd, lex->spname); + sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, + &thd->sp_func_cache, FALSE); mysql_reset_errors(thd, 0); if (sp) { @@ -4536,6 +4562,33 @@ end_with_restore_list: lex->wild->ptr() : NullS)); break; } +#ifndef DBUG_OFF + case SQLCOM_SHOW_PROC_CODE: + case SQLCOM_SHOW_FUNC_CODE: + { + sp_head *sp; + + if (lex->spname->m_name.length > NAME_LEN) + { + my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str); + goto error; + } + if (lex->sql_command == SQLCOM_SHOW_PROC_CODE) + sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname, + &thd->sp_proc_cache, FALSE); + else + sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, + &thd->sp_func_cache, FALSE); + if (!sp || !sp->show_routine_code(thd)) + { + /* We don't distinguish between errors for now */ + my_error(ER_SP_DOES_NOT_EXIST, MYF(0), + SP_COM_STRING(lex), lex->spname->m_name.str); + goto error; + } + break; + } +#endif // ifndef DBUG_OFF case SQLCOM_CREATE_VIEW: { if (end_active_trans(thd)) @@ -4554,7 +4607,7 @@ end_with_restore_list: buff.append(command[thd->lex->create_view_mode].str, command[thd->lex->create_view_mode].length); view_store_options(thd, first_table, &buff); - buff.append("VIEW ", 5); + buff.append(STRING_WITH_LEN("VIEW ")); /* Test if user supplied a db (ie: we did not use thd->db) */ if (first_table->db != thd->db && first_table->db[0]) { @@ -4564,7 +4617,7 @@ end_with_restore_list: } append_identifier(thd, &buff, first_table->table_name, first_table->table_name_length); - buff.append(" AS ", 4); + buff.append(STRING_WITH_LEN(" AS ")); buff.append(first_table->source.str, first_table->source.length); Query_log_event qinfo(thd, buff.ptr(), buff.length(), 0, FALSE); @@ -4796,21 +4849,21 @@ end_with_restore_list: if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION) reset_one_shot_variables(thd); - /* - The return value for ROW_COUNT() is "implementation dependent" if - the statement is not DELETE, INSERT or UPDATE (or a CALL executing - such a statement), but -1 is what JDBC and ODBC wants. + The return value for ROW_COUNT() is "implementation dependent" if the + statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC + wants. + + We do not change the value for a CALL or EXECUTE statement, so the value + generated by the last called (or executed) statement is preserved. */ - if (lex->sql_command != SQLCOM_CALL && uc_update_queries[lex->sql_command]<2) + if (lex->sql_command != SQLCOM_CALL && lex->sql_command != SQLCOM_EXECUTE && + uc_update_queries[lex->sql_command]<2) thd->row_count_func= -1; - goto cleanup; + DBUG_RETURN(res || thd->net.report_error); error: - res= 1; - -cleanup: - DBUG_RETURN(res || thd->net.report_error); + DBUG_RETURN(1); } @@ -5026,8 +5079,14 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, { uint found=0; ulong found_access=0; - TABLE_LIST *org_tables=tables; - for (; tables; tables= tables->next_global) + TABLE_LIST *org_tables= tables; + TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table(); + /* + The check that first_not_own_table is not reached is for the case when + the given table list refers to the list for prelocking (contains tables + of other queries). For simple queries first_not_own_table is 0. + */ + for (; tables != first_not_own_table; tables= tables->next_global) { if (tables->schema_table && (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL))) @@ -5038,6 +5097,11 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, information_schema_name.str); return TRUE; } + /* + Register access for view underlying table. + Remove SHOW_VIEW_ACL, because it will be checked during making view + */ + tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); if (tables->derived || tables->schema_table || tables->belong_to_view || (tables->table && (int)tables->table->s->tmp_table) || my_tz_check_n_skip_implicit_tables(&tables, @@ -5232,6 +5296,7 @@ bool check_stack_overrun(THD *thd, long margin, char *buf __attribute__((unused))) { long stack_used; + DBUG_ASSERT(thd == current_thd); if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >= (long) (thread_stack - margin)) { @@ -5362,6 +5427,8 @@ mysql_new_select(LEX *lex, bool move_down) select_lex->parent_lex= lex; /* Used in init_query. */ select_lex->init_query(); select_lex->init_select(); + lex->nest_level++; + select_lex->nest_level= lex->nest_level; /* Don't evaluate this subquery during statement prepare even if it's a constant one. The flag is switched off in the end of @@ -5702,9 +5769,10 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, buf, "TIMESTAMP"); } - if (!(new_field= new_create_field(thd, field_name, type, length, decimals, - type_modifier, default_value, on_update_value, - comment, change, interval_list, cs, uint_geom_type))) + if (!(new_field= new create_field()) || + new_field->init(thd, field_name, type, length, decimals, type_modifier, + default_value, on_update_value, comment, change, + interval_list, cs, uint_geom_type)) DBUG_RETURN(1); lex->create_list.push_back(new_field); @@ -5712,327 +5780,6 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, DBUG_RETURN(0); } -/***************************************************************************** -** Create field definition for create -** Return 0 on failure, otherwise return create_field instance -******************************************************************************/ - -create_field * -new_create_field(THD *thd, char *field_name, enum_field_types type, - char *length, char *decimals, - uint type_modifier, - Item *default_value, Item *on_update_value, - LEX_STRING *comment, - char *change, List<String> *interval_list, CHARSET_INFO *cs, - uint uint_geom_type) -{ - register create_field *new_field; - uint sign_len, allowed_type_modifier=0; - ulong max_field_charlength= MAX_FIELD_CHARLENGTH; - DBUG_ENTER("new_create_field"); - - if (!(new_field=new create_field())) - DBUG_RETURN(NULL); - new_field->field=0; - new_field->field_name=field_name; - new_field->def= default_value; - new_field->flags= type_modifier; - new_field->unireg_check= (type_modifier & AUTO_INCREMENT_FLAG ? - Field::NEXT_NUMBER : Field::NONE); - new_field->decimals= decimals ? (uint)atoi(decimals) : 0; - if (new_field->decimals >= NOT_FIXED_DEC) - { - my_error(ER_TOO_BIG_SCALE, MYF(0), new_field->decimals, field_name, - NOT_FIXED_DEC-1); - DBUG_RETURN(NULL); - } - - new_field->sql_type=type; - new_field->length=0; - new_field->change=change; - new_field->interval=0; - new_field->pack_length= new_field->key_length= 0; - new_field->charset=cs; - new_field->geom_type= (Field::geometry_type) uint_geom_type; - - new_field->comment=*comment; - /* - Set flag if this field doesn't have a default value - */ - if (!default_value && !(type_modifier & AUTO_INCREMENT_FLAG) && - (type_modifier & NOT_NULL_FLAG) && type != FIELD_TYPE_TIMESTAMP) - new_field->flags|= NO_DEFAULT_VALUE_FLAG; - - if (length && !(new_field->length= (uint) atoi(length))) - length=0; /* purecov: inspected */ - sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1; - - switch (type) { - case FIELD_TYPE_TINY: - if (!length) new_field->length=MAX_TINYINT_WIDTH+sign_len; - allowed_type_modifier= AUTO_INCREMENT_FLAG; - break; - case FIELD_TYPE_SHORT: - if (!length) new_field->length=MAX_SMALLINT_WIDTH+sign_len; - allowed_type_modifier= AUTO_INCREMENT_FLAG; - break; - case FIELD_TYPE_INT24: - if (!length) new_field->length=MAX_MEDIUMINT_WIDTH+sign_len; - allowed_type_modifier= AUTO_INCREMENT_FLAG; - break; - case FIELD_TYPE_LONG: - if (!length) new_field->length=MAX_INT_WIDTH+sign_len; - allowed_type_modifier= AUTO_INCREMENT_FLAG; - break; - case FIELD_TYPE_LONGLONG: - if (!length) new_field->length=MAX_BIGINT_WIDTH; - allowed_type_modifier= AUTO_INCREMENT_FLAG; - break; - case FIELD_TYPE_NULL: - break; - case FIELD_TYPE_NEWDECIMAL: - if (!length && !new_field->decimals) - new_field->length= 10; - if (new_field->length > DECIMAL_MAX_PRECISION) - { - my_error(ER_TOO_BIG_PRECISION, MYF(0), new_field->length, field_name, - DECIMAL_MAX_PRECISION); - DBUG_RETURN(NULL); - } - if (new_field->length < new_field->decimals) - { - my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name); - DBUG_RETURN(NULL); - } - new_field->length= - my_decimal_precision_to_length(new_field->length, new_field->decimals, - type_modifier & UNSIGNED_FLAG); - new_field->pack_length= - my_decimal_get_binary_size(new_field->length, new_field->decimals); - break; - case MYSQL_TYPE_VARCHAR: - /* - Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table - if they don't have a default value - */ - max_field_charlength= MAX_FIELD_VARCHARLENGTH; - break; - case MYSQL_TYPE_STRING: - break; - case FIELD_TYPE_BLOB: - case FIELD_TYPE_TINY_BLOB: - case FIELD_TYPE_LONG_BLOB: - case FIELD_TYPE_MEDIUM_BLOB: - case FIELD_TYPE_GEOMETRY: - if (default_value) // Allow empty as default value - { - String str,*res; - res=default_value->val_str(&str); - if (res->length()) - { - my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), - field_name); /* purecov: inspected */ - DBUG_RETURN(NULL); - } - new_field->def=0; - } - new_field->flags|=BLOB_FLAG; - break; - case FIELD_TYPE_YEAR: - if (!length || new_field->length != 2) - new_field->length=4; // Default length - new_field->flags|= ZEROFILL_FLAG | UNSIGNED_FLAG; - break; - case FIELD_TYPE_FLOAT: - /* change FLOAT(precision) to FLOAT or DOUBLE */ - allowed_type_modifier= AUTO_INCREMENT_FLAG; - if (length && !decimals) - { - uint tmp_length=new_field->length; - if (tmp_length > PRECISION_FOR_DOUBLE) - { - my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name); - DBUG_RETURN(NULL); - } - else if (tmp_length > PRECISION_FOR_FLOAT) - { - new_field->sql_type=FIELD_TYPE_DOUBLE; - new_field->length=DBL_DIG+7; // -[digits].E+### - } - else - new_field->length=FLT_DIG+6; // -[digits].E+## - new_field->decimals= NOT_FIXED_DEC; - break; - } - if (!length && !decimals) - { - new_field->length = FLT_DIG+6; - new_field->decimals= NOT_FIXED_DEC; - } - if (new_field->length < new_field->decimals && - new_field->decimals != NOT_FIXED_DEC) - { - my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name); - DBUG_RETURN(NULL); - } - break; - case FIELD_TYPE_DOUBLE: - allowed_type_modifier= AUTO_INCREMENT_FLAG; - if (!length && !decimals) - { - new_field->length = DBL_DIG+7; - new_field->decimals=NOT_FIXED_DEC; - } - if (new_field->length < new_field->decimals && - new_field->decimals != NOT_FIXED_DEC) - { - my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name); - DBUG_RETURN(NULL); - } - break; - case FIELD_TYPE_TIMESTAMP: - if (!length) - new_field->length= 14; // Full date YYYYMMDDHHMMSS - else if (new_field->length != 19) - { - /* - We support only even TIMESTAMP lengths less or equal than 14 - and 19 as length of 4.1 compatible representation. - */ - new_field->length=((new_field->length+1)/2)*2; /* purecov: inspected */ - new_field->length= min(new_field->length,14); /* purecov: inspected */ - } - new_field->flags|= ZEROFILL_FLAG | UNSIGNED_FLAG; - if (default_value) - { - /* Grammar allows only NOW() value for ON UPDATE clause */ - if (default_value->type() == Item::FUNC_ITEM && - ((Item_func*)default_value)->functype() == Item_func::NOW_FUNC) - { - new_field->unireg_check= (on_update_value?Field::TIMESTAMP_DNUN_FIELD: - Field::TIMESTAMP_DN_FIELD); - /* - We don't need default value any longer moreover it is dangerous. - Everything handled by unireg_check further. - */ - new_field->def= 0; - } - else - new_field->unireg_check= (on_update_value?Field::TIMESTAMP_UN_FIELD: - Field::NONE); - } - else - { - /* - If we have default TIMESTAMP NOT NULL column without explicit DEFAULT - or ON UPDATE values then for the sake of compatiblity we should treat - this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't - have another TIMESTAMP column with auto-set option before this one) - or DEFAULT 0 (in other cases). - So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will - replace this value by TIMESTAMP_DNUN_FIELD or NONE later when - information about all TIMESTAMP fields in table will be availiable. - - If we have TIMESTAMP NULL column without explicit DEFAULT value - we treat it as having DEFAULT NULL attribute. - */ - new_field->unireg_check= (on_update_value ? - Field::TIMESTAMP_UN_FIELD : - (new_field->flags & NOT_NULL_FLAG ? - Field::TIMESTAMP_OLD_FIELD: - Field::NONE)); - } - break; - case FIELD_TYPE_DATE: // Old date type - if (protocol_version != PROTOCOL_VERSION-1) - new_field->sql_type=FIELD_TYPE_NEWDATE; - /* fall trough */ - case FIELD_TYPE_NEWDATE: - new_field->length=10; - break; - case FIELD_TYPE_TIME: - new_field->length=10; - break; - case FIELD_TYPE_DATETIME: - new_field->length=19; - break; - case FIELD_TYPE_SET: - { - if (interval_list->elements > sizeof(longlong)*8) - { - my_error(ER_TOO_BIG_SET, MYF(0), field_name); /* purecov: inspected */ - DBUG_RETURN(NULL); - } - new_field->pack_length= get_set_pack_length(interval_list->elements); - - List_iterator<String> it(*interval_list); - String *tmp; - while ((tmp= it++)) - new_field->interval_list.push_back(tmp); - /* - Set fake length to 1 to pass the below conditions. - Real length will be set in mysql_prepare_table() - when we know the character set of the column - */ - new_field->length= 1; - break; - } - case FIELD_TYPE_ENUM: - { - // Should be safe - new_field->pack_length= get_enum_pack_length(interval_list->elements); - - List_iterator<String> it(*interval_list); - String *tmp; - while ((tmp= it++)) - new_field->interval_list.push_back(tmp); - new_field->length= 1; // See comment for FIELD_TYPE_SET above. - break; - } - case MYSQL_TYPE_VAR_STRING: - DBUG_ASSERT(0); // Impossible - break; - case MYSQL_TYPE_BIT: - { - if (!length) - new_field->length= 1; - if (new_field->length > MAX_BIT_FIELD_LENGTH) - { - my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name, - MAX_BIT_FIELD_LENGTH); - DBUG_RETURN(NULL); - } - new_field->pack_length= (new_field->length + 7) / 8; - break; - } - case FIELD_TYPE_DECIMAL: - DBUG_ASSERT(0); /* Was obsolete */ - } - - if (!(new_field->flags & BLOB_FLAG) && - ((new_field->length > max_field_charlength && type != FIELD_TYPE_SET && - type != FIELD_TYPE_ENUM && - (type != MYSQL_TYPE_VARCHAR || default_value)) || - (!new_field->length && - type != MYSQL_TYPE_STRING && - type != MYSQL_TYPE_VARCHAR && type != FIELD_TYPE_GEOMETRY))) - { - my_error((type == MYSQL_TYPE_VAR_STRING || type == MYSQL_TYPE_VARCHAR || - type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH : - ER_TOO_BIG_DISPLAYWIDTH, - MYF(0), - field_name, max_field_charlength); /* purecov: inspected */ - DBUG_RETURN(NULL); - } - type_modifier&= AUTO_INCREMENT_FLAG; - if ((~allowed_type_modifier) & type_modifier) - { - my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name); - DBUG_RETURN(NULL); - } - DBUG_RETURN(new_field); -} - /* Store position for column in ALTER TABLE .. ADD column */ @@ -6526,36 +6273,39 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type) /* - Create a new name resolution context for a JOIN ... ON clause. + Push a new name resolution context for a JOIN ... ON clause to the + context stack of a query block. SYNOPSIS - make_join_on_context() + push_new_name_resolution_context() thd pointer to current thread left_op left operand of the JOIN right_op rigth operand of the JOIN DESCRIPTION Create a new name resolution context for a JOIN ... ON clause, - and set the first and last leaves of the list of table references - to be used for name resolution. + set the first and last leaves of the list of table references + to be used for name resolution, and push the newly created + context to the stack of contexts of the query. RETURN - A new context if all is OK - NULL - if a memory allocation error occured + FALSE if all is OK + TRUE if a memory allocation error occured */ -Name_resolution_context * -make_join_on_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op) +bool +push_new_name_resolution_context(THD *thd, + TABLE_LIST *left_op, TABLE_LIST *right_op) { Name_resolution_context *on_context; if (!(on_context= new (thd->mem_root) Name_resolution_context)) - return NULL; + return TRUE; on_context->init(); on_context->first_name_resolution_table= left_op->first_leaf_for_name_resolution(); on_context->last_name_resolution_table= right_op->last_leaf_for_name_resolution(); - return on_context; + return thd->lex->push_context(on_context); } @@ -6681,7 +6431,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, allocate temporary THD for execution of acl_reload()/grant_reload(). */ if (!thd && (thd= (tmp_thd= new THD))) + { + thd->thread_stack= (char*) &tmp_thd; thd->store_globals(); + } if (thd) { (void)acl_reload(thd); @@ -7426,32 +7179,81 @@ Item *negate_expression(THD *thd, Item *expr) return new Item_func_not(expr); } +/* + Set the specified definer to the default value, which is the current user in + the thread. Also check that the current user satisfies to the definers + requirements. + + SYNOPSIS + get_default_definer() + thd [in] thread handler + definer [out] definer + + RETURN + error status, that is: + - FALSE -- on success; + - TRUE -- on error (current user can not be a definer). +*/ + +bool get_default_definer(THD *thd, LEX_USER *definer) +{ + /* Check that current user has non-empty host name. */ + + const Security_context *sctx= thd->security_ctx; + + if (sctx->priv_host[0] == 0) + { + my_error(ER_MALFORMED_DEFINER, MYF(0)); + return TRUE; + } + + /* Fill in. */ + + definer->user.str= (char *) sctx->priv_user; + definer->user.length= strlen(definer->user.str); + + definer->host.str= (char *) sctx->priv_host; + definer->host.length= strlen(definer->host.str); + + return FALSE; +} + /* - Assign as view definer current user + Create definer with the given user and host names. Also check that the user + and host names satisfy definers requirements. SYNOPSIS - default_view_definer() - sctx current security context - definer structure where it should be assigned + create_definer() + thd [in] thread handler + user_name [in] user name + host_name [in] host name RETURN - FALSE OK - TRUE Error + On success, return a valid pointer to the created and initialized + LEX_STRING, which contains definer information. + On error, return 0. */ -bool default_view_definer(Security_context *sctx, st_lex_user *definer) +LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) { - definer->user.str= sctx->priv_user; - definer->user.length= strlen(sctx->priv_user); + LEX_USER *definer; - if (!*sctx->priv_host) + /* Check that specified host name is valid. */ + + if (host_name->length == 0) { - my_error(ER_NO_VIEW_USER, MYF(0)); - return TRUE; + my_error(ER_MALFORMED_DEFINER, MYF(0)); + return 0; } - definer->host.str= sctx->priv_host; - definer->host.length= strlen(sctx->priv_host); - return FALSE; + /* Create and initialize. */ + + if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) + return 0; + + definer->user= *user_name; + definer->host= *host_name; + + return definer; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 865c597e00d..ffbbf0c6476 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1158,6 +1158,7 @@ static int mysql_test_update(Prepared_statement *stmt, #ifndef NO_EMBEDDED_ACCESS_CHECKS table_list->grant.want_privilege= want_privilege; table_list->table->grant.want_privilege= want_privilege; + table_list->register_want_access(want_privilege); #endif thd->lex->select_lex.no_wrap_view_item= TRUE; res= setup_fields(thd, 0, select->item_list, 1, 0, 0); @@ -1169,6 +1170,7 @@ static int mysql_test_update(Prepared_statement *stmt, table_list->grant.want_privilege= table_list->table->grant.want_privilege= (SELECT_ACL & ~table_list->table->grant.privilege); + table_list->register_want_access(SELECT_ACL); #endif if (setup_fields(thd, 0, stmt->lex->value_list, 0, 0, 0)) goto error; @@ -1825,13 +1827,16 @@ static bool init_param_array(Prepared_statement *stmt) void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length) { - Prepared_statement *stmt= new Prepared_statement(thd, &thd->protocol_prep); + Prepared_statement *stmt; bool error; DBUG_ENTER("mysql_stmt_prepare"); DBUG_PRINT("prep_query", ("%s", packet)); - if (stmt == 0) + /* First of all clear possible warnings from the previous command */ + mysql_reset_thd_for_next_command(thd); + + if (! (stmt= new Prepared_statement(thd, &thd->protocol_prep))) DBUG_VOID_RETURN; /* out of memory: error is set in Sql_alloc */ if (thd->stmt_map.insert(stmt)) @@ -1840,7 +1845,6 @@ void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length) DBUG_VOID_RETURN; /* out of memory */ } - mysql_reset_thd_for_next_command(thd); /* Reset warnings from previous command */ mysql_reset_errors(thd, 0); sp_cache_flush_obsolete(&thd->sp_proc_cache); @@ -1925,7 +1929,7 @@ static const char *get_dynamic_sql_string(LEX *lex, uint *query_len) variable absent or equal to NULL, so we need to set variable to something reasonable to get a readable error message during parsing */ - str.set("NULL", 4, &my_charset_latin1); + str.set(STRING_WITH_LEN("NULL"), &my_charset_latin1); } needs_conversion= String::needs_conversion(var_value->length(), @@ -2107,8 +2111,6 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) were closed in the end of previous prepare or execute call. */ tables->table= 0; - if (tables->nested_join) - tables->nested_join->counter= 0; if (tables->prep_on_expr) { @@ -2127,7 +2129,8 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) lex->result->cleanup(); lex->result->set_thd(thd); } - thd->allow_sum_func= 0; + lex->allow_sum_func= 0; + lex->in_sum_func= NULL; DBUG_VOID_RETURN; } @@ -2170,8 +2173,9 @@ static void reset_stmt_params(Prepared_statement *stmt) client, otherwise an error message is set in THD. */ -void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) +void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length) { + uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround ulong stmt_id= uint4korr(packet); ulong flags= (ulong) ((uchar) packet[4]); /* Query text for binary, general or slow log, if any of them is open */ @@ -2185,13 +2189,15 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) packet+= 9; /* stmt_id + 5 bytes of flags */ + /* First of all clear possible warnings from the previous command */ + mysql_reset_thd_for_next_command(thd); + if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute"))) DBUG_VOID_RETURN; DBUG_PRINT("exec_query", ("%s", stmt->query)); DBUG_PRINT("info",("stmt: %p", stmt)); - mysql_reset_thd_for_next_command(thd); sp_cache_flush_obsolete(&thd->sp_proc_cache); sp_cache_flush_obsolete(&thd->sp_func_cache); @@ -2311,6 +2317,8 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) Server_side_cursor *cursor; DBUG_ENTER("mysql_stmt_fetch"); + /* First of all clear possible warnings from the previous command */ + mysql_reset_thd_for_next_command(thd); statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch"))) DBUG_VOID_RETURN; @@ -2372,6 +2380,9 @@ void mysql_stmt_reset(THD *thd, char *packet) Prepared_statement *stmt; DBUG_ENTER("mysql_stmt_reset"); + /* First of all clear possible warnings from the previous command */ + mysql_reset_thd_for_next_command(thd); + statistic_increment(thd->status_var.com_stmt_reset, &LOCK_status); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset"))) DBUG_VOID_RETURN; @@ -2386,7 +2397,6 @@ void mysql_stmt_reset(THD *thd, char *packet) stmt->state= Query_arena::PREPARED; - mysql_reset_thd_for_next_command(thd); send_ok(thd); DBUG_VOID_RETURN; diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 154e828b47e..80fcb973028 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -134,6 +134,8 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error) { TABLE_LIST *ren_table,*new_table; frm_type_enum frm_type; + db_type table_type; + DBUG_ENTER("rename_tables"); for (ren_table= table_list; ren_table; ren_table= new_table->next_local) @@ -166,13 +168,12 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error) reg_ext); unpack_filename(name, name); - frm_type= mysql_frm_type(name); + frm_type= mysql_frm_type(thd, name, &table_type); switch (frm_type) { case FRMTYPE_TABLE: { - db_type table_type; - if ((table_type= get_table_type(thd, name)) == DB_TYPE_UNKNOWN) + if (table_type == DB_TYPE_UNKNOWN) my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno); else rc= mysql_rename_table(table_type, ren_table->db, old_alias, diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index b5865fa8816..cd293fc21c7 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -372,11 +372,6 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, goto err; } - /* - Call readers_addref before opening log to track count - of binlog readers - */ - mysql_bin_log.readers_addref(); if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0) { my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; @@ -574,8 +569,7 @@ impossible position"; goto err; if (!(flags & BINLOG_DUMP_NON_BLOCK) && - mysql_bin_log.is_active(log_file_name) && - !mysql_bin_log.is_reset_pending()) + mysql_bin_log.is_active(log_file_name)) { /* Block until there is more data in the log @@ -688,13 +682,7 @@ impossible position"; else { bool loop_breaker = 0; - // need this to break out of the for loop from switch - - // if we are going to switch log file anyway, close current log first - end_io_cache(&log); - (void) my_close(file, MYF(MY_WME)); - // decrease reference count of binlog readers - mysql_bin_log.readers_release(); + /* need this to break out of the for loop from switch */ thd->proc_info = "Finished reading one binlog; switching to next binlog"; switch (mysql_bin_log.find_next_log(&linfo, 1)) { @@ -704,25 +692,16 @@ impossible position"; case 0: break; default: - // need following call to do release on err label - mysql_bin_log.readers_addref(); errmsg = "could not find next log"; my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; goto err; } - if (loop_breaker) - { - // need following call to do release on end label - mysql_bin_log.readers_addref(); - break; - } - - /* - Call readers_addref before opening log to track count - of binlog readers - */ - mysql_bin_log.readers_addref(); + if (loop_breaker) + break; + + end_io_cache(&log); + (void) my_close(file, MYF(MY_WME)); /* Call fake_rotate_event() in case the previous log (the one which @@ -755,8 +734,6 @@ end: end_io_cache(&log); (void)my_close(file, MYF(MY_WME)); - // decrease reference count of binlog readers - mysql_bin_log.readers_release(); send_eof(thd); thd->proc_info = "Waiting to finalize termination"; @@ -783,8 +760,6 @@ err: pthread_mutex_unlock(&LOCK_thread_count); if (file >= 0) (void) my_close(file, MYF(MY_WME)); - // decrease reference count of binlog readers - mysql_bin_log.readers_release(); my_message(my_errno, errmsg, MYF(0)); DBUG_VOID_RETURN; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 97d5bf4e1d5..ad6375290cd 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -98,12 +98,16 @@ static COND* substitute_for_best_equal_field(COND *cond, void *table_join_idx); static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top); +static bool check_interleaving_with_nj(JOIN_TAB *last, JOIN_TAB *next); +static void restore_prev_nj_state(JOIN_TAB *last); +static void reset_nj_counters(List<TABLE_LIST> *join_list); +static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list, + uint first_unused); + static COND *optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list, Item::cond_result *cond_value); static bool resolve_nested_join (TABLE_LIST *table); -static COND *remove_eq_conds(THD *thd, COND *cond, - Item::cond_result *cond_value); static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item); static bool open_tmp_table(TABLE *table); static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, @@ -270,21 +274,20 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array, ORDER *order, ORDER *group, bool *hidden_group_fields) { - bool save_allow_sum_func; int res; + nesting_map save_allow_sum_func=thd->lex->allow_sum_func ; DBUG_ENTER("setup_without_group"); - save_allow_sum_func= thd->allow_sum_func; - thd->allow_sum_func= 0; + thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level); res= setup_conds(thd, tables, leaves, conds); - thd->allow_sum_func= save_allow_sum_func; + thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields, order); - thd->allow_sum_func= 0; + thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level); res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields, group, hidden_group_fields); - thd->allow_sum_func= save_allow_sum_func; + thd->lex->allow_sum_func= save_allow_sum_func; DBUG_RETURN(res); } @@ -351,8 +354,9 @@ JOIN::prepare(Item ***rref_pointer_array, if (having) { + nesting_map save_allow_sum_func= thd->lex->allow_sum_func; thd->where="having clause"; - thd->allow_sum_func=1; + thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level; select_lex->having_fix_field= 1; bool having_fix_rc= (!having->fixed && (having->fix_fields(thd, &having) || @@ -362,6 +366,18 @@ JOIN::prepare(Item ***rref_pointer_array, DBUG_RETURN(-1); /* purecov: inspected */ if (having->with_sum_func) having->split_sum_func(thd, ref_pointer_array, all_fields); + thd->lex->allow_sum_func= save_allow_sum_func; + } + if (select_lex->inner_sum_func_list) + { + Item_sum *end=select_lex->inner_sum_func_list; + Item_sum *item_sum= end; + do + { + item_sum= item_sum->next; + item_sum->split_sum_func2(thd, ref_pointer_array, + all_fields, item_sum->ref_by, FALSE); + } while (item_sum != end); } if (!thd->lex->view_prepare_mode) @@ -522,12 +538,14 @@ bool JOIN::test_in_subselect(Item **where) return 0; } + /* global select optimisation. return 0 - success 1 - error error code saved in field 'error' */ + int JOIN::optimize() { @@ -590,6 +608,7 @@ JOIN::optimize() /* Convert all outer joins to inner joins if possible */ conds= simplify_joins(this, join_list, conds, TRUE); + build_bitmap_for_nested_joins(join_list, 0); sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0; @@ -702,7 +721,8 @@ JOIN::optimize() DBUG_PRINT("error",("Error: make_select() failed")); DBUG_RETURN(1); } - + + reset_nj_counters(join_list); make_outerjoin_info(this); /* @@ -825,6 +845,7 @@ JOIN::optimize() { order=0; // The output has only one row simple_order=1; + select_distinct= 0; // No need in distinct for 1 row } calc_group_buffer(this, group_list); @@ -998,6 +1019,20 @@ JOIN::optimize() } having= 0; + /* + The loose index scan access method guarantees that all grouping or + duplicate row elimination (for distinct) is already performed + during data retrieval, and that all MIN/MAX functions are already + computed for each group. Thus all MIN/MAX functions should be + treated as regular functions, and there is no need to perform + grouping in the main execution loop. + Notice that currently loose index scan is applicable only for + single table queries, thus it is sufficient to test only the first + join_tab element of the plan for its access method. + */ + if (join_tab->is_using_loose_index_scan()) + tmp_table_param.precomputed_group_by= TRUE; + /* Create a tmp table if distinct or if the sort is too complicated */ if (need_tmp) { @@ -1174,18 +1209,21 @@ JOIN::save_join_tab() void JOIN::exec() { + List<Item> *columns_list= &fields_list; int tmp_error; DBUG_ENTER("JOIN::exec"); error= 0; if (procedure) { - if (procedure->change_columns(fields_list) || - result->prepare(fields_list, unit)) + procedure_fields_list= fields_list; + if (procedure->change_columns(procedure_fields_list) || + result->prepare(procedure_fields_list, unit)) { thd->limit_found_rows= thd->examined_row_count= 0; DBUG_VOID_RETURN; } + columns_list= &procedure_fields_list; } (void) result->prepare2(); // Currently, this cannot fail. @@ -1196,7 +1234,7 @@ JOIN::exec() (zero_result_cause?zero_result_cause:"No tables used")); else { - result->send_fields(fields_list, + result->send_fields(*columns_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); /* We have to test for 'conds' here as the WHERE may not be constant @@ -1207,9 +1245,9 @@ JOIN::exec() (!conds || conds->val_int()) && (!having || having->val_int())) { - if (do_send_rows && (procedure ? (procedure->send_row(fields_list) || - procedure->end_of_records()) - : result->send_data(fields_list))) + if (do_send_rows && + (procedure ? (procedure->send_row(procedure_fields_list) || + procedure->end_of_records()) : result->send_data(fields_list))) error= 1; else { @@ -1233,7 +1271,8 @@ JOIN::exec() if (zero_result_cause) { - (void) return_zero_rows(this, result, select_lex->leaf_tables, fields_list, + (void) return_zero_rows(this, result, select_lex->leaf_tables, + *columns_list, send_row_on_empty_set(), select_options, zero_result_cause, @@ -1397,6 +1436,15 @@ JOIN::exec() else { /* group data to new table */ + + /* + If the access method is loose index scan then all MIN/MAX + functions are precomputed, and should be treated as regular + functions. See extended comment in JOIN::exec. + */ + if (curr_join->join_tab->is_using_loose_index_scan()) + curr_join->tmp_table_param.precomputed_group_by= TRUE; + if (!(curr_tmp_table= exec_tmp_table2= create_tmp_table(thd, &curr_join->tmp_table_param, @@ -1667,7 +1715,8 @@ JOIN::exec() { thd->proc_info="Sending data"; DBUG_PRINT("info", ("%s", thd->proc_info)); - result->send_fields(*curr_fields_list, + result->send_fields((procedure ? curr_join->procedure_fields_list : + *curr_fields_list), Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); error= do_select(curr_join, curr_fields_list, NULL, procedure); thd->limit_found_rows= curr_join->send_records; @@ -1964,14 +2013,19 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, continue; } outer_join|= table->map; + s->embedding_map= 0; + for (;embedding; embedding= embedding->embedding) + s->embedding_map|= embedding->nested_join->nj_map; continue; } if (embedding) { /* s belongs to a nested join, maybe to several embedded joins */ + s->embedding_map= 0; do { NESTED_JOIN *nested_join= embedding->nested_join; + s->embedding_map|=nested_join->nj_map; s->dependent|= embedding->dep_tables; embedding= embedding->embedding; outer_join|= nested_join->used_tables; @@ -3545,6 +3599,8 @@ choose_plan(JOIN *join, table_map join_tables) bool straight_join= join->select_options & SELECT_STRAIGHT_JOIN; DBUG_ENTER("choose_plan"); + join->cur_embedding_map= 0; + reset_nj_counters(join->join_list); /* if (SELECT_STRAIGHT_JOIN option is set) reorder tables so dependent tables come after tables they depend @@ -4025,7 +4081,9 @@ best_extension_by_limited_search(JOIN *join, for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++) { table_map real_table_bit= s->table->map; - if ((remaining_tables & real_table_bit) && !(remaining_tables & s->dependent)) + if ((remaining_tables & real_table_bit) && + !(remaining_tables & s->dependent) && + (!idx || !check_interleaving_with_nj(join->positions[idx-1].table, s))) { double current_record_count, current_read_time; @@ -4041,6 +4099,7 @@ best_extension_by_limited_search(JOIN *join, { DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx, "prune_by_cost");); + restore_prev_nj_state(s); continue; } @@ -4069,6 +4128,7 @@ best_extension_by_limited_search(JOIN *join, { DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx, "pruned_by_heuristic");); + restore_prev_nj_state(s); continue; } } @@ -4103,9 +4163,11 @@ best_extension_by_limited_search(JOIN *join, sizeof(POSITION) * (idx + 1)); join->best_read= current_read_time - 0.001; } - DBUG_EXECUTE("opt", - print_plan(join, current_read_time, current_record_count, idx, "full_plan");); + DBUG_EXECUTE("opt", print_plan(join, current_read_time, + current_record_count, idx, + "full_plan");); } + restore_prev_nj_state(s); } } DBUG_VOID_RETURN; @@ -4150,7 +4212,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, for (JOIN_TAB **pos=join->best_ref+idx ; (s=*pos) ; pos++) { table_map real_table_bit=s->table->map; - if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent)) + if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) && + (!idx|| !check_interleaving_with_nj(join->positions[idx-1].table, s))) { double best,best_time,records; best=best_time=records=DBL_MAX; @@ -4488,10 +4551,10 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, join->unit->select_limit_cnt >= records) join->sort_by_table= (TABLE*) 1; // Must use temporary table - /* + /* Go to the next level only if there hasn't been a better key on this level! This will cut down the search for a lot simple cases! - */ + */ double current_record_count=record_count*records; double current_read_time=read_time+best; if (best_record_count > current_record_count || @@ -4512,6 +4575,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, return; swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); } + restore_prev_nj_state(s); if (join->select_options & SELECT_STRAIGHT_JOIN) break; // Don't test all combinations } @@ -5097,7 +5161,7 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab) This function can be called only after the execution plan has been chosen. */ - + static void make_outerjoin_info(JOIN *join) { @@ -5168,7 +5232,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) join->const_table_map|=RAND_TABLE_BIT; { // Check const tables COND *const_cond= - make_cond_for_table(cond,join->const_table_map,(table_map) 0); + make_cond_for_table(cond, + join->const_table_map, + (table_map) 0); DBUG_EXECUTE("where",print_where(const_cond,"constants");); for (JOIN_TAB *tab= join->join_tab+join->const_tables; tab < join->join_tab+join->tables ; tab++) @@ -7258,11 +7324,11 @@ propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list, ascent all attributes are calculated, all outer joins that can be converted are replaced and then all unnecessary braces are removed. As join list contains join tables in the reverse order sequential - elimination of outer joins does not requite extra recursive calls. + elimination of outer joins does not require extra recursive calls. EXAMPLES Here is an example of a join query with invalid cross references: - SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t3.a LEFT JOIN ON t3.b=t1.b + SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t3.a LEFT JOIN t3 ON t3.b=t1.b RETURN VALUE The new condition, if success @@ -7419,7 +7485,257 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top) } DBUG_RETURN(conds); } - + + +/* + Assign each nested join structure a bit in nested_join_map + + SYNOPSIS + build_bitmap_for_nested_joins() + join Join being processed + join_list List of tables + first_unused Number of first unused bit in nested_join_map before the + call + + DESCRIPTION + Assign each nested join structure (except "confluent" ones - those that + embed only one element) a bit in nested_join_map. + + NOTE + This function is called after simplify_joins(), when there are no + redundant nested joins, #non_confluent_nested_joins <= #tables_in_join so + we will not run out of bits in nested_join_map. + + RETURN + First unused bit in nested_join_map after the call. +*/ + +static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list, + uint first_unused) +{ + List_iterator<TABLE_LIST> li(*join_list); + TABLE_LIST *table; + DBUG_ENTER("build_bitmap_for_nested_joins"); + while ((table= li++)) + { + NESTED_JOIN *nested_join; + if ((nested_join= table->nested_join)) + { + /* + It is guaranteed by simplify_joins() function that a nested join + that has only one child represents a single table VIEW (and the child + is an underlying table). We don't assign bits to such nested join + structures because + 1. it is redundant (a "sequence" of one table cannot be interleaved + with anything) + 2. we could run out bits in nested_join_map otherwise. + */ + if (nested_join->join_list.elements != 1) + { + nested_join->nj_map= 1 << first_unused++; + first_unused= build_bitmap_for_nested_joins(&nested_join->join_list, + first_unused); + } + } + } + DBUG_RETURN(first_unused); +} + + +/* + Set NESTED_JOIN::counter=0 in all nested joins in passed list + + SYNOPSIS + reset_nj_counters() + join_list List of nested joins to process. It may also contain base + tables which will be ignored. + + DESCRIPTION + Recursively set NESTED_JOIN::counter=0 for all nested joins contained in + the passed join_list. +*/ + +static void reset_nj_counters(List<TABLE_LIST> *join_list) +{ + List_iterator<TABLE_LIST> li(*join_list); + TABLE_LIST *table; + DBUG_ENTER("reset_nj_counters"); + while ((table= li++)) + { + NESTED_JOIN *nested_join; + if ((nested_join= table->nested_join)) + { + nested_join->counter= 0; + reset_nj_counters(&nested_join->join_list); + } + } + DBUG_VOID_RETURN; +} + + +/* + Check interleaving with an inner tables of an outer join for extension table + + SYNOPSIS + check_interleaving_with_nj() + join Join being processed + last_tab Last table in current partial join order (this function is + not called for empty partial join orders) + next_tab Table we're going to extend the current partial join with + + DESCRIPTION + Check if table next_tab can be added to current partial join order, and + if yes, record that it has been added. + + The function assumes that both current partial join order and its + extension with next_tab are valid wrt table dependencies. + + IMPLEMENTATION + LIMITATIONS ON JOIN ORDER + The nested [outer] joins executioner algorithm imposes these limitations + on join order: + 1. "Outer tables first" - any "outer" table must be before any + corresponding "inner" table. + 2. "No interleaving" - tables inside a nested join must form a continuous + sequence in join order (i.e. the sequence must not be interrupted by + tables that are outside of this nested join). + + #1 is checked elsewhere, this function checks #2 provided that #1 has + been already checked. + + WHY NEED NON-INTERLEAVING + Consider an example: + + select * from t0 join t1 left join (t2 join t3) on cond1 + + The join order "t1 t2 t0 t3" is invalid: + + table t0 is outside of the nested join, so WHERE condition for t0 is + attached directly to t0 (without triggers, and it may be used to access + t0). Applying WHERE(t0) to (t2,t0,t3) record is invalid as we may miss + combinations of (t1, t2, t3) that satisfy condition cond1, and produce a + null-complemented (t1, t2.NULLs, t3.NULLs) row, which should not have + been produced. + + If table t0 is not between t2 and t3, the problem doesn't exist: + * If t0 is located after (t2,t3), WHERE(t0) is applied after nested join + processing has finished. + * If t0 is located before (t2,t3), predicates like WHERE_cond(t0, t2) are + wrapped into condition triggers, which takes care of correct nested + join processing. + + HOW IT IS IMPLEMENTED + The limitations on join order can be rephrased as follows: for valid + join order one must be able to: + 1. write down the used tables in the join order on one line. + 2. for each nested join, put one '(' and one ')' on the said line + 3. write "LEFT JOIN" and "ON (...)" where appropriate + 4. get a query equivalent to the query we're trying to execute. + + Calls to check_interleaving_with_nj() are equivalent to writing the + above described line from left to right. + A single check_interleaving_with_nj(A,B) call is equivalent to writing + table B and appropriate brackets on condition that table A and + appropriate brackets is the last what was written. Graphically the + transition is as follows: + + +---- current position + | + ... last_tab ))) | ( next_tab ) )..) | ... + X Y Z | + +- need to move to this + position. + + Notes about the position: + The caller guarantees that there is no more then one X-bracket by + checking "!(remaining_tables & s->dependent)" before calling this + function. X-bracket may have a pair in Y-bracket. + + When "writing" we store/update this auxilary info about the current + position: + 1. join->cur_embedding_map - bitmap of pairs of brackets (aka nested + joins) we've opened but didn't close. + 2. {each NESTED_JOIN structure not simplified away}->counter - number + of this nested join's children that have already been added to to + the partial join order. + + RETURN + FALSE Join order extended, nested joins info about current join order + (see NOTE section) updated. + TRUE Requested join order extension not allowed. +*/ + +static bool check_interleaving_with_nj(JOIN_TAB *last_tab, JOIN_TAB *next_tab) +{ + TABLE_LIST *next_emb= next_tab->table->pos_in_table_list->embedding; + JOIN *join= last_tab->join; + + if (join->cur_embedding_map & ~next_tab->embedding_map) + { + /* + next_tab is outside of the "pair of brackets" we're currently in. + Cannot add it. + */ + return TRUE; + } + + /* + Do update counters for "pairs of brackets" that we've left (marked as + X,Y,Z in the above picture) + */ + for (;next_emb; next_emb= next_emb->embedding) + { + next_emb->nested_join->counter++; + if (next_emb->nested_join->counter == 1) + { + /* + next_emb is the first table inside a nested join we've "entered". In + the picture above, we're looking at the 'X' bracket. Don't exit yet as + X bracket might have Y pair bracket. + */ + join->cur_embedding_map |= next_emb->nested_join->nj_map; + } + + if (next_emb->nested_join->join_list.elements != + next_emb->nested_join->counter) + break; + + /* + We're currently at Y or Z-bracket as depicted in the above picture. + Mark that we've left it and continue walking up the brackets hierarchy. + */ + join->cur_embedding_map &= ~next_emb->nested_join->nj_map; + } + return FALSE; +} + + +/* + Nested joins perspective: Remove the last table from the join order + + SYNOPSIS + restore_prev_nj_state() + last join table to remove, it is assumed to be the last in current + partial join order. + + DESCRIPTION + Remove the last table from the partial join order and update the nested + joins counters and join->cur_embedding_map. It is ok to call this + function for the first table in join order (for which + check_interleaving_with_nj has not been called) +*/ + +static void restore_prev_nj_state(JOIN_TAB *last) +{ + TABLE_LIST *last_emb= last->table->pos_in_table_list->embedding; + JOIN *join= last->join; + while (last_emb && !(--last_emb->nested_join->counter)) + { + join->cur_embedding_map &= last_emb->nested_join->nj_map; + last_emb= last_emb->embedding; + } +} + static COND * optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list, @@ -7468,7 +7784,7 @@ optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list, COND_FALSE always false ( 1 = 2 ) */ -static COND * +COND * remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) { if (cond->type() == Item::COND_ITEM) @@ -7873,7 +8189,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, uint convert_blob_length) { Item::Type orig_type= type; - Item *orig_item; + Item *orig_item= 0; if (type != Item::FIELD_ITEM && item->real_item()->type() == Item::FIELD_ITEM && @@ -7924,10 +8240,12 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, } else result= create_tmp_field_from_field(thd, (*from_field= field->field), - item->name, table, - modify_item ? field : - NULL, - convert_blob_length); + orig_item ? orig_item->name : + item->name, + table, + modify_item ? field : + NULL, + convert_blob_length); if (orig_type == Item::REF_ITEM && orig_modify) ((Item_ref*)orig_item)->set_result_field(result); return result; @@ -8000,6 +8318,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, MEM_ROOT *mem_root_save, own_root; TABLE *table; uint i,field_count,null_count,null_pack_length; + uint copy_func_count= param->func_count; uint hidden_null_count, hidden_null_pack_length, hidden_field_count; uint blob_count,group_null_items, string_count; uint temp_pool_slot=MY_BIT_NONE; @@ -8025,7 +8344,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, statistic_increment(thd->status_var.created_tmp_tables, &LOCK_status); - if (use_temp_pool) + if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES)) temp_pool_slot = bitmap_set_next(&temp_pool); if (temp_pool_slot != MY_BIT_NONE) // we got a slot @@ -8063,6 +8382,16 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, field_count=param->field_count+param->func_count+param->sum_func_count; hidden_field_count=param->hidden_field_count; + /* + When loose index scan is employed as access method, it already + computes all groups and the result of all aggregate functions. We + make space for the items of the aggregate function in the list of + functions TMP_TABLE_PARAM::items_to_copy, so that the values of + these items are stored in the temporary table. + */ + if (param->precomputed_group_by) + copy_func_count+= param->sum_func_count; + init_sql_alloc(&own_root, TABLE_ALLOC_BLOCK_SIZE, 0); if (!multi_alloc_root(&own_root, @@ -8070,7 +8399,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ®_field, sizeof(Field*) * (field_count+1), &blob_field, sizeof(uint)*(field_count+1), &from_field, sizeof(Field*)*field_count, - ©_func, sizeof(*copy_func)*(param->func_count+1), + ©_func, sizeof(*copy_func)*(copy_func_count+1), ¶m->keyinfo, sizeof(*param->keyinfo), &key_part_info, sizeof(*key_part_info)*(param->group_parts+1), @@ -8275,7 +8604,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, (select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) == OPTION_BIG_TABLES || (select_options & TMP_TABLE_FORCE_MYISAM)) { - table->file=get_new_handler(table,table->s->db_type= DB_TYPE_MYISAM); + table->file= get_new_handler(table, &table->mem_root, + table->s->db_type= DB_TYPE_MYISAM); if (group && (param->group_parts > table->file->max_key_parts() || param->group_length > table->file->max_key_length())) @@ -8283,7 +8613,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, } else { - table->file=get_new_handler(table,table->s->db_type= DB_TYPE_HEAP); + table->file= get_new_handler(table, &table->mem_root, + table->s->db_type= DB_TYPE_HEAP); } if (!using_unique_constraint) @@ -8596,6 +8927,7 @@ err: TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list) { uint field_count= field_list.elements; + uint blob_count= 0; Field **field; create_field *cdef; /* column definition */ uint record_length= 0; @@ -8612,6 +8944,12 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list) table->s= s= &table->share_not_to_be_used; s->fields= field_count; + if (!(s->blob_field= (uint*)thd->alloc((field_list.elements + 1) * + sizeof(uint)))) + return 0; + + s->blob_ptr_size= mi_portable_sizeof_char_ptr; + /* Create all fields and calculate the total length of record */ List_iterator_fast<create_field> it(field_list); while ((cdef= it++)) @@ -8627,9 +8965,15 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list) record_length+= (**field).pack_length(); if (! ((**field).flags & NOT_NULL_FLAG)) ++null_count; + + if ((*field)->flags & BLOB_FLAG) + s->blob_field[blob_count++]= (uint) (field - table->field); + ++field; } *field= NULL; /* mark the end of the list */ + s->blob_field[blob_count]= 0; /* mark the end of the list */ + s->blob_fields= blob_count; null_pack_length= (null_count + 7)/8; s->reclength= record_length + null_pack_length; @@ -8867,7 +9211,8 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, new_table= *table; new_table.s= &new_table.share_not_to_be_used; new_table.s->db_type= DB_TYPE_MYISAM; - if (!(new_table.file= get_new_handler(&new_table,DB_TYPE_MYISAM))) + if (!(new_table.file= get_new_handler(&new_table, &new_table.mem_root, + DB_TYPE_MYISAM))) DBUG_RETURN(1); // End of memory save_proc_info=thd->proc_info; @@ -8959,11 +9304,13 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, Next_select_func setup_end_select_func(JOIN *join) { TABLE *table= join->tmp_table; + TMP_TABLE_PARAM *tmp_tbl= &join->tmp_table_param; Next_select_func end_select; + /* Set up select_end */ if (table) { - if (table->group && join->tmp_table_param.sum_func_count) + if (table->group && tmp_tbl->sum_func_count) { if (table->s->keys) { @@ -8976,7 +9323,7 @@ Next_select_func setup_end_select_func(JOIN *join) end_select=end_unique_update; } } - else if (join->sort_and_group) + else if (join->sort_and_group && !tmp_tbl->precomputed_group_by) { DBUG_PRINT("info",("Using end_write_group")); end_select=end_write_group; @@ -8985,19 +9332,27 @@ Next_select_func setup_end_select_func(JOIN *join) { DBUG_PRINT("info",("Using end_write")); end_select=end_write; + if (tmp_tbl->precomputed_group_by) + { + /* + A preceding call to create_tmp_table in the case when loose + index scan is used guarantees that + TMP_TABLE_PARAM::items_to_copy has enough space for the group + by functions. It is OK here to use memcpy since we copy + Item_sum pointers into an array of Item pointers. + */ + memcpy(tmp_tbl->items_to_copy + tmp_tbl->func_count, + join->sum_funcs, + sizeof(Item*)*tmp_tbl->sum_func_count); + tmp_tbl->items_to_copy[tmp_tbl->func_count+tmp_tbl->sum_func_count]= 0; + } } } else { - /* Test if data is accessed via QUICK_GROUP_MIN_MAX_SELECT. */ - bool is_using_quick_group_min_max_select= - (join->join_tab->select && join->join_tab->select->quick && - (join->join_tab->select->quick->get_type() == - QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)); - if ((join->sort_and_group || (join->procedure && join->procedure->flags & PROC_GROUP)) && - !is_using_quick_group_min_max_select) + !tmp_tbl->precomputed_group_by) end_select= end_send_group; else end_select= end_send; @@ -9052,7 +9407,11 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) error= (*end_select)(join,join_tab,1); } else if (join->send_row_on_empty_set()) - rc= join->result->send_data(*join->fields); + { + List<Item> *columns_list= (procedure ? &join->procedure_fields_list : + fields); + rc= join->result->send_data(*columns_list); + } } else { @@ -10081,7 +10440,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), DBUG_RETURN(NESTED_LOOP_OK); // Didn't match having error=0; if (join->procedure) - error=join->procedure->send_row(*join->fields); + error=join->procedure->send_row(join->procedure_fields_list); else if (join->do_send_rows) error=join->result->send_data(*join->fields); if (error) @@ -10267,7 +10626,6 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { copy_fields(&join->tmp_table_param); copy_funcs(join->tmp_table_param.items_to_copy); - #ifdef TO_BE_DELETED if (!table->uniques) // If not unique handling { @@ -10342,7 +10700,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), item->save_org_in_field(group->field); /* Store in the used key if the field was 0 */ if (item->maybe_null) - group->buff[-1]=item->null_value ? 1 : 0; + group->buff[-1]= (char) group->field->is_null(); } if (!table->file->index_read(table->record[1], join->tmp_table_param.group_buff,0, @@ -10702,7 +11060,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, for (; order ; order=order->next, const_key_parts>>=1) { - Field *field=((Item_field*) (*order->item))->field; + Field *field=((Item_field*) (*order->item)->real_item())->field; int flag; /* @@ -10842,8 +11200,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, DBUG_ENTER("test_if_skip_sort_order"); LINT_INIT(ref_key_parts); - /* Check which keys can be used to resolve ORDER BY */ - usable_keys.set_all(); + /* + Check which keys can be used to resolve ORDER BY. + We must not try to use disabled keys. + */ + usable_keys= table->s->keys_in_use; + for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next) { Item *item= (*tmp_order->item)->real_item(); @@ -13386,7 +13748,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, { SELECT_LEX *sl= join->unit->first_select(); uint len= 6, lastop= 0; - memcpy(table_name_buffer, "<union", 6); + memcpy(table_name_buffer, STRING_WITH_LEN("<union")); for (; sl && len + lastop + 5 < NAME_LEN; sl= sl->next_select()) { len+= lastop; @@ -13395,7 +13757,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, } if (sl || len + lastop >= NAME_LEN) { - memcpy(table_name_buffer + len, "...>", 5); + memcpy(table_name_buffer + len, STRING_WITH_LEN("...>") + 1); len+= 4; } else @@ -13574,7 +13936,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT || quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) { - extra.append("; Using "); + extra.append(STRING_WITH_LEN("; Using ")); tab->select->quick->add_info_string(&extra); } if (tab->select) @@ -13582,7 +13944,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, if (tab->use_quick == 2) { char buf[MAX_KEY/8+1]; - extra.append("; Range checked for each record (index map: 0x"); + extra.append(STRING_WITH_LEN("; Range checked for each " + "record (index map: 0x")); extra.append(tab->keys.print(buf)); extra.append(')'); } @@ -13592,38 +13955,39 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, if (thd->variables.engine_condition_pushdown && pushed_cond) { - extra.append("; Using where with pushed condition"); + extra.append(STRING_WITH_LEN("; Using where with pushed " + "condition")); if (thd->lex->describe & DESCRIBE_EXTENDED) { - extra.append(": "); + extra.append(STRING_WITH_LEN(": ")); ((COND *)pushed_cond)->print(&extra); } } else - extra.append("; Using where"); + extra.append(STRING_WITH_LEN("; Using where")); } } if (key_read) { if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX) - extra.append("; Using index for group-by"); + extra.append(STRING_WITH_LEN("; Using index for group-by")); else - extra.append("; Using index"); + extra.append(STRING_WITH_LEN("; Using index")); } if (table->reginfo.not_exists_optimize) - extra.append("; Not exists"); + extra.append(STRING_WITH_LEN("; Not exists")); if (need_tmp_table) { need_tmp_table=0; - extra.append("; Using temporary"); + extra.append(STRING_WITH_LEN("; Using temporary")); } if (need_order) { need_order=0; - extra.append("; Using filesort"); + extra.append(STRING_WITH_LEN("; Using filesort")); } if (distinct & test_all_bits(used_tables,thd->used_tables)) - extra.append("; Distinct"); + extra.append(STRING_WITH_LEN("; Distinct")); /* Skip initial "; "*/ const char *str= extra.ptr(); @@ -13740,15 +14104,18 @@ static void print_join(THD *thd, String *str, List<TABLE_LIST> *tables) { TABLE_LIST *curr= *tbl; if (curr->outer_join) - str->append(" left join ", 11); // MySQL converts right to left joins + { + /* MySQL converts right to left joins */ + str->append(STRING_WITH_LEN(" left join ")); + } else if (curr->straight) - str->append(" straight_join ", 15); + str->append(STRING_WITH_LEN(" straight_join ")); else - str->append(" join ", 6); + str->append(STRING_WITH_LEN(" join ")); curr->print(thd, str); if (curr->on_expr) { - str->append(" on(", 4); + str->append(STRING_WITH_LEN(" on(")); curr->on_expr->print(str); str->append(')'); } @@ -13833,28 +14200,28 @@ void st_select_lex::print(THD *thd, String *str) if (!thd) thd= current_thd; - str->append("select ", 7); + str->append(STRING_WITH_LEN("select ")); /* First add options */ if (options & SELECT_STRAIGHT_JOIN) - str->append("straight_join ", 14); + str->append(STRING_WITH_LEN("straight_join ")); if ((thd->lex->lock_option == TL_READ_HIGH_PRIORITY) && (this == &thd->lex->select_lex)) - str->append("high_priority ", 14); + str->append(STRING_WITH_LEN("high_priority ")); if (options & SELECT_DISTINCT) - str->append("distinct ", 9); + str->append(STRING_WITH_LEN("distinct ")); if (options & SELECT_SMALL_RESULT) - str->append("sql_small_result ", 17); + str->append(STRING_WITH_LEN("sql_small_result ")); if (options & SELECT_BIG_RESULT) - str->append("sql_big_result ", 15); + str->append(STRING_WITH_LEN("sql_big_result ")); if (options & OPTION_BUFFER_RESULT) - str->append("sql_buffer_result ", 18); + str->append(STRING_WITH_LEN("sql_buffer_result ")); if (options & OPTION_FOUND_ROWS) - str->append("sql_calc_found_rows ", 20); + str->append(STRING_WITH_LEN("sql_calc_found_rows ")); if (!thd->lex->safe_to_cache_query) - str->append("sql_no_cache ", 13); + str->append(STRING_WITH_LEN("sql_no_cache ")); if (options & OPTION_TO_QUERY_CACHE) - str->append("sql_cache ", 10); + str->append(STRING_WITH_LEN("sql_cache ")); //Item List bool first= 1; @@ -13875,7 +14242,7 @@ void st_select_lex::print(THD *thd, String *str) */ if (table_list.elements) { - str->append(" from ", 6); + str->append(STRING_WITH_LEN(" from ")); /* go through join tree */ print_join(thd, str, &top_join_list); } @@ -13886,22 +14253,22 @@ void st_select_lex::print(THD *thd, String *str) cur_where= join->conds; if (cur_where) { - str->append(" where ", 7); + str->append(STRING_WITH_LEN(" where ")); cur_where->print(str); } // group by & olap if (group_list.elements) { - str->append(" group by ", 10); + str->append(STRING_WITH_LEN(" group by ")); print_order(str, (ORDER *) group_list.first); switch (olap) { case CUBE_TYPE: - str->append(" with cube", 10); + str->append(STRING_WITH_LEN(" with cube")); break; case ROLLUP_TYPE: - str->append(" with rollup", 12); + str->append(STRING_WITH_LEN(" with rollup")); break; default: ; //satisfy compiler @@ -13915,13 +14282,13 @@ void st_select_lex::print(THD *thd, String *str) if (cur_having) { - str->append(" having ", 8); + str->append(STRING_WITH_LEN(" having ")); cur_having->print(str); } if (order_list.elements) { - str->append(" order by ", 10); + str->append(STRING_WITH_LEN(" order by ")); print_order(str, (ORDER *) order_list.first); } diff --git a/sql/sql_select.h b/sql/sql_select.h index d6161eb6372..4aa238641e5 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -136,8 +136,16 @@ typedef struct st_join_table { TABLE_REF ref; JOIN_CACHE cache; JOIN *join; - + /* Bitmap of nested joins this table is part of */ + nested_join_map embedding_map; + void cleanup(); + inline bool is_using_loose_index_scan() + { + return (select && select->quick && + (select->quick->get_type() == + QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)); + } } JOIN_TAB; enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool @@ -193,6 +201,13 @@ class JOIN :public Sql_alloc */ ha_rows fetch_limit; POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1]; + + /* + Bitmap of nested joins embedding the position at the end of the current + partial join (valid only during join optimizer run). + */ + nested_join_map cur_embedding_map; + double best_read; List<Item> *fields; List<Cached_item> group_fields, group_fields_cache; @@ -244,6 +259,7 @@ class JOIN :public Sql_alloc //Part, shared with list above, emulate following list List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3; List<Item> &fields_list; // hold field list passed to mysql_select + List<Item> procedure_fields_list; int error; ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select @@ -390,7 +406,6 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ORDER *group, bool distinct, bool save_sum_fields, ulonglong select_options, ha_rows rows_limit, char* alias); -TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list); void free_tmp_table(THD *thd, TABLE *entry); void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields, bool reset_with_sum_func); @@ -523,3 +538,4 @@ bool cp_buffer_from_ref(THD *thd, TABLE_REF *ref); bool error_if_full_join(JOIN *join); int report_error(TABLE *table, int error); int safe_index_read(JOIN_TAB *tab); +COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 69b824f8cd9..089314078a6 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -70,17 +70,20 @@ bool mysqld_show_storage_engines(THD *thd) handlerton **types; for (types= sys_table_types; *types; types++) { - protocol->prepare_for_resend(); - protocol->store((*types)->name, system_charset_info); - const char *option_name= show_comp_option_name[(int) (*types)->state]; - - if ((*types)->state == SHOW_OPTION_YES && - !my_strcasecmp(system_charset_info, default_type_name, (*types)->name)) - option_name= "DEFAULT"; - protocol->store(option_name, system_charset_info); - protocol->store((*types)->comment, system_charset_info); - if (protocol->write()) - DBUG_RETURN(TRUE); + if (!((*types)->flags & HTON_HIDDEN)) + { + protocol->prepare_for_resend(); + protocol->store((*types)->name, system_charset_info); + const char *option_name= show_comp_option_name[(int) (*types)->state]; + + if ((*types)->state == SHOW_OPTION_YES && + !my_strcasecmp(system_charset_info, default_type_name, (*types)->name)) + option_name= "DEFAULT"; + protocol->store(option_name, system_charset_info); + protocol->store((*types)->comment, system_charset_info); + if (protocol->write()) + DBUG_RETURN(TRUE); + } } send_eof(thd); DBUG_RETURN(FALSE); @@ -359,7 +362,21 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) /* Only one table for now, but VIEW can involve several tables */ if (open_normal_and_derived_tables(thd, table_list, 0)) - DBUG_RETURN(TRUE); + { + if (!table_list->view || thd->net.last_errno != ER_VIEW_INVALID) + DBUG_RETURN(TRUE); + /* + Clear all messages with 'error' level status and + issue a warning with 'warning' level status in + case of invalid view and last error is ER_VIEW_INVALID + */ + mysql_reset_errors(thd, true); + push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN, + ER_VIEW_INVALID, + ER(ER_VIEW_INVALID), + table_list->view_db.str, + table_list->view_name.str); + } /* TODO: add environment variables show when it become possible */ if (thd->lex->only_view && !table_list->view) @@ -487,22 +504,22 @@ bool mysqld_show_create_db(THD *thd, char *dbname, protocol->prepare_for_resend(); protocol->store(dbname, strlen(dbname), system_charset_info); buffer.length(0); - buffer.append("CREATE DATABASE ", 16); + buffer.append(STRING_WITH_LEN("CREATE DATABASE ")); if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS) - buffer.append("/*!32312 IF NOT EXISTS*/ ", 25); + buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ ")); append_identifier(thd, &buffer, dbname, strlen(dbname)); if (create.default_table_charset) { - buffer.append(" /*!40100", 9); - buffer.append(" DEFAULT CHARACTER SET ", 23); + buffer.append(STRING_WITH_LEN(" /*!40100")); + buffer.append(STRING_WITH_LEN(" DEFAULT CHARACTER SET ")); buffer.append(create.default_table_charset->csname); if (!(create.default_table_charset->state & MY_CS_PRIMARY)) { - buffer.append(" COLLATE ", 9); + buffer.append(STRING_WITH_LEN(" COLLATE ")); buffer.append(create.default_table_charset->name); } - buffer.append(" */", 3); + buffer.append(STRING_WITH_LEN(" */")); } protocol->store(buffer.ptr(), buffer.length(), buffer.charset()); @@ -713,7 +730,7 @@ static void append_directory(THD *thd, String *packet, const char *dir_type, uint length= dirname_length(filename); packet->append(' '); packet->append(dir_type); - packet->append(" DIRECTORY='", 12); + packet->append(STRING_WITH_LEN(" DIRECTORY='")); #ifdef __WIN__ /* Convert \ to / to be able to create table on unix */ char *winfilename= (char*) thd->memdup(filename, length); @@ -762,16 +779,16 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) restore_record(table, s->default_values); // Get empty record if (share->tmp_table) - packet->append("CREATE TEMPORARY TABLE ", 23); + packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE ")); else - packet->append("CREATE TABLE ", 13); + packet->append(STRING_WITH_LEN("CREATE TABLE ")); if (table_list->schema_table) alias= table_list->schema_table->table_name; else alias= (lower_case_table_names == 2 ? table->alias : share->table_name); append_identifier(thd, packet, alias, strlen(alias)); - packet->append(" (\n", 3); + packet->append(STRING_WITH_LEN(" (\n")); for (ptr=table->field ; (field= *ptr); ptr++) { @@ -780,9 +797,9 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) uint flags = field->flags; if (ptr != table->field) - packet->append(",\n", 2); + packet->append(STRING_WITH_LEN(",\n")); - packet->append(" ", 2); + packet->append(STRING_WITH_LEN(" ")); append_identifier(thd,packet,field->field_name, strlen(field->field_name)); packet->append(' '); // check for surprises from the previous call to Field::sql_type() @@ -799,7 +816,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) { if (field->charset() != share->table_charset) { - packet->append(" character set ", 15); + packet->append(STRING_WITH_LEN(" character set ")); packet->append(field->charset()->csname); } /* @@ -808,20 +825,20 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) */ if (!(field->charset()->state & MY_CS_PRIMARY)) { - packet->append(" collate ", 9); + packet->append(STRING_WITH_LEN(" collate ")); packet->append(field->charset()->name); } } if (flags & NOT_NULL_FLAG) - packet->append(" NOT NULL", 9); + packet->append(STRING_WITH_LEN(" NOT NULL")); else if (field->type() == FIELD_TYPE_TIMESTAMP) { /* TIMESTAMP field require explicit NULL flag, because unlike all other fields they are treated as NOT NULL by default. */ - packet->append(" NULL", 5); + packet->append(STRING_WITH_LEN(" NULL")); } /* @@ -839,9 +856,9 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) if (has_default) { - packet->append(" default ", 9); + packet->append(STRING_WITH_LEN(" default ")); if (has_now_default) - packet->append("CURRENT_TIMESTAMP",17); + packet->append(STRING_WITH_LEN("CURRENT_TIMESTAMP")); else if (!field->is_null()) { // Not null by default type.set(tmp, sizeof(tmp), field->charset()); @@ -856,10 +873,10 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) append_unescaped(packet, def_val.ptr(), def_val.length()); } else - packet->append("''",2); + packet->append(STRING_WITH_LEN("''")); } else if (field->maybe_null()) - packet->append("NULL", 4); // Null as default + packet->append(STRING_WITH_LEN("NULL")); // Null as default else packet->append(tmp); } @@ -867,21 +884,20 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) if (!(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS) && table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD) - packet->append(" on update CURRENT_TIMESTAMP",28); + packet->append(STRING_WITH_LEN(" on update CURRENT_TIMESTAMP")); if (field->unireg_check == Field::NEXT_NUMBER && !(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS)) - packet->append(" auto_increment", 15 ); + packet->append(STRING_WITH_LEN(" auto_increment")); if (field->comment.length) { - packet->append(" COMMENT ",9); + packet->append(STRING_WITH_LEN(" COMMENT ")); append_unescaped(packet, field->comment.str, field->comment.length); } } key_info= table->key_info; - file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); bzero((char*) &create_info, sizeof(create_info)); file->update_create_info(&create_info); primary_key= share->primary_key; @@ -890,20 +906,20 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) { KEY_PART_INFO *key_part= key_info->key_part; bool found_primary=0; - packet->append(",\n ", 4); + packet->append(STRING_WITH_LEN(",\n ")); if (i == primary_key && !strcmp(key_info->name, primary_key_name)) { found_primary=1; - packet->append("PRIMARY ", 8); + packet->append(STRING_WITH_LEN("PRIMARY ")); } else if (key_info->flags & HA_NOSAME) - packet->append("UNIQUE ", 7); + packet->append(STRING_WITH_LEN("UNIQUE ")); else if (key_info->flags & HA_FULLTEXT) - packet->append("FULLTEXT ", 9); + packet->append(STRING_WITH_LEN("FULLTEXT ")); else if (key_info->flags & HA_SPATIAL) - packet->append("SPATIAL ", 8); - packet->append("KEY ", 4); + packet->append(STRING_WITH_LEN("SPATIAL ")); + packet->append(STRING_WITH_LEN("KEY ")); if (!found_primary) append_identifier(thd, packet, key_info->name, strlen(key_info->name)); @@ -912,19 +928,19 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) !limited_mysql_mode && !foreign_db_mode) { if (key_info->algorithm == HA_KEY_ALG_BTREE) - packet->append(" USING BTREE", 12); + packet->append(STRING_WITH_LEN(" USING BTREE")); if (key_info->algorithm == HA_KEY_ALG_HASH) - packet->append(" USING HASH", 11); + packet->append(STRING_WITH_LEN(" USING HASH")); // +BAR: send USING only in non-default case: non-spatial rtree if ((key_info->algorithm == HA_KEY_ALG_RTREE) && !(key_info->flags & HA_SPATIAL)) - packet->append(" USING RTREE", 12); + packet->append(STRING_WITH_LEN(" USING RTREE")); // No need to send USING FULLTEXT, it is sent as FULLTEXT KEY } - packet->append(" (", 2); + packet->append(STRING_WITH_LEN(" (")); for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) { @@ -961,71 +977,71 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) file->free_foreign_key_create_info(for_str); } - packet->append("\n)", 2); + packet->append(STRING_WITH_LEN("\n)")); if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode) { if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) - packet->append(" TYPE=", 6); + packet->append(STRING_WITH_LEN(" TYPE=")); else - packet->append(" ENGINE=", 8); + packet->append(STRING_WITH_LEN(" ENGINE=")); packet->append(file->table_type()); if (share->table_charset && !(thd->variables.sql_mode & MODE_MYSQL323) && !(thd->variables.sql_mode & MODE_MYSQL40)) { - packet->append(" DEFAULT CHARSET=", 17); + packet->append(STRING_WITH_LEN(" DEFAULT CHARSET=")); packet->append(share->table_charset->csname); if (!(share->table_charset->state & MY_CS_PRIMARY)) { - packet->append(" COLLATE=", 9); + packet->append(STRING_WITH_LEN(" COLLATE=")); packet->append(table->s->table_charset->name); } } if (share->min_rows) { - packet->append(" MIN_ROWS=", 10); + packet->append(STRING_WITH_LEN(" MIN_ROWS=")); end= longlong10_to_str(share->min_rows, buff, 10); packet->append(buff, (uint) (end- buff)); } if (share->max_rows && !table_list->schema_table) { - packet->append(" MAX_ROWS=", 10); + packet->append(STRING_WITH_LEN(" MAX_ROWS=")); end= longlong10_to_str(share->max_rows, buff, 10); packet->append(buff, (uint) (end - buff)); } if (share->avg_row_length) { - packet->append(" AVG_ROW_LENGTH=", 16); + packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH=")); end= longlong10_to_str(share->avg_row_length, buff,10); packet->append(buff, (uint) (end - buff)); } if (share->db_create_options & HA_OPTION_PACK_KEYS) - packet->append(" PACK_KEYS=1", 12); + packet->append(STRING_WITH_LEN(" PACK_KEYS=1")); if (share->db_create_options & HA_OPTION_NO_PACK_KEYS) - packet->append(" PACK_KEYS=0", 12); + packet->append(STRING_WITH_LEN(" PACK_KEYS=0")); if (share->db_create_options & HA_OPTION_CHECKSUM) - packet->append(" CHECKSUM=1", 11); + packet->append(STRING_WITH_LEN(" CHECKSUM=1")); if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE) - packet->append(" DELAY_KEY_WRITE=1",18); + packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1")); if (share->row_type != ROW_TYPE_DEFAULT) { - packet->append(" ROW_FORMAT=",12); + packet->append(STRING_WITH_LEN(" ROW_FORMAT=")); packet->append(ha_row_type[(uint) share->row_type]); } table->file->append_create_info(packet); if (share->comment && share->comment[0]) { - packet->append(" COMMENT=", 9); + packet->append(STRING_WITH_LEN(" COMMENT=")); append_unescaped(packet, share->comment, strlen(share->comment)); } if (share->connect_string.length) { - packet->append(" CONNECTION=", 12); + packet->append(STRING_WITH_LEN(" CONNECTION=")); append_unescaped(packet, share->connect_string.str, share->connect_string.length); } if (file->raid_type) @@ -1046,32 +1062,50 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) void view_store_options(THD *thd, TABLE_LIST *table, String *buff) { - buff->append("ALGORITHM=", 10); + buff->append(STRING_WITH_LEN("ALGORITHM=")); switch ((int8)table->algorithm) { case VIEW_ALGORITHM_UNDEFINED: - buff->append("UNDEFINED ", 10); + buff->append(STRING_WITH_LEN("UNDEFINED ")); break; case VIEW_ALGORITHM_TMPTABLE: - buff->append("TEMPTABLE ", 10); + buff->append(STRING_WITH_LEN("TEMPTABLE ")); break; case VIEW_ALGORITHM_MERGE: - buff->append("MERGE ", 6); + buff->append(STRING_WITH_LEN("MERGE ")); break; default: DBUG_ASSERT(0); // never should happen } - buff->append("DEFINER=", 8); - append_identifier(thd, buff, - table->definer.user.str, table->definer.user.length); - buff->append('@'); - append_identifier(thd, buff, - table->definer.host.str, table->definer.host.length); + append_definer(thd, buff, &table->definer.user, &table->definer.host); if (table->view_suid) - buff->append(" SQL SECURITY DEFINER ", 22); + buff->append(STRING_WITH_LEN("SQL SECURITY DEFINER ")); else - buff->append(" SQL SECURITY INVOKER ", 22); + buff->append(STRING_WITH_LEN("SQL SECURITY INVOKER ")); } + +/* + Append DEFINER clause to the given buffer. + + SYNOPSIS + append_definer() + thd [in] thread handle + buffer [inout] buffer to hold DEFINER clause + definer_user [in] user name part of definer + definer_host [in] host name part of definer +*/ + +void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user, + const LEX_STRING *definer_host) +{ + buffer->append(STRING_WITH_LEN("DEFINER=")); + append_identifier(thd, buffer, definer_user->str, definer_user->length); + buffer->append('@'); + append_identifier(thd, buffer, definer_host->str, definer_host->length); + buffer->append(' '); +} + + static int view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) { @@ -1104,19 +1138,19 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) } } - buff->append("CREATE ", 7); + buff->append(STRING_WITH_LEN("CREATE ")); if (!foreign_db_mode) { view_store_options(thd, table, buff); } - buff->append("VIEW ", 5); + buff->append(STRING_WITH_LEN("VIEW ")); if (!table->compact_view_format) { append_identifier(thd, buff, table->view_db.str, table->view_db.length); buff->append('.'); } append_identifier(thd, buff, table->view_name.str, table->view_name.length); - buff->append(" AS ", 4); + buff->append(STRING_WITH_LEN(" AS ")); /* We can't just use table->query, because our SQL_MODE may trigger @@ -1127,9 +1161,9 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) if (table->with_check != VIEW_CHECK_NONE) { if (table->with_check == VIEW_CHECK_LOCAL) - buff->append(" WITH LOCAL CHECK OPTION", 24); + buff->append(STRING_WITH_LEN(" WITH LOCAL CHECK OPTION")); else - buff->append(" WITH CASCADED CHECK OPTION", 27); + buff->append(STRING_WITH_LEN(" WITH CASCADED CHECK OPTION")); } return 0; } @@ -1391,7 +1425,7 @@ static bool show_status_array(THD *thd, const char *wild, case SHOW_SLAVE_RUNNING: { pthread_mutex_lock(&LOCK_active_mi); - end= strmov(buff, (active_mi->slave_running && + end= strmov(buff, (active_mi && active_mi->slave_running && active_mi->rli.slave_running) ? "ON" : "OFF"); pthread_mutex_unlock(&LOCK_active_mi); break; @@ -1402,12 +1436,15 @@ static bool show_status_array(THD *thd, const char *wild, TODO: in 5.1 with multimaster, have one such counter per line in SHOW SLAVE STATUS, and have the sum over all lines here. */ - pthread_mutex_lock(&LOCK_active_mi); - pthread_mutex_lock(&active_mi->rli.data_lock); - end= int10_to_str(active_mi->rli.retried_trans, buff, 10); - pthread_mutex_unlock(&active_mi->rli.data_lock); - pthread_mutex_unlock(&LOCK_active_mi); - break; + pthread_mutex_lock(&LOCK_active_mi); + if (active_mi) + { + pthread_mutex_lock(&active_mi->rli.data_lock); + end= int10_to_str(active_mi->rli.retried_trans, buff, 10); + pthread_mutex_unlock(&active_mi->rli.data_lock); + } + pthread_mutex_unlock(&LOCK_active_mi); + break; } case SHOW_SLAVE_SKIP_ERRORS: { @@ -1642,6 +1679,9 @@ static bool show_status_array(THD *thd, const char *wild, value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache; end= longlong10_to_str(*(longlong*) value, buff, 10); break; + case SHOW_NET_COMPRESSION: + end= strmov(buff, thd->net.compress ? "ON" : "OFF"); + break; case SHOW_UNDEF: // Show never happen case SHOW_SYS: break; // Return empty string @@ -2003,7 +2043,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) Security_context *sctx= thd->security_ctx; uint derived_tables= lex->derived_tables; int error= 1; + db_type not_used; Open_tables_state open_tables_state_backup; + bool save_view_prepare_mode= lex->view_prepare_mode; + lex->view_prepare_mode= TRUE; DBUG_ENTER("get_all_tables"); LINT_INIT(end); @@ -2028,6 +2071,13 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) bool res; lex->all_selects_list= lsel; + /* + Restore thd->temporary_tables to be able to process + temporary tables(only for 'show index' & 'show columns'). + This should be changed when processing of temporary tables for + I_S tables will be done. + */ + thd->temporary_tables= open_tables_state_backup.temporary_tables; res= open_normal_and_derived_tables(thd, show_table_list, MYSQL_LOCK_IGNORE_FLUSH); /* @@ -2047,6 +2097,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) show_table_list->view_db.str : show_table_list->db), show_table_list->alias)); + thd->temporary_tables= 0; close_thread_tables(thd); show_table_list->table= 0; goto err; @@ -2109,20 +2160,24 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) { if (with_i_schema) { - table->field[3]->store("SYSTEM VIEW", 11, system_charset_info); + table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), + system_charset_info); } else { my_snprintf(end, len, "/%s%s", file_name, reg_ext); - switch (mysql_frm_type(path)) { + switch (mysql_frm_type(thd, path, ¬_used)) { case FRMTYPE_ERROR: - table->field[3]->store("ERROR", 5, system_charset_info); + table->field[3]->store(STRING_WITH_LEN("ERROR"), + system_charset_info); break; case FRMTYPE_TABLE: - table->field[3]->store("BASE TABLE", 10, system_charset_info); + table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), + system_charset_info); break; case FRMTYPE_VIEW: - table->field[3]->store("VIEW", 4, system_charset_info); + table->field[3]->store(STRING_WITH_LEN("VIEW"), + system_charset_info); break; default: DBUG_ASSERT(0); @@ -2177,6 +2232,7 @@ err: lex->derived_tables= derived_tables; lex->all_selects_list= old_all_select_lex; lex->query_tables_last= save_query_tables_last; + lex->view_prepare_mode= save_view_prepare_mode; *save_query_tables_last= 0; lex->sql_command= save_sql_command; DBUG_RETURN(error); @@ -2270,13 +2326,19 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, there was errors during opening tables */ const char *error= thd->net.last_error; + if (tables->view) + table->field[3]->store(STRING_WITH_LEN("VIEW"), cs); + else if (tables->schema_table) + table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs); + else + table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs); table->field[20]->store(error, strlen(error), cs); thd->clear_error(); } else if (tables->view) { - table->field[3]->store("VIEW", 4, cs); - table->field[20]->store("VIEW", 4, cs); + table->field[3]->store(STRING_WITH_LEN("VIEW"), cs); + table->field[20]->store(STRING_WITH_LEN("VIEW"), cs); } else { @@ -2287,11 +2349,11 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_AUTO | HA_STATUS_NO_LOCK); if (share->tmp_table == SYSTEM_TMP_TABLE) - table->field[3]->store("SYSTEM VIEW", 11, cs); + table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs); else if (share->tmp_table) - table->field[3]->store("LOCAL TEMPORARY", 15, cs); + table->field[3]->store(STRING_WITH_LEN("LOCAL TEMPORARY"), cs); else - table->field[3]->store("BASE TABLE", 10, cs); + table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs); for (int i= 4; i < 20; i++) { @@ -2527,7 +2589,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, if (show_table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_UN_FIELD) { - table->field[5]->store("CURRENT_TIMESTAMP", 17, cs); + table->field[5]->store(STRING_WITH_LEN("CURRENT_TIMESTAMP"), cs); table->field[5]->set_notnull(); } else if (field->unireg_check != Field::NEXT_NUMBER && @@ -2557,10 +2619,13 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, table->field[6]->store((const char*) pos, strlen((const char*) pos), cs); is_blob= (field->type() == FIELD_TYPE_BLOB); - if (field->has_charset() || is_blob) + if (field->has_charset() || is_blob || + field->real_type() == MYSQL_TYPE_VARCHAR || // For varbinary type + field->real_type() == MYSQL_TYPE_STRING) // For binary type { - longlong char_max_len= is_blob ? (longlong) field->max_length() : - (longlong) field->max_length()/field->charset()->mbmaxlen; + longlong char_max_len= is_blob ? + (longlong) field->max_length() / field->charset()->mbminlen : + (longlong) field->max_length() / field->charset()->mbmaxlen; table->field[8]->store(char_max_len, TRUE); table->field[8]->set_notnull(); table->field[9]->store((longlong) field->max_length(), TRUE); @@ -2788,8 +2853,8 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, get_field(thd->mem_root, proc_table->field[10], &tmp_string); table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs); } - table->field[6]->store("SQL", 3, cs); - table->field[10]->store("SQL", 3, cs); + table->field[6]->store(STRING_WITH_LEN("SQL"), cs); + table->field[10]->store(STRING_WITH_LEN("SQL"), cs); get_field(thd->mem_root, proc_table->field[6], &tmp_string); table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs); table->field[12]->store(sp_data_access_name[enum_idx].str, @@ -2944,7 +3009,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables, pos= show_table->file->index_type(i); table->field[13]->store(pos, strlen(pos), cs); if (!show_table->s->keys_in_use.is_set(i)) - table->field[14]->store("disabled", 8, cs); + table->field[14]->store(STRING_WITH_LEN("disabled"), cs); else table->field[14]->store("", 0, cs); table->field[14]->set_notnull(); @@ -2966,47 +3031,44 @@ static int get_schema_views_record(THD *thd, struct st_table_list *tables, DBUG_ENTER("get_schema_views_record"); char definer[HOSTNAME_LENGTH + USERNAME_LENGTH + 2]; uint definer_len; - if (!res) - { - if (tables->view) - { - restore_record(table, s->default_values); - table->field[1]->store(tables->view_db.str, tables->view_db.length, cs); - table->field[2]->store(tables->view_name.str, tables->view_name.length, - cs); - table->field[3]->store(tables->query.str, tables->query.length, cs); - if (tables->with_check != VIEW_CHECK_NONE) - { - if (tables->with_check == VIEW_CHECK_LOCAL) - table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs); - else - table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs); - } - else - table->field[4]->store(STRING_WITH_LEN("NONE"), cs); + if (tables->view) + { + restore_record(table, s->default_values); + table->field[1]->store(tables->view_db.str, tables->view_db.length, cs); + table->field[2]->store(tables->view_name.str, tables->view_name.length, + cs); + table->field[3]->store(tables->query.str, tables->query.length, cs); - if (tables->updatable_view) - table->field[5]->store(STRING_WITH_LEN("YES"), cs); - else - table->field[5]->store(STRING_WITH_LEN("NO"), cs); - definer_len= (strxmov(definer, tables->definer.user.str, "@", - tables->definer.host.str, NullS) - definer); - table->field[6]->store(definer, definer_len, cs); - if (tables->view_suid) - table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs); + if (tables->with_check != VIEW_CHECK_NONE) + { + if (tables->with_check == VIEW_CHECK_LOCAL) + table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs); else - table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs); - DBUG_RETURN(schema_table_store_record(thd, table)); + table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs); } - } - else - { - if (tables->view) + else + table->field[4]->store(STRING_WITH_LEN("NONE"), cs); + + if (tables->updatable_view) + table->field[5]->store(STRING_WITH_LEN("YES"), cs); + else + table->field[5]->store(STRING_WITH_LEN("NO"), cs); + definer_len= (strxmov(definer, tables->definer.user.str, "@", + tables->definer.host.str, NullS) - definer); + table->field[6]->store(definer, definer_len, cs); + if (tables->view_suid) + table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs); + else + table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs); + if (schema_table_store_record(thd, table)) + DBUG_RETURN(1); + if (res) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, thd->net.last_errno, thd->net.last_error); - thd->clear_error(); } + if (res) + thd->clear_error(); DBUG_RETURN(0); } @@ -3057,13 +3119,15 @@ static int get_schema_constraints_record(THD *thd, struct st_table_list *tables, if (i == primary_key && !strcmp(key_info->name, primary_key_name)) { if (store_constraints(thd, table, base_name, file_name, key_info->name, - strlen(key_info->name), "PRIMARY KEY", 11)) + strlen(key_info->name), + STRING_WITH_LEN("PRIMARY KEY"))) DBUG_RETURN(1); } else if (key_info->flags & HA_NOSAME) { if (store_constraints(thd, table, base_name, file_name, key_info->name, - strlen(key_info->name), "UNIQUE", 6)) + strlen(key_info->name), + STRING_WITH_LEN("UNIQUE"))) DBUG_RETURN(1); } } @@ -3089,7 +3153,8 @@ static bool store_trigger(THD *thd, TABLE *table, const char *db, enum trg_event_type event, enum trg_action_time_type timing, LEX_STRING *trigger_stmt, - ulong sql_mode) + ulong sql_mode, + LEX_STRING *definer_buffer) { CHARSET_INFO *cs= system_charset_info; byte *sql_mode_str; @@ -3103,17 +3168,18 @@ static bool store_trigger(THD *thd, TABLE *table, const char *db, table->field[5]->store(db, strlen(db), cs); table->field[6]->store(tname, strlen(tname), cs); table->field[9]->store(trigger_stmt->str, trigger_stmt->length, cs); - table->field[10]->store("ROW", 3, cs); + table->field[10]->store(STRING_WITH_LEN("ROW"), cs); table->field[11]->store(trg_action_time_type_names[timing].str, trg_action_time_type_names[timing].length, cs); - table->field[14]->store("OLD", 3, cs); - table->field[15]->store("NEW", 3, cs); + table->field[14]->store(STRING_WITH_LEN("OLD"), cs); + table->field[15]->store(STRING_WITH_LEN("NEW"), cs); sql_mode_str= sys_var_thd_sql_mode::symbolic_mode_representation(thd, sql_mode, &sql_mode_len); table->field[17]->store((const char*)sql_mode_str, sql_mode_len, cs); + table->field[18]->store((const char *)definer_buffer->str, definer_buffer->length, cs); return schema_table_store_record(thd, table); } @@ -3147,15 +3213,21 @@ static int get_schema_triggers_record(THD *thd, struct st_table_list *tables, LEX_STRING trigger_name; LEX_STRING trigger_stmt; ulong sql_mode; + char definer_holder[HOSTNAME_LENGTH + USERNAME_LENGTH + 2]; + LEX_STRING definer_buffer; + definer_buffer.str= definer_holder; if (triggers->get_trigger_info(thd, (enum trg_event_type) event, (enum trg_action_time_type)timing, &trigger_name, &trigger_stmt, - &sql_mode)) + &sql_mode, + &definer_buffer)) continue; + if (store_trigger(thd, table, base_name, file_name, &trigger_name, (enum trg_event_type) event, (enum trg_action_time_type) timing, &trigger_stmt, - sql_mode)) + sql_mode, + &definer_buffer)) DBUG_RETURN(1); } } @@ -3491,9 +3563,9 @@ int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) buffer.append(field_info->old_name); if (lex->wild && lex->wild->ptr()) { - buffer.append(" ("); + buffer.append(STRING_WITH_LEN(" (")); buffer.append(lex->wild->ptr()); - buffer.append(")"); + buffer.append(')'); } field->set_name(buffer.ptr(), buffer.length(), system_charset_info); } @@ -3514,9 +3586,9 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) buffer.append(lex->select_lex.db); if (lex->wild && lex->wild->ptr()) { - buffer.append(" ("); + buffer.append(STRING_WITH_LEN(" (")); buffer.append(lex->wild->ptr()); - buffer.append(")"); + buffer.append(')'); } Item_field *field= new Item_field(context, NullS, NullS, field_info->field_name); @@ -4059,6 +4131,7 @@ ST_FIELD_INFO triggers_fields_info[]= {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0}, {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Created"}, {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, "sql_mode"}, + {"DEFINER", 65535, MYSQL_TYPE_STRING, 0, 0, "Definer"}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 51f802e7465..fd7bca7ec21 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -848,22 +848,22 @@ void String::print(String *str) switch (c) { case '\\': - str->append("\\\\", 2); + str->append(STRING_WITH_LEN("\\\\")); break; case '\0': - str->append("\\0", 2); + str->append(STRING_WITH_LEN("\\0")); break; case '\'': - str->append("\\'", 2); + str->append(STRING_WITH_LEN("\\'")); break; case '\n': - str->append("\\n", 2); + str->append(STRING_WITH_LEN("\\n")); break; case '\r': - str->append("\\r", 2); + str->append(STRING_WITH_LEN("\\r")); break; case 26: //Ctrl-Z - str->append("\\z", 2); + str->append(STRING_WITH_LEN("\\z")); break; default: str->append(c); diff --git a/sql/sql_string.h b/sql/sql_string.h index ddae6368228..0659f684afe 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -24,6 +24,8 @@ #define NOT_FIXED_DEC 31 #endif +#define STRING_WITH_LEN(X) ((const char*) X), ((uint) (sizeof(X) - 1)) + class String; int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 56a55d9fbc0..ba4a606537f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -103,23 +103,28 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, /* mark for close and remove all cached entries */ - thd->mysys_var->current_mutex= &LOCK_open; - thd->mysys_var->current_cond= &COND_refresh; - VOID(pthread_mutex_lock(&LOCK_open)); - if (!drop_temporary) { if ((error= wait_if_global_read_lock(thd, 0, 1))) { my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name); - goto err; + DBUG_RETURN(TRUE); } else need_start_waiters= TRUE; } + + /* + Acquire LOCK_open after wait_if_global_read_lock(). If we would hold + LOCK_open during wait_if_global_read_lock(), other threads could not + close their tables. This would make a pretty deadlock. + */ + thd->mysys_var->current_mutex= &LOCK_open; + thd->mysys_var->current_cond= &COND_refresh; + VOID(pthread_mutex_lock(&LOCK_open)); + error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0); -err: pthread_mutex_unlock(&LOCK_open); pthread_mutex_lock(&thd->mysys_var->mutex); @@ -218,6 +223,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, String wrong_tables; int error; bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0; + DBUG_ENTER("mysql_rm_table_part2"); if (lock_table_names(thd, tables)) @@ -229,7 +235,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, for (table= tables; table; table= table->next_local) { char *db=table->db; - mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL); + db_type table_type= DB_TYPE_UNKNOWN; + + mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, TRUE); if (!close_temporary_table(thd, db, table->table_name)) { tmp_table_deleted=1; @@ -256,7 +264,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, if (drop_temporary || (access(path,F_OK) && ha_create_table_from_engine(thd,db,alias)) || - (!drop_view && mysql_frm_type(path) != FRMTYPE_TABLE)) + (!drop_view && + mysql_frm_type(thd, path, &table_type) != FRMTYPE_TABLE)) { // Table was not found on disk and table can't be created from engine if (if_exists) @@ -269,7 +278,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, else { char *end; - db_type table_type= get_table_type(thd, path); + if (table_type == DB_TYPE_UNKNOWN) + mysql_frm_type(thd, path, &table_type); *(end=fn_ext(path))=0; // Remove extension for delete error= ha_delete_table(thd, table_type, path, table->table_name, !dont_log_query); @@ -695,7 +705,8 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, MY_CS_BINSORT,MYF(0)))) { char tmp[64]; - strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4), "_bin", 4); + strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4), + STRING_WITH_LEN("_bin")); my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp); DBUG_RETURN(-1); } @@ -714,7 +725,14 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, */ if (!interval) { - interval= sql_field->interval= typelib(sql_field->interval_list); + /* + Create the typelib in prepared statement memory if we're + executing one. + */ + MEM_ROOT *stmt_root= thd->stmt_arena->mem_root; + + interval= sql_field->interval= typelib(stmt_root, + sql_field->interval_list); List_iterator<String> it(sql_field->interval_list); String conv, *tmp; for (uint i= 0; (tmp= it++); i++) @@ -725,7 +743,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { uint cnv_errs; conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs); - interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(), + interval->type_names[i]= strmake_root(stmt_root, conv.ptr(), conv.length()); interval->type_lengths[i]= conv.length(); } @@ -745,8 +763,22 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, */ if (sql_field->def && cs != sql_field->def->collation.collation) { - if (!(sql_field->def= - sql_field->def->safe_charset_converter(cs))) + Query_arena backup_arena; + bool need_to_change_arena= !thd->stmt_arena->is_conventional(); + if (need_to_change_arena) + { + /* Asser that we don't do that at every PS execute */ + DBUG_ASSERT(thd->stmt_arena->is_first_stmt_execute() || + thd->stmt_arena->is_first_sp_execute()); + thd->set_n_backup_active_arena(thd->stmt_arena, &backup_arena); + } + + sql_field->def= sql_field->def->safe_charset_converter(cs); + + if (need_to_change_arena) + thd->restore_active_arena(thd->stmt_arena, &backup_arena); + + if (! sql_field->def) { /* Could not convert */ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); @@ -835,17 +867,25 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, else { /* Field redefined */ + sql_field->def= dup_field->def; sql_field->sql_type= dup_field->sql_type; sql_field->charset= (dup_field->charset ? dup_field->charset : create_info->default_table_charset); - sql_field->length= dup_field->length; - sql_field->pack_length= dup_field->pack_length; + sql_field->length= dup_field->chars_length; + sql_field->pack_length= dup_field->pack_length; sql_field->key_length= dup_field->key_length; sql_field->create_length_to_internal_length(); sql_field->decimals= dup_field->decimals; - sql_field->flags= dup_field->flags; sql_field->unireg_check= dup_field->unireg_check; + /* + We're making one field from two, the result field will have + dup_field->flags as flags. If we've incremented null_fields + because of sql_field->flags, decrement it back. + */ + if (!(sql_field->flags & NOT_NULL_FLAG)) + null_fields--; + sql_field->flags= dup_field->flags; it2.remove(); // Remove first (create) definition select_field_pos--; break; @@ -1508,7 +1548,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name, if (create_info->row_type == ROW_TYPE_DYNAMIC) db_options|=HA_OPTION_PACK_RECORD; alias= table_case_name(create_info, table_name); - file=get_new_handler((TABLE*) 0, create_info->db_type); + file= get_new_handler((TABLE*) 0, thd->mem_root, create_info->db_type); #ifdef NOT_USED /* @@ -1806,10 +1846,12 @@ mysql_rename_table(enum db_type base, const char *new_db, const char *new_name) { + THD *thd= current_thd; char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN]; char *from_base= from, *to_base= to; char tmp_name[NAME_LEN+1]; - handler *file=(base == DB_TYPE_UNKNOWN ? 0 : get_new_handler((TABLE*) 0, base)); + handler *file= (base == DB_TYPE_UNKNOWN ? 0 : + get_new_handler((TABLE*) 0, thd->mem_root, base)); int error=0; DBUG_ENTER("mysql_rename_table"); @@ -1931,7 +1973,7 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table, protocol->prepare_for_resend(); protocol->store(table->alias, system_charset_info); protocol->store((char*) operator_name, system_charset_info); - protocol->store("error", 5, system_charset_info); + protocol->store(STRING_WITH_LEN("error"), system_charset_info); protocol->store(errmsg, system_charset_info); thd->clear_error(); if (protocol->write()) @@ -2156,7 +2198,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL); + mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL, FALSE); for (table= tables; table; table= table->next_local) { char table_name[NAME_LEN*2+2]; @@ -2180,18 +2222,14 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, */ lex->query_tables= table; lex->query_tables_last= &table->next_global; - lex->query_tables_own_last= 0;; + lex->query_tables_own_last= 0; thd->no_warnings_for_error= no_warnings_for_error; + if (view_operator_func == NULL) + table->required_type=FRMTYPE_TABLE; open_and_lock_tables(thd, table); thd->no_warnings_for_error= 0; table->next_global= save_next_global; table->next_local= save_next_local; - /* if view are unsupported */ - if (table->view && view_operator_func == NULL) - { - result_code= HA_ADMIN_NOT_IMPLEMENTED; - goto send_result; - } thd->open_options&= ~extra_open_options; if (prepare_func) @@ -2222,7 +2260,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, protocol->prepare_for_resend(); protocol->store(table_name, system_charset_info); protocol->store(operator_name, system_charset_info); - protocol->store("error",5, system_charset_info); + protocol->store(STRING_WITH_LEN("error"), system_charset_info); if (!(err_msg=thd->net.last_error)) err_msg=ER(ER_CHECK_NO_SUCH_TABLE); /* if it was a view will check md5 sum */ @@ -2259,7 +2297,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, protocol->prepare_for_resend(); protocol->store(table_name, system_charset_info); protocol->store(operator_name, system_charset_info); - protocol->store("error", 5, system_charset_info); + protocol->store(STRING_WITH_LEN("error"), system_charset_info); length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY), table_name); protocol->store(buff, length, system_charset_info); @@ -2294,8 +2332,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, protocol->prepare_for_resend(); protocol->store(table_name, system_charset_info); protocol->store(operator_name, system_charset_info); - protocol->store("warning", 7, system_charset_info); - protocol->store("Table is marked as crashed", 26, system_charset_info); + protocol->store(STRING_WITH_LEN("warning"), system_charset_info); + protocol->store(STRING_WITH_LEN("Table is marked as crashed"), + system_charset_info); if (protocol->write()) goto err; } @@ -2319,41 +2358,55 @@ send_result_message: char buf[ERRMSGSIZE+20]; uint length=my_snprintf(buf, ERRMSGSIZE, ER(ER_CHECK_NOT_IMPLEMENTED), operator_name); - protocol->store("note", 4, system_charset_info); + protocol->store(STRING_WITH_LEN("note"), system_charset_info); protocol->store(buf, length, system_charset_info); } break; + case HA_ADMIN_NOT_BASE_TABLE: + { + char buf[ERRMSGSIZE+20]; + uint length= my_snprintf(buf, ERRMSGSIZE, + ER(ER_BAD_TABLE_ERROR), table_name); + protocol->store(STRING_WITH_LEN("note"), system_charset_info); + protocol->store(buf, length, system_charset_info); + } + break; + case HA_ADMIN_OK: - protocol->store("status", 6, system_charset_info); - protocol->store("OK",2, system_charset_info); + protocol->store(STRING_WITH_LEN("status"), system_charset_info); + protocol->store(STRING_WITH_LEN("OK"), system_charset_info); break; case HA_ADMIN_FAILED: - protocol->store("status", 6, system_charset_info); - protocol->store("Operation failed",16, system_charset_info); + protocol->store(STRING_WITH_LEN("status"), system_charset_info); + protocol->store(STRING_WITH_LEN("Operation failed"), + system_charset_info); break; case HA_ADMIN_REJECT: - protocol->store("status", 6, system_charset_info); - protocol->store("Operation need committed state",30, system_charset_info); + protocol->store(STRING_WITH_LEN("status"), system_charset_info); + protocol->store(STRING_WITH_LEN("Operation need committed state"), + system_charset_info); open_for_modify= FALSE; break; case HA_ADMIN_ALREADY_DONE: - protocol->store("status", 6, system_charset_info); - protocol->store("Table is already up to date", 27, system_charset_info); + protocol->store(STRING_WITH_LEN("status"), system_charset_info); + protocol->store(STRING_WITH_LEN("Table is already up to date"), + system_charset_info); break; case HA_ADMIN_CORRUPT: - protocol->store("error", 5, system_charset_info); - protocol->store("Corrupt", 7, system_charset_info); + protocol->store(STRING_WITH_LEN("error"), system_charset_info); + protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info); fatal_error=1; break; case HA_ADMIN_INVALID: - protocol->store("error", 5, system_charset_info); - protocol->store("Invalid argument",16, system_charset_info); + protocol->store(STRING_WITH_LEN("error"), system_charset_info); + protocol->store(STRING_WITH_LEN("Invalid argument"), + system_charset_info); break; case HA_ADMIN_TRY_ALTER: @@ -2389,7 +2442,7 @@ send_result_message: else { /* Hijack the row already in-progress. */ - protocol->store("error", 5, system_charset_info); + protocol->store(STRING_WITH_LEN("error"), system_charset_info); protocol->store(err_msg, system_charset_info); (void)protocol->write(); /* Start off another row for HA_ADMIN_FAILED */ @@ -2406,7 +2459,7 @@ send_result_message: } case HA_ADMIN_WRONG_CHECKSUM: { - protocol->store("note", 4, system_charset_info); + protocol->store(STRING_WITH_LEN("note"), system_charset_info); protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)), system_charset_info); break; @@ -2418,22 +2471,25 @@ send_result_message: uint length=my_snprintf(buf, ERRMSGSIZE, "Unknown - internal error %d during operation", result_code); - protocol->store("error", 5, system_charset_info); + protocol->store(STRING_WITH_LEN("error"), system_charset_info); protocol->store(buf, length, system_charset_info); fatal_error=1; break; } } - if (fatal_error) - table->table->s->version=0; // Force close of table - else if (open_for_modify) + if (table->table) { - pthread_mutex_lock(&LOCK_open); - remove_table_from_cache(thd, table->table->s->db, - table->table->s->table_name, RTFC_NO_FLAG); - pthread_mutex_unlock(&LOCK_open); - /* May be something modified consequently we have to invalidate cache */ - query_cache_invalidate3(thd, table->table, 0); + if (fatal_error) + table->table->s->version=0; // Force close of table + else if (open_for_modify) + { + pthread_mutex_lock(&LOCK_open); + remove_table_from_cache(thd, table->table->s->db, + table->table->s->table_name, RTFC_NO_FLAG); + pthread_mutex_unlock(&LOCK_open); + /* Something may be modified, that's why we have to invalidate cache */ + query_cache_invalidate3(thd, table->table, 0); + } } close_thread_tables(thd); table->table=0; // For query cache @@ -2615,6 +2671,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, char *src_table= table_ident->table.str; int err; bool res= TRUE; + db_type not_used; + TABLE_LIST src_tables_list; DBUG_ENTER("mysql_create_like_table"); src_db= table_ident->db.str ? table_ident->db.str : thd->db; @@ -2662,7 +2720,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, /* create like should be not allowed for Views, Triggers, ... */ - if (mysql_frm_type(src_path) != FRMTYPE_TABLE) + if (mysql_frm_type(thd, src_path, ¬_used) != FRMTYPE_TABLE) { my_error(ER_WRONG_OBJECT, MYF(0), src_db, src_table, "BASE TABLE"); goto err; @@ -3097,8 +3155,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db)) new_db= db; used_fields=create_info->used_fields; + + mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL, FALSE); - mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL); /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */ if (alter_info->tablespace_op != NO_TABLESPACE_OP) DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list, @@ -3337,7 +3396,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change); DBUG_RETURN(TRUE); } - def->def=alter->def; // Use new default + if ((def->def=alter->def)) // Use new default + def->flags&= ~NO_DEFAULT_VALUE_FLAG; + else + def->flags|= NO_DEFAULT_VALUE_FLAG; alter_it.remove(); } } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index dbad8dcffb5..bbc32950c2d 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -20,7 +20,8 @@ #include "sql_trigger.h" #include "parse_file.h" -static const LEX_STRING triggers_file_type= {(char *)"TRIGGERS", 8}; +static const LEX_STRING triggers_file_type= + {(char *) STRING_WITH_LEN("TRIGGERS")}; const char * const triggers_file_ext= ".TRG"; @@ -32,15 +33,39 @@ const char * const triggers_file_ext= ".TRG"; */ static File_option triggers_file_parameters[]= { - {{(char*)"triggers", 8}, + { + {(char *) STRING_WITH_LEN("triggers") }, offsetof(class Table_triggers_list, definitions_list), - FILE_OPTIONS_STRLIST}, - {{(char*)"sql_modes", 13}, + FILE_OPTIONS_STRLIST + }, + { + {(char *) STRING_WITH_LEN("sql_modes") }, offsetof(class Table_triggers_list, definition_modes_list), - FILE_OPTIONS_ULLLIST}, - {{0, 0}, 0, FILE_OPTIONS_STRING} + FILE_OPTIONS_ULLLIST + }, + { + {(char *) STRING_WITH_LEN("definers") }, + offsetof(class Table_triggers_list, definers_list), + FILE_OPTIONS_STRLIST + }, + { { 0, 0 }, 0, FILE_OPTIONS_STRING } +}; + +File_option sql_modes_parameters= +{ + {(char*) STRING_WITH_LEN("sql_modes") }, + offsetof(class Table_triggers_list, definition_modes_list), + FILE_OPTIONS_ULLLIST }; +/* + This must be kept up to date whenever a new option is added to the list + above, as it specifies the number of required parameters of the trigger in + .trg file. +*/ + +static const int TRG_NUM_REQUIRED_PARAMETERS= 4; +static const int TRG_MAX_VERSIONS= 3; /* Structure representing contents of .TRN file which are used to support @@ -52,15 +77,19 @@ struct st_trigname LEX_STRING trigger_table; }; -static const LEX_STRING trigname_file_type= {(char *)"TRIGGERNAME", 11}; +static const LEX_STRING trigname_file_type= + {(char *) STRING_WITH_LEN("TRIGGERNAME")}; const char * const trigname_file_ext= ".TRN"; static File_option trigname_file_parameters[]= { - {{(char*)"trigger_table", 15}, offsetof(struct st_trigname, trigger_table), - FILE_OPTIONS_ESTRING}, - {{0, 0}, 0, FILE_OPTIONS_STRING} + { + {(char *) STRING_WITH_LEN("trigger_table")}, + offsetof(struct st_trigname, trigger_table), + FILE_OPTIONS_ESTRING + }, + { { 0, 0 }, 0, FILE_OPTIONS_STRING } }; @@ -80,6 +109,21 @@ const LEX_STRING trg_event_type_names[]= static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig); +bool handle_old_incorrect_sql_modes(char *&unknown_key, gptr base, + MEM_ROOT *mem_root, + char *end, gptr hook_data); + +class Handle_old_incorrect_sql_modes_hook: public Unknown_key_hook +{ +private: + char *path; +public: + Handle_old_incorrect_sql_modes_hook(char *file_path) + :path(file_path) + {}; + virtual bool process_unknown_string(char *&unknown_key, gptr base, + MEM_ROOT *mem_root, char *end); +}; /* Create or drop trigger for table. @@ -104,6 +148,9 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) { TABLE *table; bool result= TRUE; + LEX_STRING definer_user; + LEX_STRING definer_host; + DBUG_ENTER("mysql_create_or_drop_trigger"); /* @@ -111,6 +158,17 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) But do we want this ? */ + /* + Note that once we will have check for TRIGGER privilege in place we won't + need second part of condition below, since check_access() function also + checks that db is specified. + */ + if (!thd->lex->spname->m_db.length || create && !tables->db_length) + { + my_error(ER_NO_DB_ERROR, MYF(0)); + DBUG_RETURN(TRUE); + } + if (!create && !(tables= add_table_for_trigger(thd, thd->lex->spname))) DBUG_RETURN(TRUE); @@ -131,9 +189,12 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) But a trigger can in theory be used to do nasty things (if it supported DROP for example) so we do the check for privileges. For now there is already a stronger test right above; but when this stronger test will - be removed, the test below will hold. + be removed, the test below will hold. Because triggers have the same + nature as functions regarding binlogging: their body is implicitely + binlogged, so they share the same danger, so trust_function_creators + applies to them too. */ - if (!trust_routine_creators && mysql_bin_log.is_open() && + if (!trust_function_creators && mysql_bin_log.is_open() && !(thd->security_ctx->master_access & SUPER_ACL)) { my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, MYF(0)); @@ -184,7 +245,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) } result= (create ? - table->triggers->create_trigger(thd, tables): + table->triggers->create_trigger(thd, tables, &definer_user, &definer_host): table->triggers->drop_trigger(thd, tables)); end: @@ -192,17 +253,30 @@ end: start_waiting_global_read_lock(thd); if (!result) + { + if (mysql_bin_log.is_open()) { - if (mysql_bin_log.is_open()) + thd->clear_error(); + + String log_query(thd->query, thd->query_length, system_charset_info); + + if (create) { - thd->clear_error(); - /* Such a statement can always go directly to binlog, no trans cache */ - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); + log_query.set((char *) 0, 0, system_charset_info); /* reset log_query */ + + log_query.append(STRING_WITH_LEN("CREATE ")); + append_definer(thd, &log_query, &definer_user, &definer_host); + log_query.append(thd->lex->trigger_definition_begin); } - send_ok(thd); + + /* Such a statement can always go directly to binlog, no trans cache. */ + Query_log_event qinfo(thd, log_query.ptr(), log_query.length(), 0, FALSE); + mysql_bin_log.write(&qinfo); } + send_ok(thd); + } + DBUG_RETURN(result); } @@ -212,15 +286,29 @@ end: SYNOPSIS create_trigger() - thd - current thread context (including trigger definition in LEX) - tables - table list containing one open table for which trigger is - created. + thd - current thread context (including trigger definition in + LEX) + tables - table list containing one open table for which the + trigger is created. + definer_user - [out] after a call it points to 0-terminated string, + which contains user name part of the actual trigger + definer. The caller is responsible to provide memory for + storing LEX_STRING object. + definer_host - [out] after a call it points to 0-terminated string, + which contains host name part of the actual trigger + definer. The caller is responsible to provide memory for + storing LEX_STRING object. + + NOTE + Assumes that trigger name is fully qualified. RETURN VALUE False - success True - error */ -bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables) +bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, + LEX_STRING *definer_user, + LEX_STRING *definer_host) { LEX *lex= thd->lex; TABLE *table= tables->table; @@ -229,14 +317,14 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables) LEX_STRING dir, file, trigname_file; LEX_STRING *trg_def, *name; ulonglong *trg_sql_mode; + char trg_definer_holder[HOSTNAME_LENGTH + USERNAME_LENGTH + 2]; + LEX_STRING *trg_definer; Item_trigger_field *trg_field; struct st_trigname trigname; /* Trigger must be in the same schema as target table. */ - if (my_strcasecmp(table_alias_charset, table->s->db, - lex->spname->m_db.str ? lex->spname->m_db.str : - thd->db)) + if (my_strcasecmp(table_alias_charset, table->s->db, lex->spname->m_db.str)) { my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0)); return 1; @@ -250,6 +338,31 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables) } /* + Definer attribute of the Lex instance is always set in sql_yacc.yy when + trigger is created. + */ + + DBUG_ASSERT(lex->definer); + + /* + If the specified definer differs from the current user, we should check + that the current user has SUPER privilege (in order to create trigger + under another user one must have SUPER privilege). + */ + + if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) || + my_strcasecmp(system_charset_info, + lex->definer->host.str, + thd->security_ctx->priv_host)) + { + if (check_global_access(thd, SUPER_ACL)) + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); + return TRUE; + } + } + + /* Let us check if all references to fields in old/new versions of row in this trigger are ok. @@ -318,15 +431,39 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables) definitions_list.push_back(trg_def, &table->mem_root) || !(trg_sql_mode= (ulonglong*)alloc_root(&table->mem_root, sizeof(ulonglong))) || - definition_modes_list.push_back(trg_sql_mode, &table->mem_root)) + definition_modes_list.push_back(trg_sql_mode, &table->mem_root) || + !(trg_definer= (LEX_STRING*) alloc_root(&table->mem_root, + sizeof(LEX_STRING))) || + definers_list.push_back(trg_definer, &table->mem_root)) goto err_with_cleanup; trg_def->str= thd->query; trg_def->length= thd->query_length; *trg_sql_mode= thd->variables.sql_mode; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + if (!is_acl_user(lex->definer->host.str, + lex->definer->user.str)) + { + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_NO_SUCH_USER, + ER(ER_NO_SUCH_USER), + lex->definer->user.str, + lex->definer->host.str); + } +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ + + *definer_user= lex->definer->user; + *definer_host= lex->definer->host; + + trg_definer->str= trg_definer_holder; + trg_definer->length= strxmov(trg_definer->str, definer_user->str, "@", + definer_host->str, NullS) - trg_definer->str; + if (!sql_create_definition_file(&dir, &file, &triggers_file_type, - (gptr)this, triggers_file_parameters, 3)) + (gptr)this, triggers_file_parameters, + TRG_MAX_VERSIONS)) return 0; err_with_cleanup: @@ -403,12 +540,14 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables) List_iterator_fast<LEX_STRING> it_name(names_list); List_iterator<LEX_STRING> it_def(definitions_list); List_iterator<ulonglong> it_mod(definition_modes_list); + List_iterator<LEX_STRING> it_definer(definers_list); char path[FN_REFLEN]; while ((name= it_name++)) { it_def++; it_mod++; + it_definer++; if (my_strcasecmp(table_alias_charset, lex->spname->m_name.str, name->str) == 0) @@ -419,6 +558,7 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables) */ it_def.remove(); it_mod.remove(); + it_definer.remove(); if (definitions_list.is_empty()) { @@ -446,7 +586,7 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables) if (sql_create_definition_file(&dir, &file, &triggers_file_type, (gptr)this, triggers_file_parameters, - 3)) + TRG_MAX_VERSIONS)) return 1; } @@ -568,7 +708,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, DBUG_RETURN(0); /* - File exists so we got to load triggers + File exists so we got to load triggers. FIXME: A lot of things to do here e.g. how about other funcs and being more paranoical ? */ @@ -579,18 +719,24 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, { Table_triggers_list *triggers= new (&table->mem_root) Table_triggers_list(table); + Handle_old_incorrect_sql_modes_hook sql_modes_hook(path.str); if (!triggers) DBUG_RETURN(1); /* - We don't have sql_modes in old versions of .TRG file, so we should - initialize list for safety. + We don't have the following attributes in old versions of .TRG file, so + we should initialize the list for safety: + - sql_modes; + - definers; */ triggers->definition_modes_list.empty(); + triggers->definers_list.empty(); if (parser->parse((gptr)triggers, &table->mem_root, - triggers_file_parameters, 2)) + triggers_file_parameters, + TRG_NUM_REQUIRED_PARAMETERS, + &sql_modes_hook)) DBUG_RETURN(1); List_iterator_fast<LEX_STRING> it(triggers->definitions_list); @@ -612,7 +758,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, DBUG_RETURN(1); // EOM } *trg_sql_mode= global_system_variables.sql_mode; - while ((trg_create_str= it++)) + while (it++) { if (triggers->definition_modes_list.push_back(trg_sql_mode, &table->mem_root)) @@ -623,8 +769,43 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, it.rewind(); } + if (triggers->definers_list.is_empty() && + !triggers->definitions_list.is_empty()) + { + /* + It is old file format => we should fill list of definers. + + If there is no definer information, we should not switch context to + definer when checking privileges. I.e. privileges for such triggers + are checked for "invoker" rather than for "definer". + */ + + LEX_STRING *trg_definer; + + if (! (trg_definer= (LEX_STRING*)alloc_root(&table->mem_root, + sizeof(LEX_STRING)))) + DBUG_RETURN(1); // EOM + + trg_definer->str= (char*) ""; + trg_definer->length= 0; + + while (it++) + { + if (triggers->definers_list.push_back(trg_definer, + &table->mem_root)) + { + DBUG_RETURN(1); // EOM + } + } + + it.rewind(); + } + DBUG_ASSERT(triggers->definition_modes_list.elements == triggers->definitions_list.elements); + DBUG_ASSERT(triggers->definers_list.elements == + triggers->definitions_list.elements); + table->triggers= triggers; /* @@ -647,7 +828,10 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, char *trg_name_buff; List_iterator_fast<ulonglong> itm(triggers->definition_modes_list); + List_iterator_fast<LEX_STRING> it_definer(triggers-> + definers_list); LEX *old_lex= thd->lex, lex; + sp_rcontext *save_spcont= thd->spcont; ulong save_sql_mode= thd->variables.sql_mode; thd->lex= &lex; @@ -659,22 +843,56 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, while ((trg_create_str= it++)) { trg_sql_mode= itm++; + LEX_STRING *trg_definer= it_definer++; thd->variables.sql_mode= (ulong)*trg_sql_mode; lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length); + thd->spcont= 0; if (yyparse((void *)thd) || thd->is_fatal_error) { /* - Free lex associated resources + Free lex associated resources. QQ: Do we really need all this stuff here ? */ delete lex.sphead; goto err_with_lex_cleanup; } - lex.sphead->m_sql_mode= *trg_sql_mode; + lex.sphead->set_info(0, 0, &lex.sp_chistics, *trg_sql_mode); + triggers->bodies[lex.trg_chistics.event] [lex.trg_chistics.action_time]= lex.sphead; + + if (!trg_definer->length) + { + /* + This trigger was created/imported from the previous version of + MySQL, which does not support triggers definers. We should emit + warning here. + */ + + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRG_NO_DEFINER, ER(ER_TRG_NO_DEFINER), + (const char*) db, + (const char*) lex.sphead->m_name.str); + + /* + Set definer to the '' to correct displaying in the information + schema. + */ + + lex.sphead->set_definer("", 0); + + /* + Triggers without definer information are executed under the + authorization of the invoker. + */ + + lex.sphead->m_chistics->suid= SP_IS_NOT_SUID; + } + else + lex.sphead->set_definer(trg_definer->str, trg_definer->length); + if (triggers->names_list.push_back(&lex.sphead->m_name, &table->mem_root)) goto err_with_lex_cleanup; @@ -701,11 +919,16 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, trg_field= trg_field->next_trg_field) trg_field->setup_field(thd, table); + triggers->m_spec_var_used[lex.trg_chistics.event] + [lex.trg_chistics.action_time]= + lex.trg_table_fields.first ? TRUE : FALSE; + lex_end(&lex); } thd->db= save_db.str; thd->db_length= save_db.length; thd->lex= old_lex; + thd->spcont= save_spcont; thd->variables.sql_mode= save_sql_mode; DBUG_RETURN(0); @@ -714,6 +937,7 @@ err_with_lex_cleanup: // QQ: anything else ? lex_end(&lex); thd->lex= old_lex; + thd->spcont= save_spcont; thd->variables.sql_mode= save_sql_mode; thd->db= save_db.str; thd->db_length= save_db.length; @@ -744,6 +968,9 @@ err_with_lex_cleanup: name - returns name of trigger stmt - returns statement of trigger sql_mode - returns sql_mode of trigger + definer_user - returns definer/creator of trigger. The caller is + responsible to allocate enough space for storing definer + information. RETURN VALUE False - success @@ -754,7 +981,8 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event, trg_action_time_type time_type, LEX_STRING *trigger_name, LEX_STRING *trigger_stmt, - ulong *sql_mode) + ulong *sql_mode, + LEX_STRING *definer) { sp_head *body; DBUG_ENTER("get_trigger_info"); @@ -763,6 +991,18 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event, *trigger_name= body->m_name; *trigger_stmt= body->m_body; *sql_mode= body->m_sql_mode; + + if (body->m_chistics->suid == SP_IS_NOT_SUID) + { + definer->str[0]= 0; + definer->length= 0; + } + else + { + definer->length= strxmov(definer->str, body->m_definer_user.str, "@", + body->m_definer_host.str, NullS) - definer->str; + } + DBUG_RETURN(0); } DBUG_RETURN(1); @@ -785,7 +1025,6 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event, static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) { - const char *db= !trig->m_db.str ? thd->db : trig->m_db.str; LEX *lex= thd->lex; char path_buff[FN_REFLEN]; LEX_STRING path; @@ -793,7 +1032,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) struct st_trigname trigname; DBUG_ENTER("add_table_for_trigger"); - strxnmov(path_buff, FN_REFLEN, mysql_data_home, "/", db, "/", + strxnmov(path_buff, FN_REFLEN, mysql_data_home, "/", trig->m_db.str, "/", trig->m_name.str, trigname_file_ext, NullS); path.length= unpack_filename(path_buff, path_buff); path.str= path_buff; @@ -815,13 +1054,14 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) } if (parser->parse((gptr)&trigname, thd->mem_root, - trigname_file_parameters, 1)) + trigname_file_parameters, 1, + &file_parser_dummy_hook)) DBUG_RETURN(0); /* We need to reset statement table list to be PS/SP friendly. */ lex->query_tables= 0; lex->query_tables_last= &lex->query_tables; - DBUG_RETURN(sp_add_to_query_tables(thd, lex, db, + DBUG_RETURN(sp_add_to_query_tables(thd, lex, trig->m_db.str, trigname.trigger_table.str, TL_WRITE)); } @@ -897,9 +1137,10 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event, trg_action_time_type time_type, bool old_row_is_record1) { - int res= 0; + bool err_status= FALSE; + sp_head *sp_trigger= bodies[event][time_type]; - if (bodies[event][time_type]) + if (sp_trigger) { Sub_statement_state statement_state; @@ -914,15 +1155,119 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event, old_field= table->field; } +#ifndef NO_EMBEDDED_ACCESS_CHECKS + Security_context *save_ctx; + + if (sp_change_security_context(thd, sp_trigger, &save_ctx)) + return TRUE; + /* - FIXME: We should juggle with security context here (because trigger - should be invoked with creator rights). + NOTE: TRIGGER_ACL should be used below. */ + if (check_global_access(thd, SUPER_ACL)) + { + sp_restore_security_context(thd, save_ctx); + return TRUE; + } + + /* + If the trigger uses special variables (NEW/OLD), check that we have + SELECT and UPDATE privileges on the subject table. + */ + + if (is_special_var_used(event, time_type)) + { + TABLE_LIST table_list, **save_query_tables_own_last; + bzero((char *) &table_list, sizeof (table_list)); + table_list.db= (char *) table->s->db; + table_list.db_length= strlen(table_list.db); + table_list.table_name= (char *) table->s->table_name; + table_list.table_name_length= strlen(table_list.table_name); + table_list.alias= (char *) table->alias; + table_list.table= table; + save_query_tables_own_last= thd->lex->query_tables_own_last; + thd->lex->query_tables_own_last= 0; + + err_status= check_table_access(thd, SELECT_ACL | UPDATE_ACL, + &table_list, 0); + thd->lex->query_tables_own_last= save_query_tables_own_last; + if (err_status) + { + sp_restore_security_context(thd, save_ctx); + return TRUE; + } + } + +#endif // NO_EMBEDDED_ACCESS_CHECKS + thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER); - res= bodies[event][time_type]->execute_function(thd, 0, 0, 0); + err_status= sp_trigger->execute_function(thd, 0, 0, 0); thd->restore_sub_statement_state(&statement_state); + +#ifndef NO_EMBEDDED_ACCESS_CHECKS + sp_restore_security_context(thd, save_ctx); +#endif // NO_EMBEDDED_ACCESS_CHECKS } - return res; + return err_status; +} + + +/* + Trigger BUG#14090 compatibility hook + + SYNOPSIS + Handle_old_incorrect_sql_modes_hook::process_unknown_string() + unknown_key [in/out] reference on the line with unknown + parameter and the parsing point + base [in] base address for parameter writing (structure + like TABLE) + mem_root [in] MEM_ROOT for parameters allocation + end [in] the end of the configuration + + NOTE: this hook process back compatibility for incorrectly written + sql_modes parameter (see BUG#14090). + + RETURN + FALSE OK + TRUE Error +*/ + +#define INVALID_SQL_MODES_LENGTH 13 + +bool +Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key, + gptr base, + MEM_ROOT *mem_root, + char *end) +{ + DBUG_ENTER("handle_old_incorrect_sql_modes"); + DBUG_PRINT("info", ("unknown key:%60s", unknown_key)); + + if (unknown_key + INVALID_SQL_MODES_LENGTH + 1 < end && + unknown_key[INVALID_SQL_MODES_LENGTH] == '=' && + !memcmp(unknown_key, STRING_WITH_LEN("sql_modes"))) + { + char *ptr= unknown_key + INVALID_SQL_MODES_LENGTH + 1; + + DBUG_PRINT("info", ("sql_modes affected by BUG#14090 detected")); + push_warning_printf(current_thd, + MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_OLD_FILE_FORMAT, + ER(ER_OLD_FILE_FORMAT), + (char *)path, "TRIGGER"); + if (get_file_options_ulllist(ptr, end, unknown_key, base, + &sql_modes_parameters, mem_root)) + { + DBUG_RETURN(TRUE); + } + /* + Set parsing pointer to the last symbol of string (\n) + 1) to avoid problem with \0 in the junk after sql_modes + 2) to speed up skipping this line by parser. + */ + unknown_key= ptr-1; + } + DBUG_RETURN(FALSE); } diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index c1d1f8d0e9e..51002683897 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -55,6 +55,12 @@ class Table_triggers_list: public Sql_alloc */ LEX_STRING sroutines_key; + /* + is_special_var_used specifies whether trigger body contains special + variables (NEW/OLD). + */ + bool m_spec_var_used[TRG_EVENT_MAX][TRG_ACTION_MAX]; + public: /* Field responsible for storing triggers definitions in file. @@ -66,6 +72,8 @@ public: */ List<ulonglong> definition_modes_list; + List<LEX_STRING> definers_list; + Table_triggers_list(TABLE *table_arg): record1_field(0), table(table_arg) { @@ -73,7 +81,9 @@ public: } ~Table_triggers_list(); - bool create_trigger(THD *thd, TABLE_LIST *table); + bool create_trigger(THD *thd, TABLE_LIST *table, + LEX_STRING *definer_user, + LEX_STRING *definer_host); bool drop_trigger(THD *thd, TABLE_LIST *table); bool process_triggers(THD *thd, trg_event_type event, trg_action_time_type time_type, @@ -81,7 +91,8 @@ public: bool get_trigger_info(THD *thd, trg_event_type event, trg_action_time_type time_type, LEX_STRING *trigger_name, LEX_STRING *trigger_stmt, - ulong *sql_mode); + ulong *sql_mode, + LEX_STRING *definer); static bool check_n_load(THD *thd, const char *db, const char *table_name, TABLE *table, bool names_only); @@ -98,11 +109,16 @@ public: return test(bodies[TRG_EVENT_UPDATE][TRG_ACTION_BEFORE]); } + inline bool is_special_var_used(int event, int action_time) const + { + return m_spec_var_used[event][action_time]; + } + void set_table(TABLE *new_table); friend class Item_trigger_field; - friend void sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, - Table_triggers_list *triggers); + friend int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, + TABLE_LIST *table); private: bool prepare_record1_accessors(TABLE *table); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index ba3c598a784..40e5a9a00cf 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -159,6 +159,7 @@ void udf_init() DBUG_VOID_RETURN; } initialized = 1; + new_thd->thread_stack= (char*) &new_thd; new_thd->store_globals(); new_thd->db= my_strdup("mysql", MYF(0)); new_thd->db_length=5; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index a8e21177338..2ff8a4bc244 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -121,7 +121,7 @@ int mysql_update(THD *thd, bool safe_update= thd->options & OPTION_SAFE_UPDATES; bool used_key_is_modified, transactional_table; int res; - int error=0; + int error; uint used_index= MAX_KEY; bool need_sort= TRUE; #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -195,6 +195,7 @@ int mysql_update(THD *thd, /* Check the fields we are going to modify */ #ifndef NO_EMBEDDED_ACCESS_CHECKS table_list->grant.want_privilege= table->grant.want_privilege= want_privilege; + table_list->register_want_access(want_privilege); #endif if (setup_fields_with_no_wrap(thd, 0, fields, 1, 0, 0)) DBUG_RETURN(1); /* purecov: inspected */ @@ -227,11 +228,18 @@ int mysql_update(THD *thd, DBUG_RETURN(1); /* purecov: inspected */ } + if (conds) + { + Item::cond_result cond_value; + conds= remove_eq_conds(thd, conds, &cond_value); + if (cond_value == Item::COND_FALSE) + limit= 0; // Impossible WHERE + } // Don't count on usage of 'only index' when calculating which key to use table->used_keys.clear_all(); select= make_select(table, 0, 0, conds, 0, &error); - if (error || - (select && select->check_quick(thd, safe_update, limit)) || !limit) + if (error || !limit || + (select && select->check_quick(thd, safe_update, limit))) { delete select; free_underlaid_joins(thd, select_lex); @@ -244,7 +252,7 @@ int mysql_update(THD *thd, } if (!select && limit != HA_POS_ERROR) { - if (MAX_KEY != (used_index= get_index_for_order(table, order, limit))) + if ((used_index= get_index_for_order(table, order, limit)) != MAX_KEY) need_sort= FALSE; } /* If running in safe sql mode, don't allow updates without keys */ @@ -267,14 +275,14 @@ int mysql_update(THD *thd, used_key_is_modified= (!select->quick->unique_key_range() && select->quick->check_if_keys_used(&fields)); } - else if (used_index != MAX_KEY) + else { - used_key_is_modified= check_if_key_used(table, used_index, fields); + used_key_is_modified= 0; + if (used_index == MAX_KEY) // no index for sort order + used_index= table->file->key_used_on_scan; + if (used_index != MAX_KEY) + used_key_is_modified= check_if_key_used(table, used_index, fields); } - else if ((used_index=table->file->key_used_on_scan) < MAX_KEY) - used_key_is_modified=check_if_key_used(table, used_index, fields); - else - used_key_is_modified=0; if (used_key_is_modified || order) { @@ -286,11 +294,11 @@ int mysql_update(THD *thd, if (used_index < MAX_KEY && old_used_keys.is_set(used_index)) { table->key_read=1; - table->file->extra(HA_EXTRA_KEYREAD); //todo: psergey: check + table->file->extra(HA_EXTRA_KEYREAD); } /* note: can actually avoid sorting below.. */ - if (order && need_sort) + if (order && (need_sort || used_key_is_modified)) { /* Doing an ORDER BY; Let filesort find and sort the rows we are going @@ -300,6 +308,7 @@ int mysql_update(THD *thd, SORT_FIELD *sortorder; ha_rows examined_rows; + used_index= MAX_KEY; // For call to init_read_record() table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), MYF(MY_FAE | MY_ZEROFILL)); if (!(sortorder=make_unireg_sortorder(order, &length)) || @@ -334,7 +343,7 @@ int mysql_update(THD *thd, /* If quick select is used, initialize it before retrieving rows. */ if (select && select->quick && select->quick->reset()) goto err; - if (used_index == MAX_KEY) + if (used_index == MAX_KEY || (select && select->quick)) init_read_record(&info,thd,table,select,0,1); else init_read_record_idx(&info, thd, table, 1, used_index); @@ -366,10 +375,7 @@ int mysql_update(THD *thd, error= 1; // Aborted limit= tmp_limit; end_read_record(&info); - - /* if we got here we must not use index in the main update loop below */ - used_index= MAX_KEY; - + /* Change select to use tempfile */ if (select) { @@ -459,7 +465,12 @@ int mysql_update(THD *thd, } else if (!ignore || error != HA_ERR_FOUND_DUPP_KEY) { - thd->fatal_error(); // Force error message + /* + If (ignore && error == HA_ERR_FOUND_DUPP_KEY) we don't have to + do anything; otherwise... + */ + if (error != HA_ERR_FOUND_DUPP_KEY) + thd->fatal_error(); /* Other handler errors are fatal */ table->file->print_error(error,MYF(0)); error= 1; break; @@ -516,6 +527,7 @@ int mysql_update(THD *thd, if (!transactional_table) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } + free_underlaid_joins(thd, select_lex); if (transactional_table) { if (ha_autocommit_or_rollback(thd, error >= 0)) @@ -528,7 +540,6 @@ int mysql_update(THD *thd, thd->lock=0; } - free_underlaid_joins(thd, select_lex); if (error < 0) { char buff[STRING_BUFFER_USUAL_SIZE]; @@ -584,12 +595,13 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, #ifndef NO_EMBEDDED_ACCESS_CHECKS table_list->grant.want_privilege= table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); + table_list->register_want_access(SELECT_ACL); #endif bzero((char*) &tables,sizeof(tables)); // For ORDER BY tables.table= table; tables.alias= table_list->alias; - thd->allow_sum_func= 0; + thd->lex->allow_sum_func= 0; if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, table_list, conds, &select_lex->leaf_tables, @@ -604,7 +616,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, /* Check that we are not using table that we are updating in a sub select */ { TABLE_LIST *duplicate; - if ((duplicate= unique_table(table_list, table_list->next_global))) + if ((duplicate= unique_table(thd, table_list, table_list->next_global))) { update_non_unique_table_error(table_list, "UPDATE", duplicate); my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name); @@ -827,7 +839,7 @@ reopen_tables: tl->lock_type != TL_READ_NO_INSERT) { TABLE_LIST *duplicate; - if ((duplicate= unique_table(tl, table_list))) + if ((duplicate= unique_table(thd, tl, table_list))) { update_non_unique_table_error(table_list, "UPDATE", duplicate); DBUG_RETURN(TRUE); @@ -1014,8 +1026,7 @@ int multi_update::prepare(List<Item> ¬_used_values, { TABLE *table=table_ref->table; if (!(tables_to_update & table->map) && - find_table_in_local_list(update_tables, table_ref->db, - table_ref->table_name)) + unique_table(thd, table_ref, update_tables)) table->no_cache= 1; // Disable row cache } DBUG_RETURN(thd->is_fatal_error != 0); @@ -1252,7 +1263,12 @@ bool multi_update::send_data(List<Item> ¬_used_values) updated--; if (!ignore || error != HA_ERR_FOUND_DUPP_KEY) { - thd->fatal_error(); // Force error message + /* + If (ignore && error == HA_ERR_FOUND_DUPP_KEY) we don't have to + do anything; otherwise... + */ + if (error != HA_ERR_FOUND_DUPP_KEY) + thd->fatal_error(); /* Other handler errors are fatal */ table->file->print_error(error,MYF(0)); DBUG_RETURN(1); } @@ -1273,22 +1289,23 @@ bool multi_update::send_data(List<Item> ¬_used_values) int error; TABLE *tmp_table= tmp_tables[offset]; fill_record(thd, tmp_table->field+1, *values_for_table[offset], 1); - found++; /* Store pointer to row */ memcpy((char*) tmp_table->field[0]->ptr, (char*) table->file->ref, table->file->ref_length); /* Write row, ignoring duplicated updates to a row */ - if ((error= tmp_table->file->write_row(tmp_table->record[0])) && - (error != HA_ERR_FOUND_DUPP_KEY && - error != HA_ERR_FOUND_DUPP_UNIQUE)) + if (error= tmp_table->file->write_row(tmp_table->record[0])) { - if (create_myisam_from_heap(thd, tmp_table, tmp_table_param + offset, - error, 1)) + if (error != HA_ERR_FOUND_DUPP_KEY && + error != HA_ERR_FOUND_DUPP_UNIQUE && + create_myisam_from_heap(thd, tmp_table, + tmp_table_param + offset, error, 1)) { do_update=0; DBUG_RETURN(1); // Not a table_is_full error } } + else + found++; } } DBUG_RETURN(0); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 858f0c2520e..4f62a80cfd4 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -214,29 +214,28 @@ bool mysql_create_view(THD *thd, - same as current user - current user has SUPER_ACL */ - if (strcmp(lex->create_view_definer->user.str, + if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 || my_strcasecmp(system_charset_info, - lex->create_view_definer->host.str, + lex->definer->host.str, thd->security_ctx->priv_host) != 0) { if (!(thd->security_ctx->master_access & SUPER_ACL)) { - my_error(ER_VIEW_OTHER_USER, MYF(0), lex->create_view_definer->user.str, - lex->create_view_definer->host.str); + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); res= TRUE; goto err; } else { - if (!is_acl_user(lex->create_view_definer->host.str, - lex->create_view_definer->user.str)) + if (!is_acl_user(lex->definer->host.str, + lex->definer->user.str)) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_NO_SUCH_USER, ER(ER_NO_SUCH_USER), - lex->create_view_definer->user.str, - lex->create_view_definer->host.str); + lex->definer->user.str, + lex->definer->host.str); } } } @@ -351,15 +350,6 @@ bool mysql_create_view(THD *thd, */ for (tbl= lex->query_tables; tbl; tbl= tbl->next_global) { - /* is this table temporary and is not view? */ - if (tbl->table->s->tmp_table != NO_TMP_TABLE && !tbl->view && - !tbl->schema_table) - { - my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias); - res= TRUE; - goto err; - } - /* is this table view and the same view which we creates now? */ if (tbl->view && strcmp(tbl->view_db.str, view->db) == 0 && @@ -371,11 +361,29 @@ bool mysql_create_view(THD *thd, } /* - Copy the privileges of the underlying VIEWs which were filled by - fill_effective_table_privileges - (they were not copied at derived tables processing) + tbl->table can be NULL when tbl is a placeholder for a view + that is indirectly referenced via a stored function from the + view being created. We don't check these indirectly + referenced views in CREATE VIEW so they don't have table + object. */ - tbl->table->grant.privilege= tbl->grant.privilege; + if (tbl->table) + { + /* is this table temporary and is not view? */ + if (tbl->table->s->tmp_table != NO_TMP_TABLE && !tbl->view && + !tbl->schema_table) + { + my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias); + res= TRUE; + goto err; + } + /* + Copy the privileges of the underlying VIEWs which were filled by + fill_effective_table_privileges + (they were not copied at derived tables processing) + */ + tbl->table->grant.privilege= tbl->grant.privilege; + } } /* prepare select to resolve all fields */ @@ -496,7 +504,7 @@ static const int num_view_backups= 3; static File_option view_parameters[]= {{{(char*) STRING_WITH_LEN("query")}, offsetof(TABLE_LIST, query), - FILE_OPTIONS_STRING}, + FILE_OPTIONS_ESTRING}, {{(char*) STRING_WITH_LEN("md5")}, offsetof(TABLE_LIST, md5), FILE_OPTIONS_STRING}, @@ -624,7 +632,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, TODO: special cascade/restrict procedure for alter? */ if (parser->parse((gptr)view, thd->mem_root, - view_parameters + revision_number_position, 1)) + view_parameters + revision_number_position, 1, + &file_parser_dummy_hook)) { DBUG_RETURN(thd->net.report_error? -1 : 0); } @@ -641,10 +650,9 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, /* fill structure */ view->query.str= (char*)str.ptr(); view->query.length= str.length()-1; // we do not need last \0 - view->source.str= thd->lex->create_view_select_start; + view->source.str= thd->query + thd->lex->create_view_select_start; view->source.length= (thd->query_length - - (thd->lex->create_view_select_start - - thd->lex->create_view_start)); + thd->lex->create_view_select_start); view->file_version= 1; view->calc_md5(md5); view->md5.str= md5; @@ -658,8 +666,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; } view->algorithm= lex->create_view_algorithm; - view->definer.user= lex->create_view_definer->user; - view->definer.host= lex->create_view_definer->host; + view->definer.user= lex->definer->user; + view->definer.host= lex->definer->host; view->view_suid= lex->create_view_suid; view->with_check= lex->create_view_check; if ((view->updatable_view= (can_be_merged && @@ -722,44 +730,59 @@ loop_out: } + /* read VIEW .frm and create structures SYNOPSIS mysql_make_view() - parser - parser object; - table - TABLE_LIST structure for filling + thd Thread handler + parser parser object + table TABLE_LIST structure for filling RETURN 0 ok 1 error */ -my_bool -mysql_make_view(File_parser *parser, TABLE_LIST *table) +bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table) { + SELECT_LEX *end, *view_select; + LEX *old_lex, *lex; + Query_arena *arena, backup; + int res; + bool result; DBUG_ENTER("mysql_make_view"); - DBUG_PRINT("info", ("table=%p (%s)", table, table->table_name)); + DBUG_PRINT("info", ("table: 0x%lx (%s)", (ulong) table, table->table_name)); if (table->view) { + /* + It's an execution of a PS/SP and the view has already been unfolded + into a list of used tables. Now we only need to update the information + about granted privileges in the view tables with the actual data + stored in MySQL privilege system. We don't need to restore the + required privileges (by calling register_want_access) because they has + not changed since PREPARE or the previous execution: the only case + when this information is changed is execution of UPDATE on a view, but + the original want_access is restored in its end. + */ + if (!table->prelocking_placeholder && table->prepare_security(thd)) + { + DBUG_RETURN(1); + } DBUG_PRINT("info", ("VIEW %s.%s is already processed on previous PS/SP execution", table->view_db.str, table->view_name.str)); DBUG_RETURN(0); } - SELECT_LEX *end; - THD *thd= current_thd; - LEX *old_lex= thd->lex, *lex; - SELECT_LEX *view_select; - int res= 0; - /* For now we assume that tables will not be changed during PS life (it will be TRUE as far as we make new table cache). */ - Query_arena *arena= thd->stmt_arena, backup; + old_lex= thd->lex; + arena= thd->stmt_arena; if (arena->is_conventional()) arena= 0; else @@ -769,7 +792,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) if (!table->timestamp.str) table->timestamp.str= table->timestamp_buffer; /* prepare default values for old format */ - table->view_suid= 1; + table->view_suid= TRUE; table->definer.user.str= table->definer.host.str= 0; table->definer.user.length= table->definer.host.length= 0; @@ -778,7 +801,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) be used here */ if (parser->parse((gptr)table, thd->mem_root, view_parameters, - required_view_parameters)) + required_view_parameters, &file_parser_dummy_hook)) goto err; /* @@ -792,7 +815,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER), table->db, table->table_name); - if (default_view_definer(thd->security_ctx, &table->definer)) + if (get_default_definer(thd, &table->definer)) goto err; } @@ -880,6 +903,10 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) goto err; } + + if (!(table->view_tables= + (List<TABLE_LIST>*) new(thd->mem_root) List<TABLE_LIST>)) + goto err; /* mark to avoid temporary table using and put view reference and find last view table @@ -890,6 +917,22 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) { tbl->skip_temporary= 1; tbl->belong_to_view= top_view; + tbl->referencing_view= table; + /* + First we fill want_privilege with SELECT_ACL (this is needed for the + tables which belongs to view subqueries and temporary table views, + then for the merged view underlying tables we will set wanted + privileges of top_view + */ + tbl->grant.want_privilege= SELECT_ACL; + /* + After unfolding the view we lose the list of tables referenced in it + (we will have only a list of underlying tables in case of MERGE + algorithm, which does not include the tables referenced from + subqueries used in view definition). + Let's build a list of all tables referenced in the view. + */ + table->view_tables->push_back(tbl); } /* @@ -915,16 +958,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) } /* - Let us set proper lock type for tables of the view's main select - since we may want to perform update or insert on view. This won't - work for view containing union. But this is ok since we don't - allow insert and update on such views anyway. - */ - if (!lex->select_lex.next_select()) - for (tbl= lex->select_lex.get_table_list(); tbl; tbl= tbl->next_local) - tbl->lock_type= table->lock_type; - - /* If we are opening this view as part of implicit LOCK TABLES, then this view serves as simple placeholder and we should not continue further processing. @@ -932,7 +965,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) if (table->prelocking_placeholder) goto ok2; - old_lex->derived_tables|= DERIVED_VIEW; + old_lex->derived_tables|= (DERIVED_VIEW | lex->derived_tables); /* move SQL_NO_CACHE & Co to whole query */ old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query && @@ -941,6 +974,37 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) if (view_select->options & OPTION_TO_QUERY_CACHE) old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE; + if (table->view_suid) + { + /* + Prepare a security context to check underlying objects of the view + */ + Security_context *save_security_ctx= thd->security_ctx; + if (!(table->view_sctx= (Security_context *) + thd->stmt_arena->alloc(sizeof(Security_context)))) + goto err; + /* Assign the context to the tables referenced in the view */ + for (tbl= view_tables; tbl; tbl= tbl->next_global) + tbl->security_ctx= table->view_sctx; + /* assign security context to SELECT name resolution contexts of view */ + for(SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + sl->context.security_ctx= table->view_sctx; + } + + /* + Setup an error processor to hide error messages issued by stored + routines referenced in the view + */ + for (SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + { + sl->context.error_processor= &view_error_processor; + sl->context.error_processor_data= (void *)table; + } + /* check MERGE algorithm ability - algorithm is not explicit TEMPORARY TABLE @@ -962,24 +1026,28 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) table->updatable= (table->updatable_view != 0); table->effective_with_check= old_lex->get_effective_with_check(table); + table->merge_underlying_list= view_tables; + /* + Let us set proper lock type for tables of the view's main select + since we may want to perform update or insert on view. This won't + work for view containing union. But this is ok since we don't + allow insert and update on such views anyway. + + Also we fill correct wanted privileges. + */ + for (tbl= table->merge_underlying_list; tbl; tbl= tbl->next_local) + { + tbl->lock_type= table->lock_type; + tbl->grant.want_privilege= top_view->grant.orig_want_privilege; + } /* prepare view context */ - lex->select_lex.context.resolve_in_table_list_only(table->ancestor= - view_tables); + lex->select_lex.context.resolve_in_table_list_only(view_tables); lex->select_lex.context.outer_context= 0; lex->select_lex.context.select_lex= table->select_lex; lex->select_lex.select_n_having_items+= table->select_lex->select_n_having_items; - /* do not check privileges & hide errors for view underlyings */ - for (SELECT_LEX *sl= lex->all_selects_list; - sl; - sl= sl->next_select_in_list()) - { - sl->context.check_privileges= FALSE; - sl->context.error_processor= &view_error_processor; - sl->context.error_processor_data= (void *)table; - } /* Tables of the main select of the view should be marked as belonging to the same select as original view (again we can use LEX::select_lex @@ -1012,7 +1080,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) } } - /* Store WHERE clause for post-processing in setup_ancestor */ + /* Store WHERE clause for post-processing in setup_underlying */ table->where= view_select->where; /* Add subqueries units to SELECT into which we merging current view. @@ -1073,20 +1141,21 @@ ok: (st_select_lex_node**)&old_lex->all_selects_list; ok2: - if (arena) - thd->restore_active_arena(arena, &backup); if (!old_lex->time_zone_tables_used && thd->lex->time_zone_tables_used) old_lex->time_zone_tables_used= thd->lex->time_zone_tables_used; - thd->lex= old_lex; - DBUG_RETURN(0); + result= !table->prelocking_placeholder && table->prepare_security(thd); -err: +end: if (arena) thd->restore_active_arena(arena, &backup); + thd->lex= old_lex; + DBUG_RETURN(result); + +err: delete table->view; table->view= 0; // now it is not VIEW placeholder - thd->lex= old_lex; - DBUG_RETURN(1); + result= 1; + goto end; } @@ -1110,6 +1179,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) char path[FN_REFLEN]; TABLE_LIST *view; bool type= 0; + db_type not_used; for (view= views; view; view= view->next_local) { @@ -1117,7 +1187,8 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) view->table_name, reg_ext, NullS); (void) unpack_filename(path, path); VOID(pthread_mutex_lock(&LOCK_open)); - if (access(path, F_OK) || (type= (mysql_frm_type(path) != FRMTYPE_VIEW))) + if (access(path, F_OK) || + (type= (mysql_frm_type(thd, path, ¬_used) != FRMTYPE_VIEW))) { char name[FN_REFLEN]; my_snprintf(name, sizeof(name), "%s.%s", view->db, view->table_name); @@ -1164,24 +1235,36 @@ err: FRMTYPE_VIEW view */ -frm_type_enum mysql_frm_type(char *path) +frm_type_enum mysql_frm_type(THD *thd, char *path, db_type *dbt) { File file; - char header[10]; //"TYPE=VIEW\n" it is 10 characters - int length; + uchar header[10]; //"TYPE=VIEW\n" it is 10 characters + int error; DBUG_ENTER("mysql_frm_type"); + *dbt= DB_TYPE_UNKNOWN; + if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0) - { DBUG_RETURN(FRMTYPE_ERROR); - } - length= my_read(file, (byte*) header, sizeof(header), MYF(MY_WME)); + error= my_read(file, (byte*) header, sizeof(header), MYF(MY_WME | MY_NABP)); my_close(file, MYF(MY_WME)); - if (length == (int) MY_FILE_ERROR) + + if (error) DBUG_RETURN(FRMTYPE_ERROR); - if (length < (int) sizeof(header) || - !strncmp(header, "TYPE=VIEW\n", sizeof(header))) + if (!strncmp((char*) header, "TYPE=VIEW\n", sizeof(header))) DBUG_RETURN(FRMTYPE_VIEW); + + /* + This is just a check for DB_TYPE. We'll return default unknown type + if the following test is true (arg #3). This should not have effect + on return value from this function (default FRMTYPE_TABLE) + */ + if (header[0] != (uchar) 254 || header[1] != 1 || + (header[2] != FRM_VER && header[2] != FRM_VER+1 && + (header[2] < FRM_VER+3 || header[2] > FRM_VER+4))) + DBUG_RETURN(FRMTYPE_TABLE); + + *dbt= ha_checktype(thd, (enum db_type) (uint) *(header + 3), 0, 0); DBUG_RETURN(FRMTYPE_TABLE); // Is probably a .frm table } @@ -1428,7 +1511,8 @@ mysql_rename_view(THD *thd, /* get view definition and source */ if (parser->parse((gptr)&view_def, thd->mem_root, view_parameters, - array_elements(view_parameters)-1)) + array_elements(view_parameters)-1, + &file_parser_dummy_hook)) goto err; /* rename view and it's backups */ diff --git a/sql/sql_view.h b/sql/sql_view.h index 4cc9eb454fb..cd61d7e9e71 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -19,7 +19,7 @@ bool mysql_create_view(THD *thd, enum_view_create_mode mode); -my_bool mysql_make_view(File_parser *parser, TABLE_LIST *table); +bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table); bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode); @@ -27,7 +27,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST * view); bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view); -frm_type_enum mysql_frm_type(char *path); +frm_type_enum mysql_frm_type(THD *thd, char *path, db_type *dbt); int view_checksum(THD *thd, TABLE_LIST *view); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index fb77f01d38c..25e10362ece 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -175,6 +175,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token CLIENT_SYM %token CLOSE_SYM %token COALESCE +%token CODE_SYM %token COLLATE_SYM %token COLLATION_SYM %token COLUMNS @@ -776,7 +777,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp -%type <lex_user> user grant_user +%type <lex_user> user grant_user get_definer %type <charset> opt_collate @@ -827,10 +828,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); subselect_end select_var_list select_var_list_init help opt_len opt_extended_describe prepare prepare_src execute deallocate - statement sp_suid opt_view_list view_list or_replace algorithm + statement sp_suid sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec - view_user view_suid + definer view_replace_or_algorithm view_replace view_algorithm_opt + view_algorithm view_or_trigger_tail view_suid view_tail view_list_opt + view_list view_select view_check_option trigger_tail END_OF_INPUT %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt @@ -1157,11 +1160,6 @@ create: | CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident { LEX *lex=Lex; - if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - YYABORT; - } lex->sql_command= SQLCOM_CREATE_INDEX; if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL, TL_OPTION_UPDATING)) @@ -1258,80 +1256,14 @@ create: YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; sp->restore_thd_mem_root(YYTHD); } - | CREATE or_replace algorithm view_user view_suid VIEW_SYM table_ident + | CREATE { - THD *thd= YYTHD; - LEX *lex= thd->lex; - lex->sql_command= SQLCOM_CREATE_VIEW; - lex->create_view_start= thd->query; - /* first table in list is target VIEW name */ - if (!lex->select_lex.add_table_to_list(thd, $7, NULL, 0)) - YYABORT; + Lex->create_view_mode= VIEW_CREATE_NEW; + Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; + Lex->create_view_suid= TRUE; } - opt_view_list AS select_view_init check_option + view_or_trigger {} - | CREATE TRIGGER_SYM sp_name trg_action_time trg_event - ON table_ident FOR_SYM EACH_SYM ROW_SYM - { - LEX *lex= Lex; - sp_head *sp; - - if (lex->sphead) - { - my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"); - YYABORT; - } - - if (!(sp= new sp_head())) - YYABORT; - sp->reset_thd_mem_root(YYTHD); - sp->init(lex); - - sp->m_type= TYPE_ENUM_TRIGGER; - lex->sphead= sp; - lex->spname= $3; - /* - We have to turn of CLIENT_MULTI_QUERIES while parsing a - stored procedure, otherwise yylex will chop it into pieces - at each ';'. - */ - sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; - YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; - - bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); - lex->sphead->m_chistics= &lex->sp_chistics; - lex->sphead->m_body_begin= lex->ptr; - } - sp_proc_stmt - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - - lex->sql_command= SQLCOM_CREATE_TRIGGER; - sp->init_strings(YYTHD, lex, $3); - /* Restore flag if it was cleared above */ - if (sp->m_old_cmq) - YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; - sp->restore_thd_mem_root(YYTHD); - - if (sp->is_not_allowed_in_function("trigger")) - YYABORT; - - /* - We have to do it after parsing trigger body, because some of - sp_proc_stmt alternatives are not saving/restoring LEX, so - lex->query_tables can be wiped out. - - QQ: What are other consequences of this? - - QQ: Could we loosen lock type in certain cases ? - */ - if (!lex->select_lex.add_table_to_list(YYTHD, $7, - (LEX_STRING*) 0, - TL_OPTION_UPDATING, - TL_WRITE)) - YYABORT; - } | CREATE USER clear_privileges grant_list { Lex->sql_command = SQLCOM_CREATE_USER; @@ -1418,41 +1350,11 @@ create_function_tail: { LEX *lex= Lex; sp_head *sp= lex->sphead; - LEX_STRING cmt = { 0, 0 }; - create_field *new_field; - uint unused1= 0; - int unused2= 0; - - if (!(new_field= new_create_field(YYTHD, (char*) "", - (enum enum_field_types)$8, - lex->length, lex->dec, lex->type, - (Item *)0, (Item *) 0, &cmt, 0, - &lex->interval_list, - (lex->charset ? lex->charset : - default_charset_info), - lex->uint_geom_type))) - YYABORT; - - sp->m_returns_cs= new_field->charset; - - if (new_field->interval_list.elements) - { - new_field->interval= - sp->create_typelib(&new_field->interval_list); - } - sp_prepare_create_field(YYTHD, new_field); - - if (prepare_create_field(new_field, &unused1, &unused2, &unused2, - HA_CAN_GEOMETRY)) - YYABORT; - sp->m_returns= new_field->sql_type; - sp->m_returns_cs= new_field->charset; - sp->m_returns_len= new_field->length; - sp->m_returns_pack= new_field->pack_flag; - sp->m_returns_typelib= new_field->interval; - sp->m_geom_returns= new_field->geom_type; - new_field->interval= NULL; + if (sp->fill_field_definition(YYTHD, lex, + (enum enum_field_types) $8, + &sp->m_return_field_def)) + YYABORT; bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); } @@ -1475,6 +1377,11 @@ create_function_tail: YYABORT; lex->sql_command= SQLCOM_CREATE_SPFUNCTION; sp->init_strings(YYTHD, lex, lex->spname); + if (!(sp->m_flags & sp_head::HAS_RETURN)) + { + my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str); + YYABORT; + } /* Restore flag if it was cleared above */ if (sp->m_old_cmq) YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; @@ -1569,8 +1476,28 @@ sp_fdparams: | sp_fdparam ; +sp_init_param: + /* Empty */ + { + LEX *lex= Lex; + + lex->length= 0; + lex->dec= 0; + lex->type= 0; + + lex->default_value= 0; + lex->on_update_value= 0; + + lex->comment= null_lex_str; + lex->charset= NULL; + + lex->interval_list.empty(); + lex->uint_geom_type= 0; + } + ; + sp_fdparam: - ident type + ident sp_init_param type { LEX *lex= Lex; sp_pcontext *spc= lex->spcont; @@ -1580,7 +1507,17 @@ sp_fdparam: my_error(ER_SP_DUP_PARAM, MYF(0), $1.str); YYABORT; } - spc->push_pvar(&$1, (enum enum_field_types)$2, sp_param_in); + sp_pvar_t *pvar= spc->push_pvar(&$1, (enum enum_field_types)$3, + sp_param_in); + + if (lex->sphead->fill_field_definition(YYTHD, lex, + (enum enum_field_types) $3, + &pvar->field_def)) + { + YYABORT; + } + pvar->field_def.field_name= pvar->name.str; + pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL; } ; @@ -1596,18 +1533,27 @@ sp_pdparams: ; sp_pdparam: - sp_opt_inout ident type + sp_opt_inout sp_init_param ident type { LEX *lex= Lex; sp_pcontext *spc= lex->spcont; - if (spc->find_pvar(&$2, TRUE)) + if (spc->find_pvar(&$3, TRUE)) { - my_error(ER_SP_DUP_PARAM, MYF(0), $2.str); + my_error(ER_SP_DUP_PARAM, MYF(0), $3.str); YYABORT; } - spc->push_pvar(&$2, (enum enum_field_types)$3, - (sp_param_mode_t)$1); + sp_pvar_t *pvar= spc->push_pvar(&$3, (enum enum_field_types)$4, + (sp_param_mode_t)$1); + + if (lex->sphead->fill_field_definition(YYTHD, lex, + (enum enum_field_types) $4, + &pvar->field_def)) + { + YYABORT; + } + pvar->field_def.field_name= pvar->name.str; + pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL; } ; @@ -1659,38 +1605,60 @@ sp_decls: ; sp_decl: - DECLARE_SYM sp_decl_idents type - { Lex->sphead->reset_lex(YYTHD); } - sp_opt_default + DECLARE_SYM sp_decl_idents { LEX *lex= Lex; - sp_pcontext *ctx= lex->spcont; - uint max= ctx->context_pvars(); - enum enum_field_types type= (enum enum_field_types)$3; - Item *it= $5; - bool has_default= (it != NULL); - for (uint i = max-$2 ; i < max ; i++) + lex->sphead->reset_lex(YYTHD); + lex->spcont->declare_var_boundary($2); + } + type + sp_opt_default + { + LEX *lex= Lex; + sp_pcontext *pctx= lex->spcont; + uint num_vars= pctx->context_pvars(); + enum enum_field_types var_type= (enum enum_field_types) $4; + Item *dflt_value_item= $5; + create_field *create_field_op; + + if (!dflt_value_item) { - sp_instr_set *in; - - ctx->set_type(i, type); - if (! has_default) - it= new Item_null(); /* QQ Set to the type with null_value? */ - in = new sp_instr_set(lex->sphead->instructions(), - ctx, - ctx->pvar_context2index(i), - it, type, lex, - (i == max - 1)); + dflt_value_item= new Item_null(); + /* QQ Set to the var_type with null_value? */ + } + + for (uint i = num_vars-$2 ; i < num_vars ; i++) + { + uint var_idx= pctx->pvar_context2index(i); + sp_pvar_t *pvar= pctx->find_pvar(var_idx); + + if (!pvar) + YYABORT; + + pvar->type= var_type; + pvar->dflt= dflt_value_item; + + if (lex->sphead->fill_field_definition(YYTHD, lex, var_type, + &pvar->field_def)) + { + YYABORT; + } + + pvar->field_def.field_name= pvar->name.str; + pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL; + + /* The last instruction is responsible for freeing LEX. */ - /* - The last instruction is assigned to be responsible for - freeing LEX. - */ - lex->sphead->add_instr(in); - ctx->set_default(i, it); + lex->sphead->add_instr( + new sp_instr_set(lex->sphead->instructions(), pctx, var_idx, + dflt_value_item, var_type, lex, + (i == num_vars - 1))); } + + pctx->declare_var_boundary(0); lex->sphead->restore_lex(YYTHD); + $$.vars= $2; $$.conds= $$.hndlrs= $$.curs= 0; } @@ -1762,7 +1730,8 @@ sp_decl: delete $5; YYABORT; } - i= new sp_instr_cpush(sp->instructions(), ctx, $5); + i= new sp_instr_cpush(sp->instructions(), ctx, $5, + ctx->current_cursors()); sp->add_instr(i); ctx->push_cursor(&$2); $$.vars= $$.conds= $$.hndlrs= 0; @@ -1912,6 +1881,8 @@ sp_hcond: sp_decl_idents: ident { + /* NOTE: field definition is filled in sp_decl section. */ + LEX *lex= Lex; sp_pcontext *spc= lex->spcont; @@ -1925,6 +1896,8 @@ sp_decl_idents: } | sp_decl_idents ',' ident { + /* NOTE: field definition is filled in sp_decl section. */ + LEX *lex= Lex; sp_pcontext *spc= lex->spcont; @@ -2002,8 +1975,8 @@ sp_proc_stmt: { sp_instr_freturn *i; - i= new sp_instr_freturn(sp->instructions(), lex->spcont, - $3, sp->m_returns, lex); + i= new sp_instr_freturn(sp->instructions(), lex->spcont, $3, + sp->m_return_field_def.sql_type, lex); sp->add_instr(i); sp->m_flags|= sp_head::HAS_RETURN; } @@ -2019,25 +1992,27 @@ sp_proc_stmt: { Lex->sphead->reset_lex(YYTHD); } expr WHEN_SYM { - /* We "fake" this by using an anonymous variable which we - set to the expression. Note that all WHENs are evaluate - at the same frame level, so we then know that it's the - top-most variable in the frame. */ LEX *lex= Lex; - uint offset= lex->spcont->current_pvars(); - sp_instr_set *i = new sp_instr_set(lex->sphead->instructions(), - lex->spcont, offset, $3, - MYSQL_TYPE_STRING, lex, TRUE); - LEX_STRING dummy={(char*)"", 0}; - - lex->spcont->push_pvar(&dummy, MYSQL_TYPE_STRING, sp_param_in); - lex->sphead->add_instr(i); - lex->sphead->m_flags|= sp_head::IN_SIMPLE_CASE; - lex->sphead->restore_lex(YYTHD); + sp_head *sp= lex->sphead; + sp_pcontext *parsing_ctx= lex->spcont; + int case_expr_id= parsing_ctx->register_case_expr(); + + if (parsing_ctx->push_case_expr_id(case_expr_id)) + YYABORT; + + sp->add_instr( + new sp_instr_set_case_expr(sp->instructions(), + parsing_ctx, + case_expr_id, + $3, + lex)); + + sp->m_flags|= sp_head::IN_SIMPLE_CASE; + sp->restore_lex(YYTHD); } sp_case END CASE_SYM { - Lex->spcont->pop_pvar(); + Lex->spcont->pop_case_expr_id(); } | sp_labeled_control {} @@ -2348,16 +2323,20 @@ sp_case: i= new sp_instr_jump_if_not(ip, ctx, $2, lex); else { /* Simple case: <caseval> = <whenval> */ - LEX_STRING ivar; - ivar.str= (char *)"_tmp_"; - ivar.length= 5; - Item *var= (Item*) new Item_splocal(ivar, - ctx->current_pvars()-1); - Item *expr= new Item_func_eq(var, $2); + Item_case_expr *var; + Item *expr; + + var= new Item_case_expr(ctx->get_current_case_expr_id()); + +#ifndef DBUG_OFF + if (var) + var->m_sp= sp; +#endif + + expr= new Item_func_eq(var, $2); i= new sp_instr_jump_if_not(ip, ctx, expr, lex); - lex->variables_used= 1; } sp->push_backpatch(i, ctx->push_label((char *)"", 0)); sp->add_instr(i); @@ -3363,11 +3342,6 @@ alter: { THD *thd= YYTHD; LEX *lex= thd->lex; - if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - YYABORT; - } lex->sql_command= SQLCOM_ALTER_TABLE; lex->name= 0; lex->duplicates= DUP_ERROR; @@ -3435,17 +3409,17 @@ alter: lex->sql_command= SQLCOM_ALTER_FUNCTION; lex->spname= $3; } - | ALTER algorithm view_user view_suid VIEW_SYM table_ident + | ALTER view_algorithm_opt definer view_suid + VIEW_SYM table_ident { THD *thd= YYTHD; LEX *lex= thd->lex; lex->sql_command= SQLCOM_CREATE_VIEW; - lex->create_view_start= thd->query; lex->create_view_mode= VIEW_ALTER; /* first table in list is target VIEW name */ lex->select_lex.add_table_to_list(thd, $6, NULL, 0); } - opt_view_list AS select_view_init check_option + view_list_opt AS view_select view_check_option {} ; @@ -3677,11 +3651,6 @@ start: START_SYM TRANSACTION_SYM start_transaction_opts { LEX *lex= Lex; - if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - YYABORT; - } lex->sql_command= SQLCOM_BEGIN; lex->start_transaction_opt= $3; } @@ -3844,11 +3813,6 @@ optimize: OPTIMIZE opt_no_write_to_binlog table_or_tables { LEX *lex=Lex; - if (lex->sphead) - { - my_error(ER_SP_BADSTATEMENT, MYF(0), "OPTIMIZE TABLE"); - YYABORT; - } lex->sql_command = SQLCOM_OPTIMIZE; lex->no_write_to_binlog= $2; lex->check_opt.init(); @@ -3866,13 +3830,7 @@ opt_no_write_to_binlog: rename: RENAME table_or_tables { - LEX *lex= Lex; - if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - YYABORT; - } - lex->sql_command=SQLCOM_RENAME_TABLE; + Lex->sql_command= SQLCOM_RENAME_TABLE; } table_to_table_list {} @@ -4013,18 +3971,6 @@ select_init: | '(' select_paren ')' union_opt; -select_view_init: - SELECT_SYM remember_name select_init2 - { - Lex->create_view_select_start= $2; - } - | - '(' remember_name select_paren ')' union_opt - { - Lex->create_view_select_start= $2; - } - ; - select_paren: SELECT_SYM select_part2 { @@ -4485,16 +4431,14 @@ simple_expr: { if ($3->is_splocal()) { - LEX_STRING *name; Item_splocal *il= static_cast<Item_splocal *>($3); - name= il->my_name(NULL); - my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str); + my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str); YYABORT; } $$= new Item_default_value(Lex->current_context(), $3); } - | VALUES '(' simple_ident ')' + | VALUES '(' simple_ident_nospvar ')' { $$= new Item_insert_value(Lex->current_context(), $3); } | FUNC_ARG0 '(' ')' { @@ -5264,10 +5208,8 @@ join_table: { YYERROR_UNLESS($1 && ($$=$3)); /* Change the current name resolution context to a local context. */ - Name_resolution_context *on_context; - if (!(on_context= make_join_on_context(YYTHD,$1,$3))) + if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; - Lex->push_context(on_context); } expr { @@ -5279,10 +5221,8 @@ join_table: { YYERROR_UNLESS($1 && ($$=$3)); /* Change the current name resolution context to a local context. */ - Name_resolution_context *on_context; - if (!(on_context= make_join_on_context(YYTHD,$1,$3))) + if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; - Lex->push_context(on_context); } expr { @@ -5309,10 +5249,8 @@ join_table: ON { /* Change the current name resolution context to a local context. */ - Name_resolution_context *on_context; - if (!(on_context= make_join_on_context(YYTHD,$1,$5))) + if (push_new_name_resolution_context(YYTHD, $1, $5)) YYABORT; - Lex->push_context(on_context); } expr { @@ -5342,10 +5280,8 @@ join_table: ON { /* Change the current name resolution context to a local context. */ - Name_resolution_context *on_context; - if (!(on_context= make_join_on_context(YYTHD,$1,$5))) + if (push_new_name_resolution_context(YYTHD, $1, $5)) YYABORT; - Lex->push_context(on_context); } expr { @@ -5406,10 +5342,9 @@ table_factor: ON { /* Change the current name resolution context to a local context. */ - Name_resolution_context *on_context; - if (!(on_context= make_join_on_context(YYTHD,$3,$7))) + if (push_new_name_resolution_context(YYTHD, $3, $7)) YYABORT; - Lex->push_context(on_context); + } expr '}' { @@ -5961,7 +5896,13 @@ select_var_ident: YYABORT; else { - ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($1,1,t->offset,t->type)); + my_var *var; + ((select_dumpvar *)lex->result)-> + var_list.push_back(var= new my_var($1,1,t->offset,t->type)); +#ifndef DBUG_OFF + if (var) + var->sp= lex->sphead; +#endif } } ; @@ -6021,21 +5962,10 @@ drop: lex->sql_command = SQLCOM_DROP_TABLE; lex->drop_temporary= $2; lex->drop_if_exists= $4; - if (!lex->drop_temporary && lex->sphead && - lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - YYABORT; - } } | DROP INDEX_SYM ident ON table_ident {} { LEX *lex=Lex; - if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - YYABORT; - } lex->sql_command= SQLCOM_DROP_INDEX; lex->alter_info.drop_list.empty(); lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY, @@ -6081,13 +6011,7 @@ drop: } | DROP VIEW_SYM if_exists table_list opt_restrict { - THD *thd= YYTHD; - LEX *lex= thd->lex; - if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - YYABORT; - } + LEX *lex= Lex; lex->sql_command= SQLCOM_DROP_VIEW; lex->drop_if_exists= $3; } @@ -6700,7 +6624,28 @@ show_param: YYABORT; if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES)) YYABORT; - }; + } + | PROCEDURE CODE_SYM sp_name + { +#ifdef DBUG_OFF + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; +#else + Lex->sql_command= SQLCOM_SHOW_PROC_CODE; + Lex->spname= $3; +#endif + } + | FUNCTION_SYM CODE_SYM sp_name + { +#ifdef DBUG_OFF + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; +#else + Lex->sql_command= SQLCOM_SHOW_FUNC_CODE; + Lex->spname= $3; +#endif + } + ; show_engine_param: STATUS_SYM @@ -7258,8 +7203,13 @@ simple_ident: { /* We're compiling a stored procedure and found a variable */ Item_splocal *splocal; - splocal= new Item_splocal($1, spv->offset, lex->tok_start_prev - + splocal= new Item_splocal($1, spv->offset, spv->type, + lex->tok_start_prev - lex->sphead->m_tmp_query); +#ifndef DBUG_OFF + if (splocal) + splocal->m_sp= lex->sphead; +#endif $$ = (Item*) splocal; lex->variables_used= 1; lex->safe_to_cache_query=0; @@ -7609,6 +7559,7 @@ keyword_sp: | CHANGED {} | CIPHER_SYM {} | CLIENT_SYM {} + | CODE_SYM {} | COLLATION_SYM {} | COLUMNS {} | COMMITTED_SYM {} @@ -8038,6 +7989,9 @@ option_value: names.length= 5; if (spc && spc->find_pvar(&names)) my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str); + else + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; } | NAMES_SYM charset_name_or_default opt_collate @@ -8727,11 +8681,6 @@ begin: BEGIN_SYM { LEX *lex=Lex; - if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - YYABORT; - } lex->sql_command = SQLCOM_BEGIN; lex->start_transaction_opt= 0; } @@ -8764,11 +8713,6 @@ commit: COMMIT_SYM opt_work opt_chain opt_release { LEX *lex=Lex; - if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - YYABORT; - } lex->sql_command= SQLCOM_COMMIT; lex->tx_chain= $3; lex->tx_release= $4; @@ -8779,11 +8723,6 @@ rollback: ROLLBACK_SYM opt_work opt_chain opt_release { LEX *lex=Lex; - if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); - YYABORT; - } lex->sql_command= SQLCOM_ROLLBACK; lex->tx_chain= $3; lex->tx_release= $4; @@ -8961,10 +8900,121 @@ subselect_end: LEX *lex=Lex; lex->pop_context(); lex->current_select = lex->current_select->return_after_parsing(); + lex->nest_level--; }; -opt_view_list: - /* empty */ {} +definer: + get_definer + { + THD *thd= YYTHD; + + if (! (thd->lex->definer= create_definer(thd, &$1->user, &$1->host))) + YYABORT; + } + ; + +get_definer: + opt_current_definer + { + THD *thd= YYTHD; + + if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) + YYABORT; + + if (get_default_definer(thd, $$)) + YYABORT; + } + | DEFINER_SYM EQ ident_or_text '@' ident_or_text + { + if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user)))) + YYABORT; + + $$->user= $3; + $$->host= $5; + } + ; + +opt_current_definer: + /* empty */ + | DEFINER_SYM EQ CURRENT_USER optional_braces + ; + +/************************************************************************** + + CREATE VIEW statement options. + +**************************************************************************/ + +view_replace_or_algorithm: + view_replace + {} + | view_replace view_algorithm + {} + | view_algorithm + {} + ; + +view_replace: + OR_SYM REPLACE + { Lex->create_view_mode= VIEW_CREATE_OR_REPLACE; } + ; + +view_algorithm: + ALGORITHM_SYM EQ UNDEFINED_SYM + { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; } + | ALGORITHM_SYM EQ MERGE_SYM + { Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; } + | ALGORITHM_SYM EQ TEMPTABLE_SYM + { Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; } + ; + +view_algorithm_opt: + /* empty */ + { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; } + | view_algorithm + {} + ; + +view_or_trigger: + definer view_or_trigger_tail + {} + | view_replace_or_algorithm definer view_tail + {} + ; + +view_or_trigger_tail: + view_tail + {} + | trigger_tail + {} + ; + +view_suid: + /* empty */ + { Lex->create_view_suid= TRUE; } + | SQL_SYM SECURITY_SYM DEFINER_SYM + { Lex->create_view_suid= TRUE; } + | SQL_SYM SECURITY_SYM INVOKER_SYM + { Lex->create_view_suid= FALSE; } + ; + +view_tail: + view_suid VIEW_SYM table_ident + { + THD *thd= YYTHD; + LEX *lex= thd->lex; + lex->sql_command= SQLCOM_CREATE_VIEW; + /* first table in list is target VIEW name */ + if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0)) + YYABORT; + } + view_list_opt AS view_select view_check_option + {} + ; + +view_list_opt: + /* empty */ + {} | '(' view_list ')' ; @@ -8981,80 +9031,112 @@ view_list: } ; -or_replace: - /* empty */ { Lex->create_view_mode= VIEW_CREATE_NEW; } - | OR_SYM REPLACE { Lex->create_view_mode= VIEW_CREATE_OR_REPLACE; } +view_select: + SELECT_SYM remember_name select_init2 + { + THD *thd=YYTHD; + LEX *lex= thd->lex; + char *stmt_beg= (lex->sphead ? + (char *)lex->sphead->m_tmp_query : + thd->query); + lex->create_view_select_start= $2 - stmt_beg; + } + | '(' remember_name select_paren ')' union_opt + { + THD *thd=YYTHD; + LEX *lex= thd->lex; + char *stmt_beg= (lex->sphead ? + (char *)lex->sphead->m_tmp_query : + thd->query); + lex->create_view_select_start= $2 - stmt_beg; + } ; -algorithm: +view_check_option: /* empty */ - { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; } - | ALGORITHM_SYM EQ UNDEFINED_SYM - { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; } - | ALGORITHM_SYM EQ MERGE_SYM - { Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; } - | ALGORITHM_SYM EQ TEMPTABLE_SYM - { Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; } + { Lex->create_view_check= VIEW_CHECK_NONE; } + | WITH CHECK_SYM OPTION + { Lex->create_view_check= VIEW_CHECK_CASCADED; } + | WITH CASCADED CHECK_SYM OPTION + { Lex->create_view_check= VIEW_CHECK_CASCADED; } + | WITH LOCAL_SYM CHECK_SYM OPTION + { Lex->create_view_check= VIEW_CHECK_LOCAL; } ; -view_user: - /* empty */ - { - THD *thd= YYTHD; - if (!(thd->lex->create_view_definer= - (LEX_USER*) thd->alloc(sizeof(st_lex_user)))) - YYABORT; - if (default_view_definer(thd->security_ctx, - thd->lex->create_view_definer)) - YYABORT; - } - | CURRENT_USER optional_braces - { - THD *thd= YYTHD; - if (!(thd->lex->create_view_definer= - (LEX_USER*) thd->alloc(sizeof(st_lex_user)))) - YYABORT; - if (default_view_definer(thd->security_ctx, - thd->lex->create_view_definer)) - YYABORT; - } - | DEFINER_SYM EQ ident_or_text '@' ident_or_text +/************************************************************************** + + CREATE TRIGGER statement parts. + +**************************************************************************/ + +trigger_tail: + TRIGGER_SYM remember_name sp_name trg_action_time trg_event + ON table_ident FOR_SYM EACH_SYM ROW_SYM + { + LEX *lex= Lex; + sp_head *sp; + + if (lex->sphead) { - THD *thd= YYTHD; - st_lex_user *view_user; - if (!(thd->lex->create_view_definer= view_user= - (LEX_USER*) thd->alloc(sizeof(st_lex_user)))) - YYABORT; - view_user->user = $3; view_user->host=$5; - if (strchr(view_user->host.str, wild_many) || - strchr(view_user->host.str, wild_one)) - { - my_error(ER_NO_VIEW_USER, MYF(0)); - YYABORT; - } + my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"); + YYABORT; } - ; - -view_suid: - /* empty */ - { Lex->create_view_suid= TRUE; } - | - SQL_SYM SECURITY_SYM DEFINER_SYM - { Lex->create_view_suid= TRUE; } - | SQL_SYM SECURITY_SYM INVOKER_SYM - { Lex->create_view_suid= FALSE; } + + if (!(sp= new sp_head())) + YYABORT; + sp->reset_thd_mem_root(YYTHD); + sp->init(lex); + + lex->trigger_definition_begin= $2; + + sp->m_type= TYPE_ENUM_TRIGGER; + lex->sphead= sp; + lex->spname= $3; + /* + We have to turn of CLIENT_MULTI_QUERIES while parsing a + stored procedure, otherwise yylex will chop it into pieces + at each ';'. + */ + sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; + YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; + + bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); + lex->sphead->m_chistics= &lex->sp_chistics; + lex->sphead->m_body_begin= lex->ptr; + } + sp_proc_stmt + { + LEX *lex= Lex; + sp_head *sp= lex->sphead; + + lex->sql_command= SQLCOM_CREATE_TRIGGER; + sp->init_strings(YYTHD, lex, $3); + /* Restore flag if it was cleared above */ + if (sp->m_old_cmq) + YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; + sp->restore_thd_mem_root(YYTHD); + + if (sp->is_not_allowed_in_function("trigger")) + YYABORT; + + /* + We have to do it after parsing trigger body, because some of + sp_proc_stmt alternatives are not saving/restoring LEX, so + lex->query_tables can be wiped out. + + QQ: What are other consequences of this? + + QQ: Could we loosen lock type in certain cases ? + */ + if (!lex->select_lex.add_table_to_list(YYTHD, $7, + (LEX_STRING*) 0, + TL_OPTION_UPDATING, + TL_WRITE)) + YYABORT; + } ; -check_option: - /* empty */ - { Lex->create_view_check= VIEW_CHECK_NONE; } - | WITH CHECK_SYM OPTION - { Lex->create_view_check= VIEW_CHECK_CASCADED; } - | WITH CASCADED CHECK_SYM OPTION - { Lex->create_view_check= VIEW_CHECK_CASCADED; } - | WITH LOCAL_SYM CHECK_SYM OPTION - { Lex->create_view_check= VIEW_CHECK_LOCAL; } - ; +/*************************************************************************/ xa: XA_SYM begin_or_start xid opt_join_or_resume { diff --git a/sql/structs.h b/sql/structs.h index 92f09385d6e..9421ebdc2af 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -20,8 +20,6 @@ struct st_table; class Field; -#define STRING_WITH_LEN(X) ((char*) X), (sizeof(X)-1) - typedef struct st_lex_string { char *str; @@ -135,7 +133,6 @@ typedef struct st_read_record { /* Parameter to read_record */ byte *cache,*cache_pos,*cache_end,*read_positions; IO_CACHE *io_cache; bool print_error, ignore_not_found_rows; - bool first; /* used only with rr_index_read */ } READ_RECORD; @@ -186,6 +183,7 @@ enum SHOW_TYPE SHOW_SSL_CTX_SESS_TIMEOUTS, SHOW_SSL_CTX_SESS_CACHE_FULL, SHOW_SSL_GET_CIPHER_LIST, #endif /* HAVE_OPENSSL */ + SHOW_NET_COMPRESSION, SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING, SHOW_SLAVE_RETRIED_TRANS, SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_CONST_LONG, SHOW_KEY_CACHE_LONGLONG, SHOW_LONG_STATUS, SHOW_LONG_CONST_STATUS, SHOW_SLAVE_SKIP_ERRORS diff --git a/sql/table.cc b/sql/table.cc index 722e4e4df25..fc75568b615 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -110,7 +110,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, if (my_read(file,(byte*) head,64,MYF(MY_NABP))) goto err; - if (memcmp(head, "TYPE=", 5) == 0) + if (memcmp(head, STRING_WITH_LEN("TYPE=")) == 0) { // new .frm my_close(file,MYF(MY_WME)); @@ -338,7 +338,8 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, my_free(buff, MYF(0)); } /* Allocate handler */ - if (!(outparam->file= get_new_handler(outparam, share->db_type))) + if (!(outparam->file= get_new_handler(outparam, &outparam->mem_root, + share->db_type))) goto err; error=4; @@ -1246,15 +1247,15 @@ fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types, } /* fix_type_pointers */ -TYPELIB *typelib(List<String> &strings) +TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings) { - TYPELIB *result=(TYPELIB*) sql_alloc(sizeof(TYPELIB)); + TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB)); if (!result) return 0; result->count=strings.elements; result->name=""; uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1); - if (!(result->type_names= (const char**) sql_alloc(nbytes))) + if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes))) return 0; result->type_lengths= (uint*) (result->type_names + result->count + 1); List_iterator<String> it(strings); @@ -1402,13 +1403,12 @@ File create_frm(THD *thd, my_string name, const char *db, if (create_info->options & HA_LEX_CREATE_TMP_TABLE) create_flags|= O_EXCL | O_NOFOLLOW; -#if SIZEOF_OFF_T > 4 /* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */ - if (create_info->max_rows > ~(ulong) 0) - create_info->max_rows= ~(ulong) 0; - if (create_info->min_rows > ~(ulong) 0) - create_info->min_rows= ~(ulong) 0; -#endif + if (create_info->max_rows > UINT_MAX32) + create_info->max_rows= UINT_MAX32; + if (create_info->min_rows > UINT_MAX32) + create_info->min_rows= UINT_MAX32; + /* Ensure that raid_chunks can't be larger than 255, as this would cause problems with drop database @@ -1693,29 +1693,6 @@ bool check_column_name(const char *name) } /* -** Get type of table from .frm file -*/ - -db_type get_table_type(THD *thd, const char *name) -{ - File file; - uchar head[4]; - int error; - DBUG_ENTER("get_table_type"); - DBUG_PRINT("enter",("name: '%s'",name)); - - if ((file=my_open(name,O_RDONLY, MYF(0))) < 0) - DBUG_RETURN(DB_TYPE_UNKNOWN); - error=my_read(file,(byte*) head,4,MYF(MY_NABP)); - my_close(file,MYF(0)); - if (error || head[0] != (uchar) 254 || head[1] != 1 || - (head[2] != FRM_VER && head[2] != FRM_VER+1 && - (head[2] < FRM_VER+3 || head[2] > FRM_VER+4))) - DBUG_RETURN(DB_TYPE_UNKNOWN); - DBUG_RETURN(ha_checktype(thd,(enum db_type) (uint) *(head+3),0,0)); -} - -/* Create Item_field for each column in the table. SYNPOSIS @@ -1798,41 +1775,43 @@ void st_table_list::calc_md5(char *buffer) /* - set ancestor TABLE for table place holder of VIEW + set underlying TABLE for table place holder of VIEW DESCRIPTION Replace all views that only uses one table with the table itself. This allows us to treat the view as a simple table and even update - it + it (it is a kind of optimisation) SYNOPSIS - st_table_list::set_ancestor() + st_table_list::set_underlying_merge() */ -void st_table_list::set_ancestor() +void st_table_list::set_underlying_merge() { TABLE_LIST *tbl; - if ((tbl= ancestor)) + if ((tbl= merge_underlying_list)) { /* This is a view. Process all tables of view */ - DBUG_ASSERT(view); + DBUG_ASSERT(view && effective_algorithm == VIEW_ALGORITHM_MERGE); do { - if (tbl->ancestor) // This is a view + if (tbl->merge_underlying_list) // This is a view { + DBUG_ASSERT(tbl->view && + tbl->effective_algorithm == VIEW_ALGORITHM_MERGE); /* This is the only case where set_ancestor is called on an object that may not be a view (in which case ancestor is 0) */ - tbl->ancestor->set_ancestor(); + tbl->merge_underlying_list->set_underlying_merge(); } } while ((tbl= tbl->next_local)); if (!multitable_view) { - table= ancestor->table; - schema_table= ancestor->schema_table; + table= merge_underlying_list->table; + schema_table= merge_underlying_list->schema_table; } } } @@ -1842,12 +1821,9 @@ void st_table_list::set_ancestor() setup fields of placeholder of merged VIEW SYNOPSIS - st_table_list::setup_ancestor() + st_table_list::setup_underlying() thd - thread handler - NOTES - ancestor is list of tables and views used by view (underlying tables/views) - DESCRIPTION It is: - preparing translation table for view columns @@ -1858,10 +1834,11 @@ void st_table_list::set_ancestor() TRUE - error */ -bool st_table_list::setup_ancestor(THD *thd) +bool st_table_list::setup_underlying(THD *thd) { - DBUG_ENTER("st_table_list::setup_ancestor"); - if (!field_translation) + DBUG_ENTER("st_table_list::setup_underlying"); + + if (!field_translation && merge_underlying_list) { Field_translator *transl; SELECT_LEX *select= &view->select_lex; @@ -1875,10 +1852,10 @@ bool st_table_list::setup_ancestor(THD *thd) DBUG_RETURN(TRUE); } - for (tbl= ancestor; tbl; tbl= tbl->next_local) + for (tbl= merge_underlying_list; tbl; tbl= tbl->next_local) { - if (tbl->ancestor && - tbl->setup_ancestor(thd)) + if (tbl->merge_underlying_list && + tbl->setup_underlying(thd)) { DBUG_RETURN(TRUE); } @@ -1941,7 +1918,7 @@ bool st_table_list::prep_where(THD *thd, Item **conds, { DBUG_ENTER("st_table_list::prep_where"); - for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) { if (tbl->view && tbl->prep_where(thd, conds, no_where_clause)) { @@ -2023,7 +2000,7 @@ bool st_table_list::prep_check_option(THD *thd, uint8 check_opt_type) { DBUG_ENTER("st_table_list::prep_check_option"); - for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) { /* see comment of check_opt_type parameter */ if (tbl->view && @@ -2046,7 +2023,7 @@ bool st_table_list::prep_check_option(THD *thd, uint8 check_opt_type) } if (check_opt_type == VIEW_CHECK_CASCADED) { - for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) { if (tbl->check_option) item= and_conds(item, tbl->check_option); @@ -2085,16 +2062,21 @@ void st_table_list::hide_view_error(THD *thd) { /* Hide "Unknown column" or "Unknown function" error */ if (thd->net.last_errno == ER_BAD_FIELD_ERROR || - thd->net.last_errno == ER_SP_DOES_NOT_EXIST) + thd->net.last_errno == ER_SP_DOES_NOT_EXIST || + thd->net.last_errno == ER_PROCACCESS_DENIED_ERROR || + thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR) { + TABLE_LIST *top= top_table(); thd->clear_error(); - my_error(ER_VIEW_INVALID, MYF(0), view_db.str, view_name.str); + my_error(ER_VIEW_INVALID, MYF(0), top->view_db.str, top->view_name.str); } else if (thd->net.last_errno == ER_NO_DEFAULT_FOR_FIELD) { + TABLE_LIST *top= top_table(); thd->clear_error(); // TODO: make correct error message - my_error(ER_NO_DEFAULT_FOR_VIEW_FIELD, MYF(0), view_db.str, view_name.str); + my_error(ER_NO_DEFAULT_FOR_VIEW_FIELD, MYF(0), + top->view_db.str, top->view_name.str); } } @@ -2115,10 +2097,10 @@ void st_table_list::hide_view_error(THD *thd) st_table_list *st_table_list::find_underlying_table(TABLE *table_to_find) { /* is this real table and table which we are looking for? */ - if (table == table_to_find && ancestor == 0) + if (table == table_to_find && merge_underlying_list == 0) return this; - for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) { TABLE_LIST *result; if ((result= tbl->find_underlying_table(table_to_find))) @@ -2201,7 +2183,7 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure) bool st_table_list::check_single_table(st_table_list **table, table_map map, st_table_list *view) { - for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) { if (tbl->table) { @@ -2243,8 +2225,8 @@ bool st_table_list::set_insert_values(MEM_ROOT *mem_root) } else { - DBUG_ASSERT(view && ancestor); - for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + DBUG_ASSERT(view && merge_underlying_list); + for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) if (tbl->set_insert_values(mem_root)) return TRUE; } @@ -2390,6 +2372,157 @@ TABLE_LIST *st_table_list::last_leaf_for_name_resolution() } +/* + Register access mode which we need for underlying tables + + SYNOPSIS + register_want_access() + want_access Acess which we require +*/ + +void st_table_list::register_want_access(ulong want_access) +{ + /* Remove SHOW_VIEW_ACL, because it will be checked during making view */ + want_access&= ~SHOW_VIEW_ACL; + if (belong_to_view) + { + grant.want_privilege= want_access; + if (table) + table->grant.want_privilege= want_access; + } + for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) + tbl->register_want_access(want_access); +} + + +/* + Load security context information for this view + + SYNOPSIS + st_table_list::prepare_view_securety_context() + thd [in] thread handler + + RETURN + FALSE OK + TRUE Error +*/ + +#ifndef NO_EMBEDDED_ACCESS_CHECKS +bool st_table_list::prepare_view_securety_context(THD *thd) +{ + DBUG_ENTER("st_table_list::prepare_view_securety_context"); + DBUG_PRINT("enter", ("table: %s", alias)); + + DBUG_ASSERT(!prelocking_placeholder && view); + if (view_suid) + { + DBUG_PRINT("info", ("This table is suid view => load contest")); + DBUG_ASSERT(view && view_sctx); + if (acl_getroot_no_password(view_sctx, + definer.user.str, + definer.host.str, + definer.host.str, + thd->db)) + { + my_error(ER_NO_SUCH_USER, MYF(0), definer.user.str, definer.host.str); + DBUG_RETURN(TRUE); + } + } + DBUG_RETURN(FALSE); +} +#endif + + +/* + Find security context of current view + + SYNOPSIS + st_table_list::find_view_security_context() + thd [in] thread handler + +*/ + +#ifndef NO_EMBEDDED_ACCESS_CHECKS +Security_context *st_table_list::find_view_security_context(THD *thd) +{ + Security_context *sctx; + TABLE_LIST *upper_view= this; + DBUG_ENTER("st_table_list::find_view_security_context"); + + DBUG_ASSERT(view); + while (upper_view && !upper_view->view_suid) + { + DBUG_ASSERT(!upper_view->prelocking_placeholder); + upper_view= upper_view->referencing_view; + } + if (upper_view) + { + DBUG_PRINT("info", ("Securety context of view %s will be used", + upper_view->alias)); + sctx= upper_view->view_sctx; + DBUG_ASSERT(sctx); + } + else + { + DBUG_PRINT("info", ("Current global context will be used")); + sctx= thd->security_ctx; + } + DBUG_RETURN(sctx); +} +#endif + + +/* + Prepare security context and load underlying tables priveleges for view + + SYNOPSIS + st_table_list::prepare_security() + thd [in] thread handler + + RETURN + FALSE OK + TRUE Error +*/ + +bool st_table_list::prepare_security(THD *thd) +{ + List_iterator_fast<TABLE_LIST> tb(*view_tables); + TABLE_LIST *tbl; + DBUG_ENTER("st_table_list::prepare_security"); +#ifndef NO_EMBEDDED_ACCESS_CHECKS + Security_context *save_security_ctx= thd->security_ctx; + + DBUG_ASSERT(!prelocking_placeholder); + if (prepare_view_securety_context(thd)) + DBUG_RETURN(TRUE); + thd->security_ctx= find_view_security_context(thd); + while ((tbl= tb++)) + { + DBUG_ASSERT(tbl->referencing_view); + char *db, *table_name; + if (tbl->view) + { + db= tbl->view_db.str; + table_name= tbl->view_name.str; + } + else + { + db= tbl->db; + table_name= tbl->table_name; + } + fill_effective_table_privileges(thd, &tbl->grant, db, table_name); + if (tbl->table) + tbl->table->grant= grant; + } + thd->security_ctx= save_security_ctx; +#else + while ((tbl= tb++)) + tbl->grant.privilege= ~NO_ACCESS; +#endif + DBUG_RETURN(FALSE); +} + + Natural_join_column::Natural_join_column(Field_translator *field_param, TABLE_LIST *tab) { @@ -2472,53 +2605,6 @@ GRANT_INFO *Natural_join_column::grant() } - -#ifndef NO_EMBEDDED_ACCESS_CHECKS - -/* - Check the access rights for the current join column. - columns. - - SYNOPSIS - Natural_join_column::check_grants() - - DESCRIPTION - Check the access rights to a column from a natural join in a generic - way that hides the heterogeneity of the column representation - whether - it is a view or a stored table colum. - - RETURN - FALSE The column can be accessed - TRUE There are no access rights to all equivalent columns -*/ - -bool -Natural_join_column::check_grants(THD *thd, const char *name, uint length) -{ - GRANT_INFO *grant; - const char *db_name; - const char *table_name; - - if (view_field) - { - DBUG_ASSERT(table_field == NULL); - grant= &(table_ref->grant); - db_name= table_ref->view_db.str; - table_name= table_ref->view_name.str; - } - else - { - DBUG_ASSERT(table_field && view_field == NULL); - grant= &(table_ref->table->grant); - db_name= table_ref->table->s->db; - table_name= table_ref->table->s->table_name; - } - - return check_grant_column(thd, grant, db_name, table_name, name, length); -} -#endif - - void Field_iterator_view::set(TABLE_LIST *table) { DBUG_ASSERT(table->field_translation); @@ -2561,8 +2647,9 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, if (view->schema_table_reformed) { /* - In case of SHOW command (schema_table_reformed set) all items are - fixed + Translation table items are always Item_fields and already fixed + ('mysql_schema_table' function). So we can return directly the + field. This case happens only for 'show & where' commands. */ DBUG_ASSERT(field && field->fixed); DBUG_RETURN(field); @@ -2594,21 +2681,14 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, void Field_iterator_natural_join::set(TABLE_LIST *table_ref) { DBUG_ASSERT(table_ref->join_columns); - delete column_ref_it; - - /* - TODO: try not to allocate new iterator every time. If we have to, - then check for out of memory condition. - */ - column_ref_it= new List_iterator_fast<Natural_join_column> - (*(table_ref->join_columns)); - cur_column_ref= (*column_ref_it)++; + column_ref_it.init(*(table_ref->join_columns)); + cur_column_ref= column_ref_it++; } void Field_iterator_natural_join::next() { - cur_column_ref= (*column_ref_it)++; + cur_column_ref= column_ref_it++; DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field || cur_column_ref->table_ref->table == cur_column_ref->table_field->table); @@ -2735,7 +2815,6 @@ GRANT_INFO *Field_iterator_table_ref::grant() SYNOPSIS Field_iterator_table_ref::get_or_create_column_ref() - thd [in] pointer to current thread is_created [out] set to TRUE if the column was created, FALSE if we return an already created colum @@ -2748,7 +2827,7 @@ GRANT_INFO *Field_iterator_table_ref::grant() */ Natural_join_column * -Field_iterator_table_ref::get_or_create_column_ref(THD *thd, bool *is_created) +Field_iterator_table_ref::get_or_create_column_ref(bool *is_created) { Natural_join_column *nj_col; @@ -2782,6 +2861,41 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, bool *is_created) } +/* + Return an existing reference to a column of a natural/using join. + + SYNOPSIS + Field_iterator_table_ref::get_natural_column_ref() + + DESCRIPTION + The method should be called in contexts where it is expected that + all natural join columns are already created, and that the column + being retrieved is a Natural_join_column. + + RETURN + # Pointer to a column of a natural join (or its operand) + NULL No memory to allocate the column +*/ + +Natural_join_column * +Field_iterator_table_ref::get_natural_column_ref() +{ + Natural_join_column *nj_col; + + DBUG_ASSERT(field_it == &natural_join_it); + /* + The field belongs to a NATURAL join, therefore the column reference was + already created via one of the two constructor calls above. In this case + we just return the already created column reference. + */ + nj_col= natural_join_it.column_ref(); + DBUG_ASSERT(nj_col && + (!nj_col->table_field || + nj_col->table_ref->table == nj_col->table_field->table)); + return nj_col; +} + + /***************************************************************************** ** Instansiate templates *****************************************************************************/ diff --git a/sql/table.h b/sql/table.h index e76d005f494..ce0616a6833 100644 --- a/sql/table.h +++ b/sql/table.h @@ -22,6 +22,7 @@ class GRANT_TABLE; class st_select_lex_unit; class st_select_lex; class COND_EQUAL; +class Security_context; /* Order clause list element */ @@ -47,6 +48,11 @@ typedef struct st_grant_info uint version; ulong privilege; ulong want_privilege; + /* + Stores the requested access acl of top level tables list. Is used to + check access rights to the underlying tables of a view. + */ + ulong orig_want_privilege; } GRANT_INFO; enum tmp_table_type {NO_TMP_TABLE=0, TMP_TABLE=1, TRANSACTIONAL_TMP_TABLE=2, @@ -359,7 +365,6 @@ typedef struct st_schema_table #define VIEW_CHECK_SKIP 2 struct st_lex; -struct st_table_list; class select_union; class TMP_TABLE_PARAM; @@ -402,9 +407,6 @@ public: const char *table_name(); const char *db_name(); GRANT_INFO *grant(); -#ifndef NO_EMBEDDED_ACCESS_CHECKS - bool check_grants(THD *thd, const char *name, uint length); -#endif }; @@ -525,11 +527,36 @@ typedef struct st_table_list Field_translator *field_translation; /* array of VIEW fields */ /* pointer to element after last one in translation table above */ Field_translator *field_translation_end; - /* list of ancestor(s) of this table (underlying table(s)/view(s) */ - st_table_list *ancestor; + /* + List (based on next_local) of underlying tables of this view. I.e. it + does not include the tables of subqueries used in the view. Is set only + for merged views. + */ + st_table_list *merge_underlying_list; + /* + - 0 for base tables + - in case of the view it is the list of all (not only underlying + tables but also used in subquery ones) tables of the view. + */ + List<st_table_list> *view_tables; /* most upper view this table belongs to */ st_table_list *belong_to_view; /* + The view directly referencing this table + (non-zero only for merged underlying tables of a view). + */ + st_table_list *referencing_view; + /* + Security context (non-zero only for tables which belong + to view with SQL SECURITY DEFINER) + */ + Security_context *security_ctx; + /* + This view security context (non-zero only for views with + SQL SECURITY DEFINER) + */ + Security_context *view_sctx; + /* List of all base tables local to a subquery including all view tables. Unlike 'next_local', this in this list views are *not* leaves. Created in setup_tables() -> make_leaves_list(). @@ -595,9 +622,9 @@ typedef struct st_table_list bool prelocking_placeholder; void calc_md5(char *buffer); - void set_ancestor(); + void set_underlying_merge(); int view_check_option(THD *thd, bool ignore_failure); - bool setup_ancestor(THD *thd); + bool setup_underlying(THD *thd); void cleanup_items(); bool placeholder() {return derived || view; } void print(THD *thd, String *str); @@ -625,6 +652,14 @@ typedef struct st_table_list return prep_where(thd, conds, no_where_clause); return FALSE; } + + void register_want_access(ulong want_access); + bool prepare_security(THD *thd); +#ifndef NO_EMBEDDED_ACCESS_CHECKS + Security_context *find_view_security_context(THD *thd); + bool prepare_view_securety_context(THD *thd); +#endif + private: bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_where(THD *thd, Item **conds, bool no_where_clause); @@ -696,11 +731,11 @@ public: class Field_iterator_natural_join: public Field_iterator { - List_iterator_fast<Natural_join_column> *column_ref_it; + List_iterator_fast<Natural_join_column> column_ref_it; Natural_join_column *cur_column_ref; public: - Field_iterator_natural_join() :column_ref_it(NULL), cur_column_ref(NULL) {} - ~Field_iterator_natural_join() { delete column_ref_it; } + Field_iterator_natural_join() :cur_column_ref(NULL) {} + ~Field_iterator_natural_join() {} void set(TABLE_LIST *table); void next(); bool end_of_fields() { return !cur_column_ref; } @@ -747,7 +782,8 @@ public: GRANT_INFO *grant(); Item *create_item(THD *thd) { return field_it->create_item(thd); } Field *field() { return field_it->field(); } - Natural_join_column *get_or_create_column_ref(THD *thd, bool *is_created); + Natural_join_column *get_or_create_column_ref(bool *is_created); + Natural_join_column *get_natural_column_ref(); }; @@ -757,7 +793,15 @@ typedef struct st_nested_join table_map used_tables; /* bitmap of tables in the nested join */ table_map not_null_tables; /* tables that rejects nulls */ struct st_join_table *first_nested;/* the first nested table in the plan */ - uint counter; /* to count tables in the nested join */ + /* + Used to count tables in the nested join in 2 isolated places: + 1. In make_outerjoin_info(). + 2. check_interleaving_with_nj/restore_prev_nj_state (these are called + by the join optimizer. + Before each use the counters are zeroed by reset_nj_counters. + */ + uint counter; + nested_join_map nj_map; /* Bit used to identify this nested join*/ } NESTED_JOIN; diff --git a/sql/tztime.cc b/sql/tztime.cc index 537050e94db..3a9d9a60aed 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1532,6 +1532,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) */ if (!(thd= new THD)) DBUG_RETURN(1); + thd->thread_stack= (char*) &thd; thd->store_globals(); /* Init all memory structures that require explicit destruction */ @@ -1558,7 +1559,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) sql_print_error("Fatal error: OOM while initializing time zones"); goto end_with_cleanup; } - tmp_tzname->name.set("SYSTEM", 6, &my_charset_latin1); + tmp_tzname->name.set(STRING_WITH_LEN("SYSTEM"), &my_charset_latin1); tmp_tzname->tz= my_tz_SYSTEM; if (my_hash_insert(&tz_names, (const byte *)tmp_tzname)) { @@ -2442,6 +2443,7 @@ scan_tz_dir(char * name_end) int main(int argc, char **argv) { +#ifndef __NETWARE__ MY_INIT(argv[0]); if (argc != 2 && argc != 3) @@ -2500,6 +2502,10 @@ main(int argc, char **argv) free_root(&tz_storage, MYF(0)); } +#else + fprintf(stderr, "This tool has not been ported to NetWare\n"); +#endif /* __NETWARE__ */ + return 0; } diff --git a/sql/unireg.cc b/sql/unireg.cc index 065f8583f71..0ab77462f61 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -90,7 +90,7 @@ bool mysql_create_frm(THD *thd, my_string file_name, if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0))) DBUG_RETURN(1); if (db_file == NULL) - db_file= get_new_handler((TABLE*) 0, create_info->db_type); + db_file= get_new_handler((TABLE*) 0, thd->mem_root, create_info->db_type); /* If fixed row records, we need one bit to check for deleted rows */ if (!(create_info->table_options & HA_OPTION_PACK_RECORD)) @@ -699,7 +699,7 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type, /* We need a table to generate columns for default values */ bzero((char*) &table,sizeof(table)); table.s= &table.share_not_to_be_used; - handler= get_new_handler((TABLE*) 0, table_type); + handler= get_new_handler((TABLE*) 0, thd->mem_root, table_type); if (!handler || !(buff=(uchar*) my_malloc((uint) reclength,MYF(MY_WME | MY_ZEROFILL)))) diff --git a/sql/unireg.h b/sql/unireg.h index 6afefa579e8..b932a2f320c 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -43,18 +43,14 @@ #define ERRMAPP 1 /* Errormap f|r my_error */ #define LIBLEN FN_REFLEN-FN_LEN /* Max l{ngd p} dev */ -#define MAX_DBKEY_LENGTH (FN_LEN*2+1+1+4+4) /* extra 4+4 bytes for slave tmp - * tables */ +/* extra 4+4 bytes for slave tmp tables */ +#define MAX_DBKEY_LENGTH (NAME_LEN*2+1+1+4+4) #define MAX_ALIAS_NAME 256 #define MAX_FIELD_NAME 34 /* Max colum name length +2 */ #define MAX_SYS_VAR_LENGTH 32 -#define MAX_KEY 64 /* Max used keys */ +#define MAX_KEY MAX_INDEXES /* Max used keys */ #define MAX_REF_PARTS 16 /* Max parts used as ref */ -#if SIZEOF_CHARP > 4 -#define MAX_KEY_LENGTH 3072 /* max possible key, if 64 bits */ -#else -#define MAX_KEY_LENGTH 1024 /* max possible key, if 32 bits */ -#endif +#define MAX_KEY_LENGTH 3072 /* max possible key */ #if SIZEOF_OFF_T > 4 #define MAX_REFLENGTH 8 /* Max length for record ref */ #else diff --git a/strings/conf_to_src.c b/strings/conf_to_src.c index 5a6adb398da..9ec2224ab62 100644 --- a/strings/conf_to_src.c +++ b/strings/conf_to_src.c @@ -171,50 +171,68 @@ static int my_read_charset_file(const char *filename) return FALSE; } +static int +is_case_sensitive(CHARSET_INFO *cs) +{ + return (cs->sort_order && + cs->sort_order['A'] < cs->sort_order['a'] && + cs->sort_order['a'] < cs->sort_order['B']) ? 1 : 0; +} + void dispcset(FILE *f,CHARSET_INFO *cs) { fprintf(f,"{\n"); fprintf(f," %d,%d,%d,\n",cs->number,0,0); - fprintf(f," MY_CS_COMPILED%s%s,\n", + fprintf(f," MY_CS_COMPILED%s%s%s,\n", cs->state & MY_CS_BINSORT ? "|MY_CS_BINSORT" : "", - cs->state & MY_CS_PRIMARY ? "|MY_CS_PRIMARY" : ""); + cs->state & MY_CS_PRIMARY ? "|MY_CS_PRIMARY" : "", + is_case_sensitive(cs) ? "|MY_CS_CSSORT" : ""); if (cs->name) { - fprintf(f," \"%s\",\n",cs->csname); - fprintf(f," \"%s\",\n",cs->name); - fprintf(f," \"\",\n"); - fprintf(f," ctype_%s,\n",cs->name); - fprintf(f," to_lower_%s,\n",cs->name); - fprintf(f," to_upper_%s,\n",cs->name); + fprintf(f," \"%s\", /* cset name */\n",cs->csname); + fprintf(f," \"%s\", /* coll name */\n",cs->name); + fprintf(f," \"\", /* comment */\n"); + fprintf(f," NULL, /* tailoring */\n"); + fprintf(f," ctype_%s, /* ctype */\n",cs->name); + fprintf(f," to_lower_%s, /* lower */\n",cs->name); + fprintf(f," to_upper_%s, /* upper */\n",cs->name); if (cs->sort_order) - fprintf(f," sort_order_%s,\n",cs->name); + fprintf(f," sort_order_%s, /* sort_order */\n",cs->name); else - fprintf(f," NULL,\n"); - fprintf(f," to_uni_%s,\n",cs->name); - fprintf(f," from_uni_%s,\n",cs->name); + fprintf(f," NULL, /* sort_order */\n"); + fprintf(f," NULL, /* contractions */\n"); + fprintf(f," NULL, /* sort_order_big*/\n"); + fprintf(f," to_uni_%s, /* to_uni */\n",cs->name); } else { - fprintf(f," NULL,\n"); - fprintf(f," NULL,\n"); - fprintf(f," NULL,\n"); - fprintf(f," NULL,\n"); - fprintf(f," NULL,\n"); - fprintf(f," NULL,\n"); - fprintf(f," NULL,\n"); - fprintf(f," NULL,\n"); - fprintf(f," NULL,\n"); + fprintf(f," NULL, /* cset name */\n"); + fprintf(f," NULL, /* coll name */\n"); + fprintf(f," NULL, /* comment */\n"); + fprintf(f," NULL, /* tailoging */\n"); + fprintf(f," NULL, /* ctype */\n"); + fprintf(f," NULL, /* lower */\n"); + fprintf(f," NULL, /* upper */\n"); + fprintf(f," NULL, /* sort order */\n"); + fprintf(f," NULL, /* contractions */\n"); + fprintf(f," NULL, /* sort_order_big*/\n"); + fprintf(f," NULL, /* to_uni */\n"); } - - fprintf(f," \"\",\n"); - fprintf(f," \"\",\n"); - fprintf(f," 0,\n"); - fprintf(f," 0,\n"); - fprintf(f," 0,\n"); + + fprintf(f," NULL, /* from_uni */\n"); + fprintf(f," NULL, /* state map */\n"); + fprintf(f," NULL, /* ident map */\n"); + fprintf(f," 1, /* strxfrm_multiply*/\n"); + fprintf(f," 1, /* mbminlen */\n"); + fprintf(f," 1, /* mbmaxlen */\n"); + fprintf(f," 0, /* min_sort_char */\n"); + fprintf(f," 255, /* max_sort_char */\n"); + fprintf(f," 0, /* escape_with_backslash_is_dangerous */\n"); + fprintf(f," &my_charset_8bit_handler,\n"); if (cs->state & MY_CS_BINSORT) - fprintf(f," &my_collation_bin_handler,\n"); + fprintf(f," &my_collation_8bit_bin_handler,\n"); else fprintf(f," &my_collation_8bit_simple_ci_handler,\n"); fprintf(f,"}\n"); @@ -253,6 +271,11 @@ main(int argc, char **argv __attribute__((unused))) } } + + fprintf(f,"#include <my_global.h>\n"); + fprintf(f,"#include <m_ctype.h>\n\n"); + + for (cs=all_charsets; cs < all_charsets+256; cs++) { if (simple_cs_is_full(cs)) diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index 4768e42a0b0..b18e5ee59d2 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -6706,6 +6706,14 @@ static const char esperanto[]= "& U < \\u016d <<< \\u016c"; /* + A simplified version of Hungarian, without consonant contractions. +*/ +static const char hungarian[]= + "&O < \\u00F6 <<< \\u00D6 << \\u0151 <<< \\u0150" + "&U < \\u00FC <<< \\u00DC << \\u0171 <<< \\u0170"; + + +/* Unicode Collation Algorithm: Collation element (weight) scanner, for consequent scan of collations @@ -8627,6 +8635,39 @@ CHARSET_INFO my_charset_ucs2_esperanto_uca_ci= }; +CHARSET_INFO my_charset_ucs2_hungarian_uca_ci= +{ + 146,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_hungarian_ci",/* name */ + "", /* comment */ + hungarian, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* contractions */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + my_unicase_default, /* caseinfo */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 1, /* caseup_multiply */ + 1, /* casedn_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + ' ', /* pad char */ + 0, /* escape_with_backslash_is_dangerous */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + + #endif @@ -9252,6 +9293,38 @@ CHARSET_INFO my_charset_utf8_esperanto_uca_ci= &my_collation_any_uca_handler }; +CHARSET_INFO my_charset_utf8_hungarian_uca_ci= +{ + 210,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "utf8", /* cs name */ + "utf8_hungarian_ci",/* name */ + "", /* comment */ + hungarian, /* tailoring */ + ctype_utf8, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* contractions */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + my_unicase_default, /* caseinfo */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 1, /* caseup_multiply */ + 1, /* casedn_multiply */ + 1, /* mbminlen */ + 3, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + ' ', /* pad char */ + 0, /* escape_with_backslash_is_dangerous */ + &my_charset_utf8_handler, + &my_collation_any_uca_handler +}; + #endif /* HAVE_CHARSET_utf8 */ #endif /* HAVE_UCA_COLLATIONS */ diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 80a7bd84601..e2629f445cb 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1373,14 +1373,50 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *cs, return (int) (t_is_prefix ? t-te : ((se-s) - (te-t))); } -static int my_strnncollsp_ucs2_bin(CHARSET_INFO *cs, +static int my_strnncollsp_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)), const uchar *s, uint slen, const uchar *t, uint tlen, my_bool diff_if_only_endspace_difference __attribute__((unused))) { - /* TODO: Needs to be fixed to handle end space! */ - return my_strnncoll_ucs2_bin(cs,s,slen,t,tlen,0); + const uchar *se, *te; + uint minlen; + + /* extra safety to make sure the lengths are even numbers */ + slen= (slen >> 1) << 1; + tlen= (tlen >> 1) << 1; + + se= s + slen; + te= t + tlen; + + for (minlen= min(slen, tlen); minlen; minlen-= 2) + { + int s_wc= s[0] * 256 + s[1]; + int t_wc= t[0] * 256 + t[1]; + if ( s_wc != t_wc ) + return s_wc > t_wc ? 1 : -1; + + s+= 2; + t+= 2; + } + + if (slen != tlen) + { + int swap= 1; + if (slen < tlen) + { + s= t; + se= te; + swap= -1; + } + + for ( ; s < se ; s+= 2) + { + if (s[0] || s[1] != ' ') + return (s[0] == 0 && s[1] < ' ') ? -swap : swap; + } + } + return 0; } diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c index 16b8ce5aac4..0bc465f16ea 100644 --- a/strings/ctype-win1250ch.c +++ b/strings/ctype-win1250ch.c @@ -514,42 +514,84 @@ static int my_strnxfrm_win1250ch(CHARSET_INFO * cs __attribute__((unused)), #ifdef REAL_MYSQL -static uchar NEAR like_range_prefix_min_win1250ch[] = +static uchar NEAR like_range_prefix_min_win1250ch[]= { -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, -48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, -80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, -96, 54, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, -80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 165, 124, 125, 126, 0, -0, 0, 130, 0, 132, 133, 134, 135, 0, 137, 138, 139, 83, 84, 142, 90, -0, 145, 146, 147, 148, 149, 150, 151, 0, 153, 138, 155, 83, 84, 142, 90, -32, 161, 162, 76, 164, 165, 166, 167, 168, 65, 83, 171, 172, 173, 174, 90, -176, 177, 178, 76, 180, 181, 0, 183, 184, 65, 83, 187, 76, 189, 76, 90, -82, 65, 65, 65, 65, 76, 67, 67, 200, 69, 69, 69, 69, 73, 73, 68, -68, 78, 78, 79, 79, 79, 79, 215, 216, 85, 85, 85, 85, 89, 84, 223, -82, 65, 65, 65, 65, 76, 67, 67, 200, 69, 69, 69, 69, 73, 73, 68, -68, 78, 78, 79, 79, 79, 79, 247, 216, 85, 85, 85, 85, 89, 84, 255, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; -static uchar NEAR like_range_prefix_max_win1250ch[] = { -182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, -182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, -160, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, -48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -64, 185, 98, 73, 240, 234, 102, 103, 104, 238, 106, 107, 179, 109, 242, 245, -112, 113, 224, 186, 254, 251, 118, 119, 120, 253, 159, 91, 92, 93, 94, 95, -96, 54, 98, 73, 240, 234, 102, 103, 104, 238, 106, 107, 179, 109, 242, 245, -112, 113, 224, 186, 254, 251, 118, 119, 120, 253, 159, 165, 124, 125, 126, 182, -182, 182, 130, 182, 132, 133, 134, 135, 182, 137, 154, 139, 186, 254, 158, 159, -182, 145, 146, 147, 148, 149, 150, 151, 182, 153, 154, 155, 186, 254, 158, 159, -32, 161, 162, 179, 164, 165, 166, 167, 168, 185, 186, 171, 172, 173, 174, 159, -176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 179, 189, 179, 159, -224, 185, 185, 185, 185, 179, 238, 238, 200, 234, 234, 234, 234, 238, 238, 240, -240, 242, 242, 245, 245, 245, 245, 215, 248, 251, 251, 251, 251, 253, 254, 223, -224, 185, 185, 185, 185, 179, 238, 238, 200, 234, 234, 234, 234, 238, 238, 240, -240, 242, 242, 245, 245, 245, 245, 247, 248, 251, 251, 251, 251, 253, 254, 255, + +/* + The letter "C" is a special case: + "CH" is sorted between "H" and "I". + prefix_max for "C" is "I": prefix_max[0x43] == 0x49 + prefix_max for "c" is "i": prefix_max[0x63] == 0x69 + For all other characters: prefix_max[i] == i +*/ + +static uchar NEAR like_range_prefix_max_win1250ch[]= +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x49, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x62, 0x69, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; #define min_sort_char '\x20' diff --git a/strings/decimal.c b/strings/decimal.c index ea6ac2caf38..5fb37d374a2 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -973,7 +973,7 @@ int double2decimal(double from, decimal_t *to) { /* TODO: fix it, when we'll have dtoa */ char s[400], *end; - sprintf(s, "%f", from); + sprintf(s, "%.16G", from); end= strend(s); return string2decimal(s, to, &end); } @@ -1069,9 +1069,9 @@ int decimal2longlong(decimal_t *from, longlong *to) } } /* boundary case: 9223372036854775808 */ - if (unlikely(from->sign==0 && x < 0 && -x < 0)) + if (unlikely(from->sign==0 && x == LONGLONG_MIN)) { - *to= -1-x; + *to= LONGLONG_MAX; return E_DEC_OVERFLOW; } @@ -1986,7 +1986,11 @@ int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to) carry+=hi; } for (; carry; buf0--) + { + if (buf0 < to->buf) + return E_DEC_OVERFLOW; ADD(*buf0, *buf0, 0, carry); + } } /* Now we have to check for -0.000 case */ @@ -2671,7 +2675,8 @@ void test_pr(const char *s1, int prec, int dec, char filler, const char *orig, int slen= sizeof(s2); int res; - sprintf(s, "'%s', %d, %d, '%c'", s1, prec, dec, filler); + sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'", + s1, prec, dec, filler); end= strend(s1); string2decimal(s1, &a, &end); res= decimal2string(&a, s2, &slen, prec, dec, filler); diff --git a/support-files/MacOSX/make_mysql_pkg.pl b/support-files/MacOSX/make_mysql_pkg.pl deleted file mode 100644 index 22283d57098..00000000000 --- a/support-files/MacOSX/make_mysql_pkg.pl +++ /dev/null @@ -1,475 +0,0 @@ -#!/usr/bin/perl -w -# -# -# make_mysql_pkg.pl -# -# This script creates a Mac OS X installation package -# of MySQL for Apple's Installer application. -# -# To use it: -# -# 1.) Unpack the mysql source tarball and cd into the directory -# 2.) execute this script -# -# -# Written by Marc Liyanage (http://www.entropy.ch) -# -# History: -# -# When Who What -# ------------------------------------------------------------------ -# 2001-09-16 Marc Liyanage First version -# 2001-11-18 Marc Liyanage Improved configure directory options -# - -use strict; -use DirHandle; - -my $data = {}; - -$data->{PREFIX_DIR} = "/usr/local/mysql"; -$data->{CONFIG} = join(" ", - "--prefix=$data->{PREFIX_DIR}", - "--localstatedir=$data->{PREFIX_DIR}/data", - "--libdir=$data->{PREFIX_DIR}/lib", - "--includedir=$data->{PREFIX_DIR}/include", - "--with-named-z-libs=/usr/local/libz.a", - "--with-innodb", - "--with-server-suffix='-entropy.ch'", - "--with-comment='http://www.entropy.ch/software/macosx/mysql/'", - "--with-mysqld-user=mysql", - "--enable-assembler", - "CFLAGS=\"-DHAVE_BROKEN_REALPATH -lncurses\"", -); - - - - - -prepare($data); -configure_source($data); -make($data); -make_binary_distribution($data); -create_pax_root($data); -create_package($data); -cleanup($data); - -print "Package $data->{PACKAGE_TARBALL_FILENAME} created\n"; - - - - - - -# Subroutines follow here... - - - - -# Prepares data in the global $data hash, like version numbers, -# directory names etc. Also makes sure that no old stuff -# is in our way. -# -sub prepare { - - my ($data) = @_; - - # Keep the current wd for reference - # - $data->{OLDWD} = `pwd`; - chomp($data->{OLDWD}); - - # Look for configure script - # - unless (-f "configure") { - abort($data, "Unable to find 'configure', make sure you're in the MySQL source toplevel directory!"); - } - - # Try to find version number there - # - my $mysql_version_h = `cat configure`; - ($data->{VERSION}) = $mysql_version_h =~ /^VERSION=(.+?)$/m; - - unless ($data->{VERSION} =~ /\d+/) { - abort($data, "Unable to find MySQL version number!"); - } - - debug($data, "found MySQL version number $data->{VERSION}"); - - - # PAXROOT_DIR is where we will build our own little - # fake /usr/local directory. Make sure it doesn't exist, - # then try to create it. - # - $data->{PAXROOT_DIR} = "/tmp/mysql-$data->{VERSION}-paxroot"; - - if (-e $data->{PAXROOT_DIR}) { - abort($data, "$data->{PAXROOT_DIR} exists, please remove first"); - } - - if (system("mkdir $data->{PAXROOT_DIR}")) { - abort($data, "Unable to mkdir $data->{PAXROOT_DIR}, please make sure you have the right permissions!"); - } - - - # PACKAGE_DIR is where we will build the package directory - # hierarchy, according to the standard .pkg layout. - # - $data->{PACKAGE_NAME} = "mysql-$data->{VERSION}.pkg"; - $data->{PACKAGE_DIR} = "/tmp/$data->{PACKAGE_NAME}"; - - if (-e $data->{PACKAGE_DIR}) { - abort($data, "$data->{PACKAGE_DIR} exists, please remove first"); - } - - if (system("mkdir $data->{PACKAGE_DIR}")) { - abort($data, "Unable to mkdir $data->{PACKAGE_DIR}, please make sure you have the right permissions!"); - } - - -} - - - -# Configure the MySQL source with our options -# -sub configure_source { - - my ($data) = @_; - - if (system("./configure $data->{CONFIG}")) { - abort($data, "Unable to configure!"); - } - -} - - - - -# Build the software -# -sub make { - - my ($data) = @_; - - if (system("make")) { - abort($data, "Unable to make!"); - } - -} - - - -# We don't ever install the software, but instead we use an -# included script to create a binary distribution -# tarball. -# -sub make_binary_distribution { - - my ($data) = @_; - - if (system("./scripts/make_binary_distribution > make_binary_distribution.out")) { - abort($data, "Unable to make_binary_distribution!"); - } - - my @output = `cat make_binary_distribution.out`; - my $last_line = $output[-1]; - unlink("make_binary_distribution.out"); - - my ($tarball_filename, $tarball_directory) = $last_line =~ /^((.+)\.tar\.gz) created/i; - - unless ($tarball_filename and -f $tarball_filename) { - abort($data, "Unable determine the output filename of scripts/make_binary_distribution!"); - } - - $data->{BINARY_TARBALL_FILENAME} = $tarball_filename; - $data->{BINARY_TARBALL_DIRECTORY} = $tarball_directory; - -} - - - - -# Now we build a fake /usr/local directory hierarchy. -# This will be fed to the pax tool to create the archive. -# -sub create_pax_root { - - my ($data) = @_; - - # Go there and try to extract the binary distribution - # tarball which we created in the previous step. - # - chdir($data->{PAXROOT_DIR}); - my $tarfile = "$data->{OLDWD}/$data->{BINARY_TARBALL_FILENAME}"; - - if (system("tar -xzf $tarfile")) { - abort($data, "Unable to extract $tarfile inside $data->{PAXROOT_DIR}"); - } - - # Rename it to what we want it to be in the - # installed /usr/local directory later on, i.e. - # mysql-<version>. Then create a symlink from - # mysql to mysql-<version> - # - rename($data->{BINARY_TARBALL_DIRECTORY}, "mysql-$data->{VERSION}"); - symlink("mysql-$data->{VERSION}", "mysql"); - - - # We create a bunch of symlinks in /usr/local/bin and - # /usr/local/share/man so that the end-user will not - # have to adjust PATH and MANPATH to include the - # /usr/local/mysql/bin and man directories. - # - system("mkdir -p $_") foreach qw(bin share/man); - - - # First create the symlinks in the bin directory - # - # 2001-02-13: we no longer use symlinks for the binaries, we - # use small dummy scripts instead because the - # mysql scripts do a lot of guesswork with their - # own path and that will not work when called via the symlink - # -# symlink("../mysql/bin/$_", "$_") foreach (grep {$_ !~ /^\.+$/} DirHandle->new("../mysql/bin")->read()); - - chdir("bin"); - - foreach my $command (grep {$_ !~ /^\.+$/} DirHandle->new("../mysql/bin")->read()) { - - my $scriptcode = qq+#!/bin/sh\n# Part of the entropy.ch mysql package\ncd /usr/local/mysql/\nexec ./bin/$command "\$\@"\n+; - open(SCRIPTFILE, ">$command") or die "Unable to write open $command\n"; - print SCRIPTFILE $scriptcode; - close(SCRIPTFILE); - chmod(0755, $command); - - } - - - - - - - - # Now include the man pages. Two problems here: - # 1.) the make_binary_distribution script does not seem - # to include the man pages, so we have to copy them over - # now. [outdated, was fixed by MySQL!] - # 2.) The man pages could be in different sections, so - # we have to recursively copy *and* symlink them. - # - - # First find out what's there in the source distribution. - # Store the names of the manpages in anonymous - # arrays which in turn will be stored in a hash, using - # the section numbers as hash keys. - # - chdir("$data->{PAXROOT_DIR}/mysql"); - my %man_sections; - foreach my $manpage (grep {$_ =~ /^.+\.(\d+)$/} DirHandle->new("man")->read()) { - - my ($section) = $manpage =~ /\.(\d+)$/; - - $man_sections{$section} ||= []; - push @{$man_sections{$section}}, "$manpage"; - - } - - - # Now iterate through the sections and man pages, - # and copy/symlink the man pages - # - chdir("$data->{PAXROOT_DIR}/share/man/"); - - foreach my $section (keys(%man_sections)) { - - system("mkdir -p man$section"); - chdir("man$section"); - - foreach my $manpage (@{$man_sections{$section}}) { - - symlink("../../../mysql/man/$manpage", $manpage) - - } - - chdir(".."); - - } - - - - # Fix up the library and lib directories. They are packed up wrong in the - # binary distribution tarball. - # - # (no longer needed as of 3.23.47) - # (oops, still needed because 3.23.47 is broken...) - # -# if (-d "$data->{PAXROOT_DIR}/mysql/lib/mysql") { -# abort($data, "$data->{PAXROOT_DIR}/mysql/lib/mysql exists, layout has changed!"); -# } -# chdir("$data->{PAXROOT_DIR}/mysql/lib/"); -# system("mkdir -p mysql"); -# system("mv * mysql"); - -# if (-d "$data->{PAXROOT_DIR}/mysql/include/mysql") { -# abort($data, "$data->{PAXROOT_DIR}/mysql/include/mysql exists, layout has changed!"); -# } -# chdir("$data->{PAXROOT_DIR}/mysql/include/"); -# system("mkdir -p mysql"); -# system("mv * mysql"); - - - - - - - - - -} - - - -# Take the pax root directory, create a few auxiliary -# files and then pack everything up into a tarball -# -sub create_package { - - my ($data) = @_; - - # Create the resources directory in which all - # interesting files for this package will be stored - # - $data->{PKG_RESOURCES_DIR} = "$data->{PACKAGE_DIR}/Contents/Resources"; - - if (system("mkdir -p $data->{PKG_RESOURCES_DIR}")) { - abort("Unable to create package resources dir $data->{PKG_RESOURCES_DIR}"); - } - - - # Create the big archive with all the files using - # the pax tool - # - chdir($data->{PAXROOT_DIR}); - if(system("pax -w . | gzip -c > $data->{PKG_RESOURCES_DIR}/mysql-$data->{VERSION}.pax.gz")) { - abort("Unable to create package pax file"); - } - - - # Create the "Bill Of Materials" (bom) file. - # - if(system("mkbom . $data->{PKG_RESOURCES_DIR}/mysql-$data->{VERSION}.bom")) { - abort("Unable to create package bom file"); - } - - - # Create the ".sizes" file with some information about the package - # - my $size_uncompressed = `du -sk $data->{PAXROOT_DIR} | cut -f 1`; - chomp($size_uncompressed); - - my $size_compressed = `du -sk $data->{PACKAGE_DIR} | cut -f 1`; - chomp($size_compressed); - - my $numfiles = `find /tmp/mysql-$data->{VERSION}-paxroot | wc -l`; - $numfiles--; - - open(SIZESFILE, ">$data->{PKG_RESOURCES_DIR}/mysql-$data->{VERSION}.sizes") or abort("Unable to write open sizes file $data->{PKG_RESOURCES_DIR}/mysql-$data->{VERSION}.sizes"); - print SIZESFILE "NumFiles $numfiles\n"; - print SIZESFILE "InstalledSize $size_uncompressed\n"; - print SIZESFILE "CompressedSize $size_compressed\n"; - close(SIZESFILE); - - - # Create the ".info" file with more information abou the package. - # - open(INFOFILE, ">$data->{PKG_RESOURCES_DIR}/mysql-$data->{VERSION}.info") or abort("Unable to write open sizes file $data->{PKG_RESOURCES_DIR}/mysql-$data->{VERSION}.info"); - my $infodata = join("", <DATA>); - $infodata =~ s/<%(.+?)%>/$data->{$1}/eg; - abort("Unable to get info file data from __DATA__!") unless ($infodata =~ /\w+/); - print INFOFILE $infodata; - close(INFOFILE); - - - - # Finally, create the .tar.gz file for the package, - # this is our end result - # - chdir($data->{PACKAGE_DIR}); - chdir(".."); - - $data->{PACKAGE_TARBALL_FILENAME} = "$data->{PACKAGE_NAME}.tar.gz"; - - if(system("tar -czf $data->{OLDWD}/$data->{PACKAGE_TARBALL_FILENAME} $data->{PACKAGE_NAME}")) { - abort("Unable to create package tar file $data->{OLDWD}/$data->{PACKAGE_TARBALL_FILENAME}"); - } - - - -} - - -# Abort with an error message -# -sub abort { - - my ($data, $errormessage) = @_; - - my ($caller) = (caller(1))[3]; - $caller =~ s/^main:://; - - print "*** Error: $caller(): $errormessage\n"; - - exit 1; - -} - - -# Output informative messages -# -sub debug { - - my ($data, $message) = @_; - - my ($caller) = (caller(1))[3]; - $caller =~ s/^main:://; - - print "*** Info: $caller(): $message\n"; - -} - - - -# Remove temporary items -# -sub cleanup { - - my ($data) = @_; - - chdir($data->{OLDWD}); - - system("rm -rf $data->{PACKAGE_DIR}"); - system("rm -rf $data->{PAXROOT_DIR}"); - system("rm $data->{BINARY_TARBALL_FILENAME}"); - -} - - - - -__DATA__ -Title MySQL -Version <%VERSION%> -Description The MySQL database server in a convenient Mac OS X package. Some additional configuration is necessary, please see http://www.entropy.ch/software/macosx/mysql/ -DefaultLocation /usr/local -Diskname (null) -DeleteWarning -NeedsAuthorization YES -DisableStop NO -UseUserMask NO -Application NO -Relocatable NO -Required NO -InstallOnly NO -RequiresReboot NO -InstallFat NO diff --git a/support-files/Makefile.am b/support-files/Makefile.am index 972d1dc7038..26d51438a1b 100644 --- a/support-files/Makefile.am +++ b/support-files/Makefile.am @@ -107,7 +107,5 @@ SUFFIXES = .sh $< > $@-t @MV@ $@-t $@ -all: binary-configure - # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/support-files/my-huge.cnf.sh b/support-files/my-huge.cnf.sh index f7a47054658..5dc3e5a1900 100644 --- a/support-files/my-huge.cnf.sh +++ b/support-files/my-huge.cnf.sh @@ -33,7 +33,7 @@ sort_buffer_size = 2M read_buffer_size = 2M read_rnd_buffer_size = 8M myisam_sort_buffer_size = 64M -thread_cache = 8 +thread_cache_size = 8 query_cache_size = 32M # Try number of CPU's*2 for thread_concurrency thread_concurrency = 8 diff --git a/support-files/my-innodb-heavy-4G.cnf.sh b/support-files/my-innodb-heavy-4G.cnf.sh index b3f43272a7d..77c6cea56d5 100644 --- a/support-files/my-innodb-heavy-4G.cnf.sh +++ b/support-files/my-innodb-heavy-4G.cnf.sh @@ -128,7 +128,7 @@ join_buffer_size = 8M # the amount of thread creations needed if you have a lot of new # connections. (Normally this doesn't give a notable performance # improvement if you have a good thread implementation.) -thread_cache = 8 +thread_cache_size = 8 # This permits the application to give the threads system a hint for the # desired number of threads that should be run at the same time. This diff --git a/support-files/my-large.cnf.sh b/support-files/my-large.cnf.sh index 1e7d9f7aade..4dc3f929c48 100644 --- a/support-files/my-large.cnf.sh +++ b/support-files/my-large.cnf.sh @@ -33,7 +33,7 @@ sort_buffer_size = 1M read_buffer_size = 1M read_rnd_buffer_size = 4M myisam_sort_buffer_size = 64M -thread_cache = 8 +thread_cache_size = 8 query_cache_size= 16M # Try number of CPU's*2 for thread_concurrency thread_concurrency = 8 diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 6dbffdc9778..1892e8b4a46 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -56,12 +56,18 @@ if test -z "$basedir" then basedir=@prefix@ bindir=@bindir@ - datadir=@localstatedir@ + if test -z "$datadir" + then + datadir=@localstatedir@ + fi sbindir=@sbindir@ libexecdir=@libexecdir@ else bindir="$basedir/bin" - datadir="$basedir/data" + if test -z "$datadir" + then + datadir="$basedir/data" + fi sbindir="$basedir/sbin" libexecdir="$basedir/libexec" fi diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 265f576cd86..912c6f9e051 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -35,7 +35,7 @@ Release: %{release} License: %{license} Source: http://www.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/mysql-%{mysql_version}.tar.gz URL: http://www.mysql.com/ -Packager: Lenz Grimmer <build@mysql.com> +Packager: MySQL Production Engineering Team <build@mysql.com> Vendor: MySQL AB Provides: msqlormysql MySQL-server mysql BuildRequires: ncurses-devel @@ -325,7 +325,13 @@ fi make test-force || true # Save mysqld-max -mv sql/mysqld sql/mysqld-max +# check if mysqld was installed in .libs/ +if test -f sql/.libs/mysqld +then + cp sql/.libs/mysqld sql/mysqld-max +else + cp sql/mysqld sql/mysqld-max +fi nm --numeric-sort sql/mysqld-max > sql/mysqld-max.sym # Save the perror binary so it supports the NDB error codes (BUG#13740) mv extra/perror extra/perror.ndb @@ -361,15 +367,21 @@ BuildMySQL "--disable-shared \ %if %{STATIC_BUILD} --with-mysqld-ldflags='-all-static' \ --with-client-ldflags='-all-static' \ - --with-zlib-dir=bundled \ $USE_OTHER_LIBC_DIR \ +%else %endif + --with-zlib-dir=bundled \ --with-comment=\"MySQL Community Edition - Standard (GPL)\" \ --with-server-suffix='%{server_suffix}' \ --with-archive-storage-engine \ --with-innodb \ --with-big-tables" -nm --numeric-sort sql/mysqld > sql/mysqld.sym +if test -f sql/.libs/mysqld +then + nm --numeric-sort sql/.libs/mysqld > sql/mysqld.sym +else + nm --numeric-sort sql/mysqld > sql/mysqld.sym +fi # We might want to save the config log file if test -n "$MYSQL_CONFLOG_DEST" @@ -507,22 +519,22 @@ echo "Restarting mysqld." %preun server if test $1 = 0 then - # Stop MySQL before uninstalling it + # Stop MySQL before uninstalling it if test -x %{_sysconfdir}/init.d/mysql then %{_sysconfdir}/init.d/mysql stop > /dev/null - fi - # Remove autostart of mysql - # for older SuSE Linux versions - if test -x /sbin/insserv - then - /sbin/insserv -r %{_sysconfdir}/init.d/mysql - # use chkconfig on Red Hat and newer SuSE releases - elif test -x /sbin/chkconfig - then - /sbin/chkconfig --del mysql - fi + # Remove autostart of mysql + # for older SuSE Linux versions + if test -x /sbin/insserv + then + /sbin/insserv -r %{_sysconfdir}/init.d/mysql + # use chkconfig on Red Hat and newer SuSE releases + elif test -x /sbin/chkconfig + then + /sbin/chkconfig --del mysql + fi + fi fi # We do not remove the mysql user since it may still own a lot of @@ -541,41 +553,48 @@ fi %doc %attr(644, root, root) %{_infodir}/mysql.info* -%doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* +%doc %attr(644, root, man) %{_mandir}/man1/myisamchk.1* +%doc %attr(644, root, man) %{_mandir}/man1/myisamlog.1* +%doc %attr(644, root, man) %{_mandir}/man1/myisampack.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqld.1* -%doc %attr(644, root, man) %{_mandir}/man1/mysql_fix_privilege_tables.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqld_multi.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqld_safe.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysql_fix_privilege_tables.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysqlmanager.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* %doc %attr(644, root, man) %{_mandir}/man1/perror.1* %doc %attr(644, root, man) %{_mandir}/man1/replace.1* +%doc %attr(644, root, man) %{_mandir}/man1/safe_mysqld.1* %ghost %config(noreplace,missingok) %{_sysconfdir}/my.cnf %ghost %config(noreplace,missingok) %{_sysconfdir}/mysqlmanager.passwd -%attr(755, root, root) %{_bindir}/my_print_defaults %attr(755, root, root) %{_bindir}/myisamchk %attr(755, root, root) %{_bindir}/myisam_ftdump %attr(755, root, root) %{_bindir}/myisamlog %attr(755, root, root) %{_bindir}/myisampack +%attr(755, root, root) %{_bindir}/my_print_defaults +%attr(755, root, root) %{_bindir}/mysqlbug %attr(755, root, root) %{_bindir}/mysql_convert_table_format %attr(755, root, root) %{_bindir}/mysql_create_system_tables +%attr(755, root, root) %{_bindir}/mysqld_multi +%attr(755, root, root) %{_bindir}/mysqld_safe %attr(755, root, root) %{_bindir}/mysql_explain_log %attr(755, root, root) %{_bindir}/mysql_fix_extensions %attr(755, root, root) %{_bindir}/mysql_fix_privilege_tables +%attr(755, root, root) %{_bindir}/mysqlhotcopy %attr(755, root, root) %{_bindir}/mysql_install_db %attr(755, root, root) %{_bindir}/mysql_secure_installation %attr(755, root, root) %{_bindir}/mysql_setpermission +%attr(755, root, root) %{_bindir}/mysqltest %attr(755, root, root) %{_bindir}/mysql_tzinfo_to_sql %attr(755, root, root) %{_bindir}/mysql_zap -%attr(755, root, root) %{_bindir}/mysqlbug -%attr(755, root, root) %{_bindir}/mysqld_multi -%attr(755, root, root) %{_bindir}/mysqld_safe -%attr(755, root, root) %{_bindir}/mysqlhotcopy -%attr(755, root, root) %{_bindir}/mysqltest %attr(755, root, root) %{_bindir}/perror %attr(755, root, root) %{_bindir}/replace -%attr(755, root, root) %{_bindir}/resolve_stack_dump %attr(755, root, root) %{_bindir}/resolveip +%attr(755, root, root) %{_bindir}/resolve_stack_dump %attr(755, root, root) %{_bindir}/safe_mysqld %attr(755, root, root) %{_sbindir}/mysqld @@ -604,10 +623,14 @@ fi %attr(755, root, root) %{_bindir}/mysqlimport %attr(755, root, root) %{_bindir}/mysqlshow +%doc %attr(644, root, man) %{_mandir}/man1/msql2mysql.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlaccess.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqladmin.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysqlbinlog.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysqlcheck.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqldump.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysqlimport.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlshow.1* %post shared @@ -645,6 +668,7 @@ fi %files devel %defattr(-, root, root, 0755) %doc EXCEPTIONS-CLIENT +%doc %attr(644, root, man) %{_mandir}/man1/mysql_config.1* %attr(755, root, root) %{_bindir}/comp_err %attr(755, root, root) %{_bindir}/mysql_config %dir %attr(755, root, root) %{_includedir}/mysql @@ -666,6 +690,8 @@ fi %{_libdir}/mysql/libndbclient.a %{_libdir}/mysql/libndbclient.la %{_libdir}/mysql/libvio.a +%{_libdir}/mysql/libz.a +%{_libdir}/mysql/libz.la %files shared %defattr(-, root, root, 0755) @@ -694,6 +720,29 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Fri Dec 12 2005 Rodrigo Novo <rodrigo@mysql.com> + +- Added zlib to the list of (static) libraries installed +- Added check against libtool wierdness (WRT: sql/mysqld || sql/.libs/mysqld) +- Compile MySQL with bundled zlib +- Fixed %packager name to "MySQL Production Engineering Team" + +* Mon Dec 05 2005 Joerg Bruehe <joerg@mysql.com> + +- Avoid using the "bundled" zlib on "shared" builds: + As it is not installed (on the build system), this gives dependency + problems with "libtool" causing the build to fail. + (Change was done on Nov 11, but left uncommented.) + +* Tue Nov 22 2005 Joerg Bruehe <joerg@mysql.com> + +- Extend the file existence check for "init.d/mysql" on un-install + to also guard the call to "insserv"/"chkconfig". + +* Thu Oct 27 2005 Lenz Grimmer <lenz@grimmer.com> + +- added more man pages + * Wed Oct 19 2005 Kent Boortz <kent@mysql.com> - Made yaSSL support an option (off by default) @@ -716,7 +765,7 @@ fi * Fri Oct 14 2005 Kent Boortz <kent@mysql.com> -- Removed unneeded/obsolte configure options +- Removed unneeded/obsolete configure options - Added archive engine to standard server - Removed the embedded server from experimental server - Changed suffix "-Max" => "-max" diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 65a4617445c..216961b3a80 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -36,7 +36,7 @@ #define VER "2.1" #define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */ -#define MAX_KEY 64 +#define MAX_KEY MAX_INDEXES #define MAX_SERVER_ARGS 64 /* set default options */ @@ -59,6 +59,8 @@ static my_bool have_innodb= FALSE; static const char *opt_basedir= "./"; +static longlong opt_getopt_ll_test= 0; + static int embedded_server_arg_count= 0; static char *embedded_server_args[MAX_SERVER_ARGS]; @@ -14317,6 +14319,7 @@ static void test_bug12243() mysql_autocommit(mysql, TRUE); /* restore default */ } + /* Bug#11718: query with function, join and order by returns wrong type */ @@ -14351,6 +14354,276 @@ static void test_bug11718() rc= mysql_query(mysql, "drop table t1, t2"); myquery(rc); } + + +/* + Bug #12925: Bad handling of maximum values in getopt +*/ +static void test_bug12925() +{ + myheader("test_bug12925"); + if (opt_getopt_ll_test) + DIE_UNLESS(opt_getopt_ll_test == LL(25600*1024*1024)); +} + + +/* + Bug#14210 "Simple query with > operator on large table gives server + crash" +*/ + +static void test_bug14210() +{ + MYSQL_STMT *stmt; + int rc, i; + const char *stmt_text; + ulong type; + + myheader("test_bug14210"); + + mysql_query(mysql, "drop table if exists t1"); + /* + To trigger the problem the table must be InnoDB, although the problem + itself is not InnoDB related. In case the table is MyISAM this test + is harmless. + */ + mysql_query(mysql, "create table t1 (a varchar(255)) type=InnoDB"); + rc= mysql_query(mysql, "insert into t1 (a) values (repeat('a', 256))"); + myquery(rc); + rc= mysql_query(mysql, "set @@session.max_heap_table_size=16384"); + /* Create a big enough table (more than max_heap_table_size) */ + for (i= 0; i < 8; i++) + { + rc= mysql_query(mysql, "insert into t1 (a) select a from t1"); + myquery(rc); + } + /* create statement */ + stmt= mysql_stmt_init(mysql); + type= (ulong) CURSOR_TYPE_READ_ONLY; + mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type); + + stmt_text= "select a from t1"; + + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + rc= mysql_stmt_execute(stmt); + while ((rc= mysql_stmt_fetch(stmt)) == 0) + ; + DIE_UNLESS(rc == MYSQL_NO_DATA); + + rc= mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); + rc= mysql_query(mysql, "set @@session.max_heap_table_size=default"); + myquery(rc); +} + +/* Bug#13488: wrong column metadata when fetching from cursor */ + +static void test_bug13488() +{ + MYSQL_BIND bind[3]; + MYSQL_STMT *stmt1; + int rc, f1, f2, f3, i; + const ulong type= CURSOR_TYPE_READ_ONLY; + const char *query= "select * from t1 left join t2 on f1=f2 where f1=1"; + + myheader("test_bug13488"); + + rc= mysql_query(mysql, "drop table if exists t1, t2"); + myquery(rc); + rc= mysql_query(mysql, "create table t1 (f1 int not null primary key)"); + myquery(rc); + rc= mysql_query(mysql, "create table t2 (f2 int not null primary key, " + "f3 int not null)"); + myquery(rc); + rc= mysql_query(mysql, "insert into t1 values (1), (2)"); + myquery(rc); + rc= mysql_query(mysql, "insert into t2 values (1,2), (2,4)"); + myquery(rc); + + memset(bind, 0, sizeof(bind)); + for (i= 0; i < 3; i++) + { + bind[i].buffer_type= MYSQL_TYPE_LONG; + bind[i].buffer_length= 4; + bind[i].length= 0; + } + bind[0].buffer=&f1; + bind[1].buffer=&f2; + bind[2].buffer=&f3; + + stmt1= mysql_stmt_init(mysql); + rc= mysql_stmt_attr_set(stmt1,STMT_ATTR_CURSOR_TYPE, (const void *)&type); + check_execute(stmt1, rc); + + rc= mysql_stmt_prepare(stmt1, query, strlen(query)); + check_execute(stmt1, rc); + + rc= mysql_stmt_execute(stmt1); + check_execute(stmt1, rc); + + rc= mysql_stmt_bind_result(stmt1, bind); + check_execute(stmt1, rc); + + rc= mysql_stmt_fetch(stmt1); + check_execute(stmt1, rc); + + rc= mysql_stmt_free_result(stmt1); + check_execute(stmt1, rc); + + rc= mysql_stmt_reset(stmt1); + check_execute(stmt1, rc); + + rc= mysql_stmt_close(stmt1); + check_execute(stmt1, rc); + + if (!opt_silent) + printf("data is: %s", (f1 == 1 && f2 == 1 && f3 == 2)?"OK": + "wrong"); + DIE_UNLESS(f1 == 1 && f2 == 1 && f3 == 2); + rc= mysql_query(mysql, "drop table t1, t2"); + myquery(rc); +} + +/* + Bug#13524: warnings of a previous command are not reset when fetching + from a cursor. +*/ + +static void test_bug13524() +{ + MYSQL_STMT *stmt; + int rc; + unsigned int warning_count; + const ulong type= CURSOR_TYPE_READ_ONLY; + const char *query= "select * from t1"; + + myheader("test_bug13524"); + + rc= mysql_query(mysql, "drop table if exists t1, t2"); + myquery(rc); + rc= mysql_query(mysql, "create table t1 (a int not null primary key)"); + myquery(rc); + rc= mysql_query(mysql, "insert into t1 values (1), (2), (3), (4)"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type); + check_execute(stmt, rc); + + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + + warning_count= mysql_warning_count(mysql); + DIE_UNLESS(warning_count == 0); + + /* Check that DROP TABLE produced a warning (no such table) */ + rc= mysql_query(mysql, "drop table if exists t2"); + myquery(rc); + warning_count= mysql_warning_count(mysql); + DIE_UNLESS(warning_count == 1); + + /* + Check that fetch from a cursor cleared the warning from the previous + command. + */ + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + warning_count= mysql_warning_count(mysql); + DIE_UNLESS(warning_count == 0); + + /* Cleanup */ + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + +/* + Bug#14845 "mysql_stmt_fetch returns MYSQL_NO_DATA when COUNT(*) is 0" +*/ + +static void test_bug14845() +{ + MYSQL_STMT *stmt; + int rc; + const ulong type= CURSOR_TYPE_READ_ONLY; + const char *query= "select count(*) from t1 where 1 = 0"; + + myheader("test_bug14845"); + + rc= mysql_query(mysql, "drop table if exists t1"); + myquery(rc); + rc= mysql_query(mysql, "create table t1 (id int(11) default null, " + "name varchar(20) default null)" + "engine=MyISAM DEFAULT CHARSET=utf8"); + myquery(rc); + rc= mysql_query(mysql, "insert into t1 values (1,'abc'),(2,'def')"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type); + check_execute(stmt, rc); + + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_fetch(stmt); + DIE_UNLESS(rc == 0); + + rc= mysql_stmt_fetch(stmt); + DIE_UNLESS(rc == MYSQL_NO_DATA); + + /* Cleanup */ + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + + +/* + Bug #15510: mysql_warning_count returns 0 after mysql_stmt_fetch which + should warn +*/ +static void test_bug15510() +{ + MYSQL_STMT *stmt; + MYSQL_RES *res; + int rc; + const char *query= "select 1 from dual where 1/0"; + + myheader("test_bug15510"); + + rc= mysql_query(mysql, "set @@sql_mode='ERROR_FOR_DIVISION_BY_ZERO'"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_fetch(stmt); + DIE_UNLESS(mysql_warning_count(mysql)); + + /* Cleanup */ + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "set @@sql_mode=''"); + myquery(rc); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -14393,6 +14666,9 @@ static struct my_option client_test_long_options[] = {"user", 'u', "User for login if not current user", (char **) &opt_user, (char **) &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif + {"getopt-ll-test", 'g', "Option for testing bug in getopt library", + (char **) &opt_getopt_ll_test, (char **) &opt_getopt_ll_test, 0, + GET_LL, REQUIRED_ARG, 0, 0, LONGLONG_MAX, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -14598,10 +14874,16 @@ static struct my_tests_st my_tests[]= { { "test_bug10760", test_bug10760 }, { "test_bug12001", test_bug12001 }, { "test_bug11718", test_bug11718 }, + { "test_bug12925", test_bug12925 }, { "test_bug11909", test_bug11909 }, { "test_bug11901", test_bug11901 }, { "test_bug11904", test_bug11904 }, { "test_bug12243", test_bug12243 }, + { "test_bug14210", test_bug14210 }, + { "test_bug13488", test_bug13488 }, + { "test_bug13524", test_bug13524 }, + { "test_bug14845", test_bug14845 }, + { "test_bug15510", test_bug15510}, { 0, 0 } }; diff --git a/vio/Makefile.am b/vio/Makefile.am index 0d4f052b30a..544639139de 100644 --- a/vio/Makefile.am +++ b/vio/Makefile.am @@ -20,23 +20,23 @@ else yassl_dummy_link_fix= endif INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include \ - $(openssl_includes) -LDADD= @CLIENT_EXTRA_LDFLAGS@ $(openssl_libs) + $(openssl_includes) $(yassl_includes) +LDADD= @CLIENT_EXTRA_LDFLAGS@ $(openssl_libs) $(yassl_libs) pkglib_LIBRARIES= libvio.a noinst_PROGRAMS = test-ssl test-sslserver test-sslclient noinst_HEADERS= vio_priv.h test_ssl_SOURCES= test-ssl.c $(yassl_dummy_link_fix) test_ssl_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \ ../mysys/libmysys.a ../strings/libmystrings.a \ - $(openssl_libs) + $(openssl_libs) $(yassl_libs) test_sslserver_SOURCES= test-sslserver.c $(yassl_dummy_link_fix) test_sslserver_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \ ../mysys/libmysys.a ../strings/libmystrings.a \ - $(openssl_libs) + $(openssl_libs) $(yassl_libs) test_sslclient_SOURCES= test-sslclient.c $(yassl_dummy_link_fix) test_sslclient_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \ ../mysys/libmysys.a ../strings/libmystrings.a \ - $(openssl_libs) + $(openssl_libs) $(yassl_libs) libvio_a_SOURCES= vio.c viosocket.c viossl.c viosslfactories.c # Don't update the files from bitkeeper diff --git a/vio/vio.c b/vio/vio.c index ff93cff959f..bc286b2d2bb 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -87,7 +87,7 @@ static void vio_init(Vio* vio, enum enum_vio_type type, #ifdef HAVE_OPENSSL if (type == VIO_TYPE_SSL) { - vio->viodelete =vio_ssl_delete; + vio->viodelete =vio_delete; vio->vioerrno =vio_ssl_errno; vio->read =vio_ssl_read; vio->write =vio_ssl_write; diff --git a/vio/vio_priv.h b/vio/vio_priv.h index c1c78cc6efa..eb495025ddd 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -28,7 +28,6 @@ void vio_ignore_timeout(Vio *vio, uint which, uint timeout); #ifdef HAVE_OPENSSL #include "my_net.h" /* needed because of struct in_addr */ -void vio_ssl_delete(Vio* vio); int vio_ssl_read(Vio *vio,gptr buf, int size); int vio_ssl_write(Vio *vio,const gptr buf,int size); void vio_ssl_timeout(Vio *vio, uint which, uint timeout); diff --git a/vio/viossl.c b/vio/viossl.c index e6af07c4b0b..1273814c551 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -69,25 +69,6 @@ report_errors() DBUG_VOID_RETURN; } -/* - Delete a vio object - - SYNPOSIS - vio_ssl_delete() - vio Vio object. May be 0. -*/ - - -void vio_ssl_delete(Vio * vio) -{ - if (vio) - { - if (vio->type != VIO_CLOSED) - vio_close(vio); - my_free((gptr) vio,MYF(0)); - } -} - int vio_ssl_errno(Vio *vio __attribute__((unused))) { diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 766d835d2c0..4ee27f1e491 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -191,9 +191,6 @@ void netware_ssl_cleanup() /* NetWare SSL initialization */ static void netware_ssl_init() { - /* initialize OpenSSL library */ - SSL_library_init(); - /* cleanup OpenSSL library */ NXVmRegisterExitHandler(netware_ssl_cleanup, NULL); } @@ -228,16 +225,17 @@ new_VioSSLConnectorFd(const char* key_file, ptr->ssl_method= 0; /* FIXME: constants! */ -#ifdef __NETWARE__ - netware_ssl_init(); -#endif - if (!ssl_algorithms_added) { DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()")); ssl_algorithms_added = TRUE; + SSL_library_init(); OpenSSL_add_all_algorithms(); } +#ifdef __NETWARE__ + netware_ssl_init(); +#endif + if (!ssl_error_strings_loaded) { DBUG_PRINT("info", ("todo:SSL_load_error_strings()")); @@ -319,17 +317,18 @@ new_VioSSLAcceptorFd(const char *key_file, /* FIXME: constants! */ ptr->session_id_context= ptr; -#ifdef __NETWARE__ - netware_ssl_init(); -#endif - if (!ssl_algorithms_added) { DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()")); ssl_algorithms_added = TRUE; + SSL_library_init(); OpenSSL_add_all_algorithms(); } +#ifdef __NETWARE__ + netware_ssl_init(); +#endif + if (!ssl_error_strings_loaded) { DBUG_PRINT("info", ("todo: SSL_load_error_strings()")); diff --git a/zlib/Makefile.am b/zlib/Makefile.am index e94d184a841..11b1991fa62 100644 --- a/zlib/Makefile.am +++ b/zlib/Makefile.am @@ -18,6 +18,8 @@ pkglib_LTLIBRARIES=libz.la +libz_la_LDFLAGS= -version-info 3:3:2 + noinst_HEADERS= crc32.h deflate.h inffast.h inffixed.h inflate.h \ inftrees.h trees.h zconf.h zlib.h zutil.h |