diff options
553 files changed, 10239 insertions, 3428 deletions
diff --git a/.bzrignore b/.bzrignore index e167619c1a6..ca4ba1432aa 100644 --- a/.bzrignore +++ b/.bzrignore @@ -9,6 +9,8 @@ *.d *.da *.exe +*.gcda +*.gcno *.gcov *.idb *.la @@ -209,6 +211,11 @@ bdb/dist/autom4te.cache/requests bdb/dist/autom4te.cache/traces.0 bdb/dist/config.hin bdb/dist/configure +bdb/dist/db.h +bdb/dist/db_config.h +bdb/dist/db_cxx.h +bdb/dist/db_int.h +bdb/dist/include.tcl bdb/dist/tags bdb/dist/template/db_server_proc bdb/dist/template/gen_client_ret @@ -334,6 +341,7 @@ client/sql_string.cpp client/ssl_test client/thimble client/thread_test +client/tmp.diff client_debug/* client_release/* client_test @@ -697,6 +705,7 @@ mysql-test/r/*.err mysql-test/r/*.log mysql-test/r/*.out mysql-test/r/*.reject +mysql-test/r/*.warnings mysql-test/r/alter_table.err mysql-test/r/archive.err mysql-test/r/bdb-alter-table-1.err @@ -762,10 +771,12 @@ mysql-test/r/rpl000016.eval mysql-test/r/rpl_log.eval mysql-test/r/slave-running.eval mysql-test/r/slave-stopped.eval +mysql-test/r/tmp.result mysql-test/r/udf.log mysql-test/share/mysql mysql-test/std_data/*.pem mysql-test/t/index_merge.load +mysql-test/t/tmp.test mysql-test/var mysql-test/var/* mysql.kdevprj diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 8055f337821..6f3c4222ed2 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -56,9 +56,9 @@ global_warnings="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wch #debug_extra_warnings="-Wuninitialized" c_warnings="$global_warnings -Wunused" cxx_warnings="$global_warnings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor" -base_max_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-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" +base_max_configs="--with-innodb --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 --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-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/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed index 2509fa50a7b..5ff033b2163 100644 --- a/BitKeeper/etc/collapsed +++ b/BitKeeper/etc/collapsed @@ -15,6 +15,8 @@ 45214442pBGT9KuZEGixBH71jTzbOA 45214a07hVsIGwvwa-WrO-jpeaSwVw 452a92d0-31-8wSzSfZi165fcGcXPA +452c6c6dAjuNghfc1ObZ_UQ5SCl85g +4538a7b0EbDHHkWPbIwxO6ZIDdg6Dg 454a7ef8gdvE_ddMlJyghvOAkKPNOQ 454bb488ijVLOUK_GFjcoISE0GxPUA 454bb9a8AwlGRC_wWLS2sNMoRBMRGw diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index 981b55c66ec..8051cf98b7a 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -35,9 +35,17 @@ fi CHANGESET=`bk -R prs -r+ -h -d':P:::I:' ChangeSet` CSETKEY=`bk -R prs -r+ -h -d':KEY:' ChangeSet` -BUG=`bk -R prs -r+ -h -d':C:' ChangeSet | sed -ne 's/^.*[Bb][Uu][Gg] *# *\([0-9][0-9]*\).*$/\1/p'` -WL=`bk -R prs -r+ -h -d':C:' ChangeSet | sed -ne 's/^.*[Ww][Ll] *# *\([0-9][0-9]*\).*$/ WL#\1/p'` - +# +# composing subject lines of commit mails. +# if a fix targets to a WL and there is a bug referred +# then X-Bug mail header will contain the first found bug's number +# +BUG=`bk -R prs -r+ -h -d':C:' ChangeSet | \ + sed -ne 's/[Bb][Uu][Gg] *# *\([0-9][0-9]*\).*$/BUG#\1/ + s/.*BUG#\([0-9][0-9]*\)/\1/p'` +WL=`bk -R prs -r+ -h -d':C:' ChangeSet | \ + sed -ne 's/[Ww][Ll] *# *\([0-9][0-9]*\).*$/WL#\1/ + s/.*\(WL#[0-9][0-9]*\)/ \1/p'` if [ "$BUG" = "" ] then TO=dev-public@mysql.com diff --git a/Docs/Makefile.am b/Docs/Makefile.am index 4722f61f5b9..ad78a30118e 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -26,7 +26,7 @@ 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. -install-data-hook: mysql.info +install-data-hook: $(srcdir)/mysql.info $(mkinstalldirs) $(DESTDIR)$(infodir) $(INSTALL_DATA) $(srcdir)/mysql.info $(DESTDIR)$(infodir) @@ -44,23 +44,23 @@ CLEAN_FILES: $(TXT_FILES) GT = $(srcdir)/Support/generate-text-files.pl -../INSTALL-SOURCE: mysql.info $(GT) - perl -w $(GT) mysql.info "installing-source" "windows-source-build" > $@ +../INSTALL-SOURCE: $(srcdir)/mysql.info $(GT) + perl -w $(GT) $(srcdir)/mysql.info "installing-source" "windows-source-build" > $@ -../INSTALL-WIN-SOURCE: mysql.info $(GT) - perl -w $(GT) mysql.info "windows-source-build" "post-installation" > $@ +../INSTALL-WIN-SOURCE: $(srcdir)/mysql.info $(GT) + perl -w $(GT) $(srcdir)/mysql.info "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" > $@ +INSTALL-BINARY: $(srcdir)/mysql.info $(GT) + perl -w $(GT) $(srcdir)/mysql.info "installing-binary" "installing-source" > $@ -../EXCEPTIONS-CLIENT: mysql.info $(GT) - perl -w $(GT) mysql.info "mysql-floss-license-exception" "function-index" > $@ +../EXCEPTIONS-CLIENT: $(srcdir)/mysql.info $(GT) + perl -w $(GT) $(srcdir)/mysql.info "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" > $@ +../support-files/MacOSX/ReadMe.txt: $(srcdir)/mysql.info $(GT) + perl -w $(GT) $(srcdir)/mysql.info "mac-os-x-installation" "netware-installation" > $@ # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/Makefile.am b/Makefile.am index 6b79b72ec4c..f7a9ffa7c2a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,6 +49,14 @@ BUILT_SOURCES = linked_client_sources linked_server_sources \ CLEANFILES = $(BUILT_SOURCES) bdb/build_unix/db.h DISTCLEANFILES = ac_available_languages_fragment +# Our current filtering of "sql_yacc.cc" in "sql/Makefile.am" creates +# a problem, if a VPATH build and "sql_yacc.cc" was part of the source +# distribution we end up with one "sql_yacc.cc" in the source tree, +# and one in the build tree. This breaks "distcleancheck", until this +# is sorted out we redefine the find that scans for files not removed + +distcleancheck_listfiles = find . -name sql_yacc.cc -o -type f -print + linked_include_sources: cd include; $(MAKE) link_sources echo timestamp > linked_include_sources @@ -92,19 +100,20 @@ bin-dist: all # Create initial database files for Windows installations. dist-hook: rm -rf `find $(distdir) -type d -name SCCS -print` - if echo "$(distdir)" | grep -q '^/' ; then \ - scripts/mysql_install_db --no-defaults --windows \ - --basedir=$(top_srcdir) \ - --datadir="$(distdir)/win/data"; \ - else \ - scripts/mysql_install_db --no-defaults --windows \ - --basedir=$(top_srcdir) \ - --datadir="$$(pwd)/$(distdir)/win/data"; \ - fi + rm -f `find $(distdir) -type l -print` + mkdir -p $(distdir)/win + scripts/mysql_install_db --no-defaults --windows \ + --basedir=$(top_builddir) \ + --datadir=$(distdir)/win/data \ + --srcdir=$(top_srcdir) tags: support-files/build-tags -.PHONY: init-db bin-dist + +.PHONY: init-db bin-dist \ + test test-force test-full test-force-full test-force-mem \ + test-pl test-force-pl test-full-pl test-force-full-pl test-force-pl-mem \ + test-ps test-ns # Target 'test' will run the regression test suite using the built server. # @@ -114,20 +123,33 @@ tags: # will then calculate the various port numbers it needs from this, # making sure each user use different ports. -test: +test-ps: cd mysql-test ; \ - ./mysql-test-run && \ - ./mysql-test-run --ps-protocol + @PERL@ ./mysql-test-run.pl $(force) --ps-protocol -test-force: - cd mysql-test; \ - ./mysql-test-run --force && \ - ./mysql-test-run --ps-protocol --force +test-ns: + cd mysql-test ; \ + @PERL@ ./mysql-test-run.pl $(force) -test-force-mem: - cd mysql-test; \ - ./mysql-test-run --force --mem && \ - ./mysql-test-run --ps-protocol --force --mem +test: test-ns test-ps + +# To ease script-writing, although in 5.0 it is identical to 'test' +test-full: test +test-force: + $(MAKE) force=--force test +test-force-full: + $(MAKE) force=--force test-full + +#used by autopush.pl to run memory based tests +test-force-mem: + $(MAKE) 'force=--force --mem' test + +# Keep these for a while +test-pl: test +test-full-pl: test-full +test-force-pl: test-force +test-force-pl-mem: test-force-mem +test-force-full-pl: test-force-full diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 09a6a3f1e2a..d37d99ad479 100755 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -66,7 +66,7 @@ TARGET_LINK_LIBRARIES(mysqldump mysqlclient mysys dbug yassl taocrypt zlib wsock ADD_EXECUTABLE(mysqlimport mysqlimport.c) TARGET_LINK_LIBRARIES(mysqlimport mysqlclient mysys dbug yassl taocrypt zlib wsock32) -ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c) +ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c ../mysys/my_getpagesize.c) TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient mysys dbug yassl taocrypt zlib wsock32) ADD_EXECUTABLE(mysqlshow mysqlshow.c) diff --git a/client/Makefile.am b/client/Makefile.am index df6e38223d4..db578b05da4 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -49,7 +49,8 @@ mysqlshow_SOURCES= mysqlshow.c mysqldump_SOURCES= mysqldump.c my_user.c \ $(top_srcdir)/mysys/mf_getdate.c mysqlimport_SOURCES= mysqlimport.c -mysql_upgrade_SOURCES= mysql_upgrade.c +mysql_upgrade_SOURCES= mysql_upgrade.c \ + $(top_srcdir)/mysys/my_getpagesize.c sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc strings_src=decimal.c diff --git a/client/client_priv.h b/client/client_priv.h index 9e011144836..7ebbade4ef6 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -51,5 +51,6 @@ enum options_client #endif OPT_TRIGGERS, OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE, - OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_SSL_VERIFY_SERVER_CERT + OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_SSL_VERIFY_SERVER_CERT, + OPT_DEBUG_INFO }; diff --git a/client/mysql.cc b/client/mysql.cc index d0965588b80..61d25eff3e2 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -819,10 +819,23 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), default_charset_used= 1; break; case OPT_DELIMITER: - if (argument == disabled_my_option) + if (argument == disabled_my_option) + { strmov(delimiter, DEFAULT_DELIMITER); - else - strmake(delimiter, argument, sizeof(delimiter) - 1); + } + else + { + /* Check that delimiter does not contain a backslash */ + if (!strstr(argument, "\\")) + { + strmake(delimiter, argument, sizeof(delimiter) - 1); + } + else + { + put_info("DELIMITER cannot contain a backslash character", INFO_ERROR); + return 0; + } + } delimiter_length= (uint)strlen(delimiter); delimiter_str= delimiter; break; @@ -2397,7 +2410,6 @@ print_table_data(MYSQL_RES *result) const char *buffer; uint data_length; uint field_max_length; - bool right_justified; uint visible_length; uint extra_padding; @@ -3041,6 +3053,14 @@ com_delimiter(String *buffer __attribute__((unused)), char *line) INFO_ERROR); return 0; } + else + { + if (strstr(tmp, "\\")) + { + put_info("DELIMITER cannot contain a backslash character", INFO_ERROR); + return 0; + } + } strmake(delimiter, tmp, sizeof(delimiter) - 1); delimiter_length= (int)strlen(delimiter); delimiter_str= delimiter; @@ -3446,7 +3466,6 @@ server_version_string(MYSQL *mysql) { char *bufp = buf; MYSQL_RES *result; - MYSQL_ROW cur; bufp = strnmov(buf, mysql_get_server_info(mysql), sizeof buf); diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 37cbeb81e1d..cce4b440be0 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -375,22 +375,24 @@ static int comp_names(struct fileinfo *a, struct fileinfo *b) } -static int -find_file(const char *name, const char *root, uint flags, char *result, size_t len, ...) +static int find_file(const char *name, const char *root, + uint flags, char *result, size_t len, ...) { - int ret; + int ret= 1; va_list va; - FILEINFO key= { (char*)name, NULL }; const char *subdir; char *cp; - + FILEINFO key; + + /* Init key with name of the file to look for */ + key.name= (char*)name; + DBUG_ASSERT(root != NULL); cp= strmake(result, root, len); if (cp[-1] != FN_LIBCHAR) *cp++= FN_LIBCHAR; - ret= 1; va_start(va, len); subdir= (!(flags & MY_SEARCH_SELF)) ? va_arg(va, char *) : ""; while (subdir) @@ -597,7 +599,7 @@ fix_priv_tables: if (find_file(MYSQL_FIX_PRIV_TABLES_NAME, basedir, MYF(0), path, sizeof(path), - "support_files", "share/mysql", "scripts", + "support_files", "share", "share/mysql", "scripts", NullS) && find_file(MYSQL_FIX_PRIV_TABLES_NAME, "/usr/local/mysql", MYF(0), path, sizeof(path), diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index c04c2ecabd6..102c665031d 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1088,7 +1088,7 @@ could be out of memory"); } if (len < 8 && net->read_pos[0] == 254) break; // end of data - DBUG_PRINT("info",( "len= %u, net->read_pos[5] = %d\n", + DBUG_PRINT("info",( "len: %lu, net->read_pos[5]: %d\n", len, net->read_pos[5])); if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 , len - 1, &error_msg, @@ -1310,6 +1310,25 @@ static int dump_local_log_entries(const char* logname) } else // reading from stdin; { + /* + Bug fix: #23735 + Author: Chuck Bell + Description: + Windows opens stdin in text mode by default. Certain characters + such as CTRL-Z are interpeted as events and the read() method + will stop. CTRL-Z is the EOF marker in Windows. to get past this + you have to open stdin in binary mode. Setmode() is used to set + stdin in binary mode. Errors on setting this mode result in + halting the function and printing an error message to stderr. + */ +#if defined (__WIN__) || (_WIN64) + if (_setmode(fileno(stdin), O_BINARY) == -1) + { + fprintf(stderr, "Could not set binary mode on stdin.\n"); + return 1; + } +#endif + if (init_io_cache(file, fileno(stdin), 0, READ_CACHE, (my_off_t) 0, 0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE))) return 1; diff --git a/client/mysqldump.c b/client/mysqldump.c index 757bec09b50..05765ef2a02 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -30,14 +30,14 @@ ** master/autocommit code by Brian Aker <brian@tangent.org> ** SSL by ** Andrei Errapart <andreie@no.spam.ee> -** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee> +** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee> ** XML by Gary Huntress <ghuntress@mediaone.net> 10/10/01, cleaned up ** and adapted to mysqldump 05/11/01 by Jani Tolonen ** Added --single-transaction option 06/06/2002 by Peter Zaitsev ** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov */ -#define DUMP_VERSION "10.10" +#define DUMP_VERSION "10.11" #include <my_global.h> #include <my_sys.h> @@ -99,7 +99,7 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1; static ulong opt_max_allowed_packet, opt_net_buffer_length; static MYSQL mysql_connection,*mysql=0; -static my_bool insert_pat_inited=0; +static my_bool insert_pat_inited= 0, info_flag; static DYNAMIC_STRING insert_pat; static char *opt_password=0,*current_user=0, *current_host=0,*path=0,*fields_terminated=0, @@ -107,6 +107,7 @@ static char *opt_password=0,*current_user=0, *where=0, *order_by=0, *opt_compatible_mode_str= 0, *err_ptr= 0; +static char **defaults_argv= 0; static char compatible_mode_normal_str[255]; static ulong opt_compatible_mode= 0; #define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1 @@ -116,7 +117,7 @@ static my_string opt_mysql_unix_port=0; static int first_error=0; static DYNAMIC_STRING extended_row; #include <sslopt-vars.h> -FILE *md_result_file; +FILE *md_result_file= 0; #ifdef HAVE_SMEM static char *shared_memory_base_name=0; #endif @@ -215,6 +216,8 @@ static struct my_option my_long_options[] = {"debug", '#', "Output debug log", (gptr*) &default_dbug_option, (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif + {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.", (gptr*) &info_flag, + (gptr*) &info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, "Set the default character set.", (gptr*) &default_charset, (gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -628,14 +631,6 @@ byte* get_table_key(const char *entry, uint *length, } -void init_table_rule_hash(HASH* h) -{ - if (hash_init(h, charset_info, 16, 0, 0, - (hash_get_key) get_table_key, - (hash_free_key) free_table_ent, 0)) - exit(EX_EOM); -} - static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) @@ -678,6 +673,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; case '#': DBUG_PUSH(argument ? argument : default_dbug_option); + info_flag= 1; break; #include <sslopt-case.h> case 'V': print_version(); exit(0); @@ -718,9 +714,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), fprintf(stderr, "Illegal use of option --ignore-table=<database>.<table>\n"); exit(1); } - if (!hash_inited(&ignore_table)) - init_table_rule_hash(&ignore_table); - if (my_hash_insert(&ignore_table, (byte*)my_strdup(argument, MYF(0)))) exit(EX_EOM); break; @@ -796,9 +789,21 @@ static int get_options(int *argc, char ***argv) md_result_file= stdout; load_defaults("my",load_default_groups,argc,argv); + defaults_argv= *argv; - if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) - exit(ho_error); + if (hash_init(&ignore_table, charset_info, 16, 0, 0, + (hash_get_key) get_table_key, + (hash_free_key) free_table_ent, 0)) + return(EX_EOM); + /* Don't copy cluster internal log tables */ + if (my_hash_insert(&ignore_table, + (byte*) my_strdup("mysql.apply_status", MYF(MY_WME))) || + my_hash_insert(&ignore_table, + (byte*) my_strdup("mysql.schema", MYF(MY_WME)))) + return(EX_EOM); + + if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option))) + return(ho_error); *mysql_params->p_max_allowed_packet= opt_max_allowed_packet; *mysql_params->p_net_buffer_length= opt_net_buffer_length; @@ -810,7 +815,7 @@ static int get_options(int *argc, char ***argv) { fprintf(stderr, "%s: You must use option --tab with --fields-...\n", my_progname); - return(1); + return(EX_USAGE); } /* Ensure consistency of the set of binlog & locking options */ @@ -820,7 +825,7 @@ static int get_options(int *argc, char ***argv) { fprintf(stderr, "%s: You can't use --single-transaction and " "--lock-all-tables at the same time.\n", my_progname); - return(1); + return(EX_USAGE); } if (opt_master_data) opt_lock_all_tables= !opt_single_transaction; @@ -829,14 +834,14 @@ static int get_options(int *argc, char ***argv) if (enclosed && opt_enclosed) { fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname); - return(1); + return(EX_USAGE); } if ((opt_databases || opt_alldbs) && path) { fprintf(stderr, "%s: --databases or --all-databases can't be used with --tab.\n", my_progname); - return(1); + return(EX_USAGE); } if (strcmp(default_charset, charset_info->csname) && !(charset_info= get_charset_by_csname(default_charset, @@ -845,7 +850,7 @@ static int get_options(int *argc, char ***argv) if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs)) { short_usage(); - return 1; + return EX_USAGE; } if (tty_password) opt_password=get_tty_password(NullS); @@ -920,6 +925,23 @@ static FILE* open_sql_file_for_table(const char* table) } +static void free_resources() +{ + if (md_result_file && md_result_file != stdout) + my_fclose(md_result_file, MYF(0)); + my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); + if (hash_inited(&ignore_table)) + hash_free(&ignore_table); + if (extended_insert) + dynstr_free(&extended_row); + if (insert_pat_inited) + dynstr_free(&insert_pat); + if (defaults_argv) + free_defaults(defaults_argv); + my_end(info_flag ? MY_CHECK_ERROR : 0); +} + + static void safe_exit(int error) { if (!first_error) @@ -928,18 +950,19 @@ static void safe_exit(int error) return; if (mysql) mysql_close(mysql); + free_resources(); exit(error); } -/* safe_exit */ /* -** dbConnect -- connects to the host and selects DB. + db_connect -- connects to the host and selects DB. */ -static int dbConnect(char *host, char *user,char *passwd) + +static int connect_to_db(char *host, char *user,char *passwd) { char buff[20+FN_REFLEN]; - DBUG_ENTER("dbConnect"); + DBUG_ENTER("connect_to_db"); verbose_msg("-- Connecting to %s...\n", host ? host : "localhost"); mysql_init(&mysql_connection); @@ -960,11 +983,11 @@ static int dbConnect(char *host, char *user,char *passwd) #endif mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd, - NULL,opt_mysql_port,opt_mysql_unix_port, - 0))) + NULL,opt_mysql_port,opt_mysql_unix_port, + 0))) { DB_error(&mysql_connection, "when trying to connect"); - return 1; + DBUG_RETURN(1); } /* Don't dump SET NAMES with a pre-4.1 server (bug#7997). @@ -981,7 +1004,7 @@ static int dbConnect(char *host, char *user,char *passwd) if (mysql_query_with_error_report(mysql, 0, buff)) { safe_exit(EX_MYSQLERR); - return 1; + DBUG_RETURN(1); } /* set time_zone to UTC to allow dumping date types between servers with @@ -993,11 +1016,11 @@ static int dbConnect(char *host, char *user,char *passwd) if (mysql_query_with_error_report(mysql, 0, buff)) { safe_exit(EX_MYSQLERR); - return 1; + DBUG_RETURN(1); } } - return 0; -} /* dbConnect */ + DBUG_RETURN(0); +} /* connect_to_db */ /* @@ -1396,7 +1419,7 @@ static uint dump_routines_for_db(char *db) routine body of other routines that are not the creator of! */ DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d", - routine_name, row[2], strlen(row[2]))); + routine_name, row[2], (int) strlen(row[2]))); if (strlen(row[2])) { char *query_str= NULL; @@ -1519,7 +1542,11 @@ static uint get_table_structure(char *table, char *db, char *table_type, { complete_insert= opt_complete_insert; if (!insert_pat_inited) - insert_pat_inited= init_dynamic_string(&insert_pat, "", 1024, 1024); + { + insert_pat_inited= 1; + if (init_dynamic_string(&insert_pat, "", 1024, 1024)) + safe_exit(EX_MYSQLERR); + } else dynstr_set(&insert_pat, ""); } @@ -1974,7 +2001,7 @@ continue_xml: write_footer(sql_file); my_fclose(sql_file, MYF(MY_WME)); } - DBUG_RETURN(num_fields); + DBUG_RETURN((uint) num_fields); } /* get_table_structure */ @@ -1988,7 +2015,7 @@ continue_xml: */ -static void dump_triggers_for_table (char *table, char *db) +static void dump_triggers_for_table(char *table, char *db) { char *result_table; char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3]; @@ -2176,7 +2203,7 @@ static void dump_table(char *table, char *db) The "table" could be a view. If so, we don't do anything here. */ if (strcmp (table_type, "VIEW") == 0) - return; + DBUG_VOID_RETURN; /* Check --no-data flag */ if (opt_no_data) @@ -2693,6 +2720,8 @@ static int dump_databases(char **db_names) { int result=0; char **db; + DBUG_ENTER("dump_databases"); + for (db= db_names ; *db ; db++) { if (dump_all_tables_in_db(*db)) @@ -2706,7 +2735,7 @@ static int dump_databases(char **db_names) result=1; } } - return result; + DBUG_RETURN(result); } /* dump_databases */ @@ -2721,7 +2750,7 @@ RETURN VALUES 0 Success. 1 Failure. */ -int init_dumping_views(char *qdatabase) +int init_dumping_views(char *qdatabase __attribute__((unused))) { return 0; } /* init_dumping_views */ @@ -2818,12 +2847,11 @@ static int init_dumping(char *database, int init_func(char*)) } /* init_dumping */ +/* Return 1 if we should copy the table */ + my_bool include_table(byte* hash_key, uint len) { - if (hash_search(&ignore_table, (byte*) hash_key, len)) - return FALSE; - - return TRUE; + return !hash_search(&ignore_table, (byte*) hash_key, len); } @@ -2832,16 +2860,16 @@ static int dump_all_tables_in_db(char *database) char *table; uint numrows; char table_buff[NAME_LEN*2+3]; - char hash_key[2*NAME_LEN+2]; /* "db.tablename" */ char *afterdot; int using_mysql_db= my_strcasecmp(&my_charset_latin1, database, "mysql"); + DBUG_ENTER("dump_all_tables_in_db"); afterdot= strmov(hash_key, database); *afterdot++= '.'; if (init_dumping(database, init_dumping_tables)) - return 1; + DBUG_RETURN(1); if (opt_xml) print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS); if (lock_tables) @@ -2895,7 +2923,7 @@ static int dump_all_tables_in_db(char *database) fprintf(md_result_file,"\n--\n-- Flush Grant Tables \n--\n"); fprintf(md_result_file,"\n/*! FLUSH PRIVILEGES */;\n"); } - return 0; + DBUG_RETURN(0); } /* dump_all_tables_in_db */ @@ -3257,7 +3285,6 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row, /* - SYNOPSIS Check if we the table is one of the table types that should be ignored: @@ -3297,8 +3324,8 @@ char check_if_ignore_table(const char *table_name, char *table_type) { if (mysql_errno(mysql) != ER_PARSE_ERROR) { /* If old MySQL version */ - verbose_msg("-- Warning: Couldn't get status information for " \ - "table %s (%s)\n", table_name,mysql_error(mysql)); + verbose_msg("-- Warning: Couldn't get status information for " + "table %s (%s)\n", table_name, mysql_error(mysql)); DBUG_RETURN(result); /* assume table is ok */ } } @@ -3653,19 +3680,24 @@ static my_bool get_view_structure(char *table, char* db) int main(int argc, char **argv) { + int exit_code; MY_INIT("mysqldump"); compatible_mode_normal_str[0]= 0; default_charset= (char *)mysql_universal_client_charset; bzero((char*) &ignore_table, sizeof(ignore_table)); - if (get_options(&argc, &argv)) + exit_code= get_options(&argc, &argv); + if (exit_code) { - my_end(0); - exit(EX_USAGE); + free_resources(0); + exit(exit_code); } - if (dbConnect(current_host, current_user, opt_password)) + if (connect_to_db(current_host, current_user, opt_password)) + { + free_resources(0); exit(EX_MYSQLERR); + } if (!path) write_header(md_result_file, *argv); @@ -3712,15 +3744,6 @@ err: dbDisconnect(current_host); if (!path) write_footer(md_result_file); - if (md_result_file != stdout) - my_fclose(md_result_file, MYF(0)); - my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); - if (hash_inited(&ignore_table)) - hash_free(&ignore_table); - if (extended_insert) - dynstr_free(&extended_row); - if (insert_pat_inited) - dynstr_free(&insert_pat); - my_end(0); + free_resources(); return(first_error); } /* main */ diff --git a/client/mysqltest.c b/client/mysqltest.c index 6871701e691..a58f2ae376e 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -29,9 +29,10 @@ Matt Wagner <matt@mysql.com> Monty Jani + Holyfoot */ -#define MTEST_VERSION "3.0" +#define MTEST_VERSION "3.1" #include <my_global.h> #include <mysql_embed.h> @@ -102,6 +103,7 @@ static my_bool disable_query_log= 0, disable_result_log= 0; static my_bool disable_warnings= 0, disable_ps_warnings= 0; static my_bool disable_info= 1; static my_bool abort_on_error= 1; +static my_bool server_initialized= 0; static char **default_argv; static const char *load_default_groups[]= { "mysqltest", "client", 0 }; @@ -220,6 +222,14 @@ struct st_connection MYSQL* util_mysql; char *name; MYSQL_STMT* stmt; + +#ifdef EMBEDDED_LIBRARY + const char *cur_query; + int cur_query_len; + pthread_mutex_t mutex; + pthread_cond_t cond; + int query_done; +#endif /*EMBEDDED_LIBRARY*/ }; struct st_connection connections[128]; struct st_connection* cur_con, *next_con, *connections_end; @@ -264,6 +274,7 @@ enum enum_commands { Q_DISABLE_PARSING, Q_ENABLE_PARSING, Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST, Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, + Q_CHMOD_FILE, Q_UNKNOWN, /* Unknown command. */ Q_COMMENT, /* Comments, ignored. */ @@ -344,8 +355,10 @@ const char *command_names[]= "copy_file", "perl", "die", + /* Don't execute any more commands, compare result */ "exit", + "chmod", 0 }; @@ -458,7 +471,6 @@ void mysql_disable_rpl_parse(MYSQL* mysql __attribute__((unused))) {} int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; } my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; } #endif - void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, int len); void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val); @@ -469,7 +481,56 @@ void handle_error(struct st_command*, const char *err_sqlstate, DYNAMIC_STRING *ds); void handle_no_error(struct st_command*); +#ifdef EMBEDDED_LIBRARY +/* + send_one_query executes query in separate thread what is + necessary in embedded library to run 'send' in proper way. + This implementation doesn't handle errors returned + by mysql_send_query. It's technically possible, though + i don't see where it is needed. +*/ +pthread_handler_t send_one_query(void *arg) +{ + struct st_connection *cn= (struct st_connection*)arg; + + mysql_thread_init(); + VOID(mysql_send_query(&cn->mysql, cn->cur_query, cn->cur_query_len)); + + mysql_thread_end(); + pthread_mutex_lock(&cn->mutex); + cn->query_done= 1; + VOID(pthread_cond_signal(&cn->cond)); + pthread_mutex_unlock(&cn->mutex); + pthread_exit(0); + return 0; +} + +static int do_send_query(struct st_connection *cn, const char *q, int q_len, + int flags) +{ + pthread_t tid; + + if (flags & QUERY_REAP_FLAG) + return mysql_send_query(&cn->mysql, q, q_len); + + if (pthread_mutex_init(&cn->mutex, NULL) || + pthread_cond_init(&cn->cond, NULL)) + die("Error in the thread library"); + cn->cur_query= q; + cn->cur_query_len= q_len; + cn->query_done= 0; + if (pthread_create(&tid, NULL, send_one_query, (void*)cn)) + die("Cannot start new thread for query"); + + return 0; +} + +#else /*EMBEDDED_LIBRARY*/ + +#define do_send_query(cn,q,q_len,flags) mysql_send_query(&cn->mysql, q, q_len) + +#endif /*EMBEDDED_LIBRARY*/ void do_eval(DYNAMIC_STRING *query_eval, const char *query, const char *query_end, my_bool pass_through_escape_chars) @@ -710,13 +771,18 @@ void free_used_memory() free_all_replace(); my_free(pass,MYF(MY_ALLOW_ZERO_PTR)); free_defaults(default_argv); - mysql_server_end(); free_re(); #ifdef __WIN__ free_tmp_sh_file(); free_win_path_patterns(); #endif - DBUG_VOID_RETURN; + + /* Only call mysql_server_end if mysql_server_init has been called */ + if (server_initialized) + mysql_server_end(); + + /* Don't use DBUG after mysql_server_end() */ + return; } @@ -891,8 +957,8 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) die(NullS); if (!eval_result && (uint) stat_info.st_size != ds->length) { - DBUG_PRINT("info",("Size differs: result size: %u file size: %llu", - ds->length, stat_info.st_size)); + DBUG_PRINT("info",("Size differs: result size: %u file size: %lu", + ds->length, (ulong) stat_info.st_size)); DBUG_PRINT("info",("result: '%s'", ds->str)); DBUG_RETURN(RESULT_LENGTH_MISMATCH); } @@ -1180,7 +1246,9 @@ void var_set(const char *var_name, const char *var_name_end, v->int_dirty= 0; v->str_val_len= strlen(v->str_val); } - strxmov(buf, v->name, "=", v->str_val, NullS); + my_snprintf(buf, sizeof(buf), "%.*s=%.*s", + v->name_len, v->name, + v->str_val_len, v->str_val); if (!(v->env_s= my_strdup(buf, MYF(MY_WME)))) die("Out of memory"); putenv(v->env_s); @@ -1754,6 +1822,46 @@ void do_copy_file(struct st_command *command) /* SYNOPSIS + do_chmod_file + command command handle + + DESCRIPTION + chmod <octal> <file> + Change file permission of <file> + +*/ + +void do_chmod_file(struct st_command *command) +{ + ulong mode= 0; + static DYNAMIC_STRING ds_mode; + static DYNAMIC_STRING ds_file; + const struct command_arg chmod_file_args[] = { + "mode", ARG_STRING, TRUE, &ds_mode, "Mode of file", + "file", ARG_STRING, TRUE, &ds_file, "Filename of file to modify" + }; + DBUG_ENTER("do_chmod_file"); + + check_command_args(command, command->first_argument, + chmod_file_args, + sizeof(chmod_file_args)/sizeof(struct command_arg), + ' '); + + /* Parse what mode to set */ + if (ds_mode.length != 4 || + str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS) + die("You must write a 4 digit octal number for mode"); + + DBUG_PRINT("info", ("chmod %o %s", (uint)mode, ds_file.str)); + handle_command_error(command, chmod(ds_file.str, mode)); + dynstr_free(&ds_mode); + dynstr_free(&ds_file); + DBUG_VOID_RETURN; +} + + +/* + SYNOPSIS do_file_exists command called command @@ -2861,12 +2969,19 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, Connect failed Only allow retry if this was an error indicating the server - could not be contacted + could not be contacted. Error code differs depending + on protocol/connection type */ - if (mysql_errno(mysql) == CR_CONNECTION_ERROR && + if ((mysql_errno(mysql) == CR_CONN_HOST_ERROR || + mysql_errno(mysql) == CR_CONNECTION_ERROR) && failed_attempts < opt_max_connect_retries) + { + verbose_msg("Connect attempt %d/%d failed: %d: %s", failed_attempts, + opt_max_connect_retries, mysql_errno(mysql), + mysql_error(mysql)); my_sleep(connection_retry_sleep); + } else { if (failed_attempts > 0) @@ -3075,14 +3190,15 @@ void do_connect(struct st_command *command) else if (!strncmp(con_options, "COMPRESS", 8)) con_compress= 1; else - die("Illegal option to connect: %.*s", end - con_options, con_options); + die("Illegal option to connect: %.*s", + (int) (end - con_options), con_options); /* Process next option */ con_options= end; } if (next_con == connections_end) die("Connection limit exhausted, you can have max %d connections", - (sizeof(connections)/sizeof(struct st_connection))); + (int) (sizeof(connections)/sizeof(struct st_connection))); if (find_connection_by_name(ds_connection_name.str)) die("Connection %s already exists", ds_connection_name.str); @@ -3403,10 +3519,10 @@ int read_line(char *buf, int size) DBUG_RETURN(0); } else if ((c == '{' && - (!my_strnncoll_simple(charset_info, "while", 5, - buf, min(5, p - buf), 0) || - !my_strnncoll_simple(charset_info, "if", 2, - buf, min(2, p - buf), 0)))) + (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5, + (uchar*) buf, min(5, p - buf), 0) || + !my_strnncoll_simple(charset_info, (const uchar*) "if", 2, + (uchar*) buf, min(2, p - buf), 0)))) { /* Only if and while commands can be terminated by { */ *p++= c; @@ -4506,7 +4622,6 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) } - /* Run query using MySQL C API @@ -4523,11 +4638,12 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) error - function will not return */ -void run_query_normal(MYSQL *mysql, struct st_command *command, +void run_query_normal(struct st_connection *cn, struct st_command *command, int flags, char *query, int query_len, DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings) { MYSQL_RES *res= 0; + MYSQL *mysql= &cn->mysql; int err= 0, counter= 0; DBUG_ENTER("run_query_normal"); DBUG_PRINT("enter",("flags: %d", flags)); @@ -4538,14 +4654,26 @@ void run_query_normal(MYSQL *mysql, struct st_command *command, /* Send the query */ - if (mysql_send_query(mysql, query, query_len)) + if (do_send_query(cn, query, query_len, flags)) { handle_error(command, mysql_errno(mysql), mysql_error(mysql), mysql_sqlstate(mysql), ds); goto end; } } - +#ifdef EMBEDDED_LIBRARY + /* + Here we handle 'reap' command, so we need to check if the + query's thread was finished and probably wait + */ + else if (flags & QUERY_REAP_FLAG) + { + pthread_mutex_lock(&cn->mutex); + while (!cn->query_done) + pthread_cond_wait(&cn->cond, &cn->mutex); + pthread_mutex_unlock(&cn->mutex); + } +#endif /*EMBEDDED_LIBRARY*/ if (!(flags & QUERY_REAP_FLAG)) DBUG_VOID_RETURN; @@ -4564,10 +4692,9 @@ void run_query_normal(MYSQL *mysql, struct st_command *command, } /* - Store the result. If res is NULL, use mysql_field_count to - determine if that was expected + Store the result of the query if it will return any fields */ - if (!(res= mysql_store_result(mysql)) && mysql_field_count(mysql)) + if (mysql_field_count(mysql) && ((res= mysql_store_result(mysql)) == 0)) { handle_error(command, mysql_errno(mysql), mysql_error(mysql), mysql_sqlstate(mysql), ds); @@ -4619,7 +4746,10 @@ void run_query_normal(MYSQL *mysql, struct st_command *command, } if (res) + { mysql_free_result(res); + res= 0; + } counter++; } while (!(err= mysql_next_result(mysql))); if (err > 0) @@ -4686,7 +4816,7 @@ void handle_error(struct st_command *command, err_errno, err_error); /* Abort the run of this test, pass the failed query as reason */ - abort_not_supported_test("Query '%s' failed, required functionality" \ + abort_not_supported_test("Query '%s' failed, required functionality " \ "not supported", command->query); } @@ -5036,8 +5166,9 @@ int util_query(MYSQL* org_mysql, const char* query){ */ -void run_query(MYSQL *mysql, struct st_command *command, int flags) +void run_query(struct st_connection *cn, struct st_command *command, int flags) { + MYSQL *mysql= &cn->mysql; DYNAMIC_STRING *ds; DYNAMIC_STRING ds_result; DYNAMIC_STRING ds_warnings; @@ -5194,7 +5325,7 @@ void run_query(MYSQL *mysql, struct st_command *command, int flags) match_re(&ps_re, query)) run_query_stmt(mysql, command, query, query_len, ds, &ds_warnings); else - run_query_normal(mysql, command, flags, query, query_len, + run_query_normal(cn, command, flags, query, query_len, ds, &ds_warnings); if (sp_created) @@ -5505,6 +5636,7 @@ int main(int argc, char **argv) embedded_server_args, (char**) embedded_server_groups)) die("Can't initialize MySQL server"); + server_initialized= 1; if (cur_file == file_stack && cur_file->file == 0) { cur_file->file= stdin; @@ -5624,6 +5756,7 @@ int main(int argc, char **argv) case Q_FILE_EXIST: do_file_exist(command); break; case Q_WRITE_FILE: do_write_file(command); break; case Q_COPY_FILE: do_copy_file(command); break; + case Q_CHMOD_FILE: do_chmod_file(command); break; case Q_PERL: do_perl(command); break; case Q_DELIMITER: do_delimiter(command); @@ -5659,7 +5792,7 @@ int main(int argc, char **argv) strmake(command->require_file, save_file, sizeof(save_file)); save_file[0]= 0; } - run_query(&cur_con->mysql, command, QUERY_REAP_FLAG|QUERY_SEND_FLAG); + run_query(cur_con, command, QUERY_REAP_FLAG|QUERY_SEND_FLAG); display_result_vertically= old_display_result_vertically; command->last_argument= command->end; command_executed++; @@ -5690,7 +5823,7 @@ int main(int argc, char **argv) strmake(command->require_file, save_file, sizeof(save_file)); save_file[0]= 0; } - run_query(&cur_con->mysql, command, flags); + run_query(cur_con, command, flags); command_executed++; command->last_argument= command->end; break; @@ -5716,7 +5849,7 @@ int main(int argc, char **argv) the query and read the result some time later when reap instruction is given on this connection. */ - run_query(&cur_con->mysql, command, QUERY_SEND_FLAG); + run_query(cur_con, command, QUERY_SEND_FLAG); command_executed++; command->last_argument= command->end; break; diff --git a/cmd-line-utils/readline/bind.c b/cmd-line-utils/readline/bind.c index 17f61d1df08..568c3e8776a 100644 --- a/cmd-line-utils/readline/bind.c +++ b/cmd-line-utils/readline/bind.c @@ -337,6 +337,7 @@ rl_generic_bind (type, keyseq, data, map) KEYMAP_ENTRY k; k.function = 0; + k.type= 0; /* If no keys to bind to, exit right away. */ if (!keyseq || !*keyseq) @@ -434,7 +435,7 @@ rl_translate_keyseq (seq, array, len) { register int i, c, l, temp; - for (i = l = 0; c = seq[i]; i++) + for (i = l = 0; (c = seq[i]); i++) { if (c == '\\') { @@ -735,7 +736,8 @@ _rl_read_file (filename, sizep) file_size = (size_t)finfo.st_size; /* check for overflow on very large files */ - if (file_size != finfo.st_size || file_size + 1 < file_size) + if ((long long) file_size != (long long) finfo.st_size || + file_size + 1 < file_size) { if (file >= 0) close (file); @@ -765,8 +767,8 @@ _rl_read_file (filename, sizep) /* Re-read the current keybindings file. */ int -rl_re_read_init_file (count, ignore) - int count, ignore; +rl_re_read_init_file (int count __attribute__((unused)), + int ignore __attribute__((unused))) { int r; r = rl_read_init_file ((const char *)NULL); @@ -987,8 +989,7 @@ parser_if (args) /* Invert the current parser state if there is anything on the stack. */ static int -parser_else (args) - char *args; +parser_else (char *args __attribute__((unused))) { register int i; @@ -1018,8 +1019,7 @@ parser_else (args) /* Terminate a conditional, popping the value of _rl_parsing_conditionalized_out from the stack. */ static int -parser_endif (args) - char *args; +parser_endif (char *args __attribute__((unused))) { if (if_stack_depth) _rl_parsing_conditionalized_out = if_stack[--if_stack_depth]; @@ -1142,7 +1142,7 @@ rl_parse_and_bind (string) { int passc = 0; - for (i = 1; c = string[i]; i++) + for (i = 1; (c = string[i]); i++) { if (passc) { @@ -1218,7 +1218,7 @@ rl_parse_and_bind (string) { int delimiter = string[i++], passc; - for (passc = 0; c = string[i]; i++) + for (passc = 0; (c = string[i]); i++) { if (passc) { @@ -1377,7 +1377,7 @@ static struct { #if defined (VISIBLE_STATS) { "visible-stats", &rl_visible_stats, 0 }, #endif /* VISIBLE_STATS */ - { (char *)NULL, (int *)NULL } + { (char *)NULL, (int *)NULL, 0 } }; static int @@ -1446,7 +1446,7 @@ static struct { { "editing-mode", V_STRING, sv_editmode }, { "isearch-terminators", V_STRING, sv_isrchterm }, { "keymap", V_STRING, sv_keymap }, - { (char *)NULL, 0 } + { (char *)NULL, 0, 0 } }; static int @@ -1466,7 +1466,7 @@ find_string_var (name) values result in 0 (false). */ static int bool_to_int (value) - char *value; +const char *value; { return (value == 0 || *value == '\0' || (_rl_stricmp (value, "on") == 0) || @@ -1725,13 +1725,13 @@ char * rl_get_keymap_name_from_edit_mode () { if (rl_editing_mode == emacs_mode) - return "emacs"; + return (char*) "emacs"; #if defined (VI_MODE) else if (rl_editing_mode == vi_mode) - return "vi"; + return (char*) "vi"; #endif /* VI_MODE */ else - return "none"; + return (char*) "none"; } /* **************************************************************** */ @@ -1966,7 +1966,7 @@ rl_function_dumper (print_readably) fprintf (rl_outstream, "\n"); - for (i = 0; name = names[i]; i++) + for (i = 0; (name = names[i]); i++) { rl_command_func_t *function; char **invokers; @@ -2025,8 +2025,8 @@ rl_function_dumper (print_readably) rl_outstream. If an explicit argument is given, then print the output in such a way that it can be read back in. */ int -rl_dump_functions (count, key) - int count, key; +rl_dump_functions (int count __attribute__((unused)), + int key __attribute__((unused))) { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); @@ -2105,8 +2105,7 @@ rl_macro_dumper (print_readably) } int -rl_dump_macros (count, key) - int count, key; +rl_dump_macros(int count __attribute__((unused)), int key __attribute__((unused))) { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); @@ -2195,8 +2194,7 @@ rl_variable_dumper (print_readably) rl_outstream. If an explicit argument is given, then print the output in such a way that it can be read back in. */ int -rl_dump_variables (count, key) - int count, key; +rl_dump_variables(int count __attribute__((unused)), int key __attribute__((unused))) { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); diff --git a/cmd-line-utils/readline/chardefs.h b/cmd-line-utils/readline/chardefs.h index cb04c982343..04a3b7a8e9c 100644 --- a/cmd-line-utils/readline/chardefs.h +++ b/cmd-line-utils/readline/chardefs.h @@ -59,7 +59,11 @@ #define largest_char 255 /* Largest character value. */ #define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0)) +#if largest_char >= 255 +#define META_CHAR(c) ((c) > meta_character_threshold) +#else #define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char) +#endif #define CTRL(c) ((c) & control_character_mask) #define META(c) ((c) | meta_character_bit) diff --git a/cmd-line-utils/readline/complete.c b/cmd-line-utils/readline/complete.c index df0a698b81f..f4c361789b7 100644 --- a/cmd-line-utils/readline/complete.c +++ b/cmd-line-utils/readline/complete.c @@ -360,15 +360,15 @@ rl_complete (ignore, invoking_key) /* List the possible completions. See description of rl_complete (). */ int -rl_possible_completions (ignore, invoking_key) - int ignore, invoking_key; +rl_possible_completions (int ignore __attribute__((unused)), + int invoking_key __attribute__((unused))) { return (rl_complete_internal ('?')); } int -rl_insert_completions (ignore, invoking_key) - int ignore, invoking_key; +rl_insert_completions (int ignore __attribute__((unused)), + int invoking_key __attribute__((unused))) { return (rl_complete_internal ('*')); } @@ -760,10 +760,7 @@ print_filename (to_print, full_pathname) } static char * -rl_quote_filename (s, rtype, qcp) - char *s; - int rtype; - char *qcp; +rl_quote_filename (char *s, int rtype __attribute__((unused)), char *qcp) { char *r; @@ -871,7 +868,7 @@ _rl_find_completion_word (fp, dp) completion, so use the word break characters to find the substring on which to complete. */ #if defined (HANDLE_MULTIBYTE) - while (rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY)) + while ((rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY))) #else while (--rl_point) #endif @@ -1805,7 +1802,7 @@ rl_completion_matches (text, entry_function) match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); match_list[1] = (char *)NULL; - while (string = (*entry_function) (text, matches)) + while ((string = (*entry_function) (text, matches))) { if (matches + 1 == match_list_size) match_list = (char **)xrealloc @@ -1855,7 +1852,7 @@ rl_username_completion_function (text, state) setpwent (); } - while (entry = getpwent ()) + while ((entry = getpwent ())) { /* Null usernames should result in all users as possible completions. */ if (namelen == 0 || (STREQN (username, entry->pw_name, namelen))) @@ -2091,8 +2088,7 @@ rl_filename_completion_function (text, state) hit the end of the match list, we restore the original unmatched text, ring the bell, and reset the counter to zero. */ int -rl_menu_complete (count, ignore) - int count, ignore; +rl_menu_complete (int count, int ignore __attribute__((unused))) { rl_compentry_func_t *our_func; int matching_filenames, found_quote; diff --git a/cmd-line-utils/readline/display.c b/cmd-line-utils/readline/display.c index 06eaa5e4be2..46b57325e33 100644 --- a/cmd-line-utils/readline/display.c +++ b/cmd-line-utils/readline/display.c @@ -218,7 +218,7 @@ expand_prompt (pmt, lp, lip, niflp, vlp) if (niflp) *niflp = 0; if (vlp) - *vlp = lp ? *lp : strlen (r); + *vlp = lp ? *lp : (int) strlen (r); return r; } @@ -435,7 +435,7 @@ rl_redisplay () return; if (!rl_display_prompt) - rl_display_prompt = ""; + rl_display_prompt = (char*) ""; if (invisible_line == 0) { @@ -757,7 +757,7 @@ rl_redisplay () c_pos = out; lb_linenum = newlines; } - for (i = in; i < in+wc_bytes; i++) + for (i = in; i < (int) (in+wc_bytes); i++) line[out++] = rl_line_buffer[i]; for (i = 0; i < wc_width; i++) CHECK_LPOS(); @@ -835,7 +835,7 @@ rl_redisplay () #define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l])) #define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l]) #define VIS_CHARS(line) (visible_line + vis_lbreaks[line]) -#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line) +#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? (char*) "" : VIS_CHARS(line) #define INV_LINE(line) (invisible_line + inv_lbreaks[line]) /* For each line in the buffer, do the updating display. */ @@ -876,7 +876,7 @@ rl_redisplay () _rl_move_vert (linenum); _rl_move_cursor_relative (0, tt); _rl_clear_to_eol - ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth); + ((linenum == _rl_vis_botlin) ? (int) strlen (tt) : _rl_screenwidth); } } _rl_vis_botlin = inv_botlin; @@ -1086,7 +1086,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) int col_lendiff, col_temp; #if defined (HANDLE_MULTIBYTE) mbstate_t ps_new, ps_old; - int new_offset, old_offset, tmp; + int new_offset, old_offset; #endif /* If we're at the right edge of a terminal that supports xn, we're @@ -1837,7 +1837,7 @@ rl_reset_line_state () { rl_on_new_line (); - rl_display_prompt = rl_prompt ? rl_prompt : ""; + rl_display_prompt = rl_prompt ? rl_prompt : (char*) ""; forced_display = 1; return 0; } @@ -2212,7 +2212,7 @@ _rl_col_width (str, start, end) int start, end; { wchar_t wc; - mbstate_t ps = {0}; + mbstate_t ps; int tmp, point, width, max; if (end <= start) @@ -2221,6 +2221,7 @@ _rl_col_width (str, start, end) point = 0; max = end; + memset (&ps, 0, sizeof(ps)); while (point < start) { tmp = mbrlen (str + point, max, &ps); diff --git a/cmd-line-utils/readline/histexpand.c b/cmd-line-utils/readline/histexpand.c index 47f97e9a6f7..a09be00a859 100644 --- a/cmd-line-utils/readline/histexpand.c +++ b/cmd-line-utils/readline/histexpand.c @@ -87,14 +87,14 @@ char history_comment_char = '\0'; /* The list of characters which inhibit the expansion of text if found immediately following history_expansion_char. */ -char *history_no_expand_chars = " \t\n\r="; +char *history_no_expand_chars = (char*) " \t\n\r="; /* If set to a non-zero value, single quotes inhibit history expansion. The default is 0. */ int history_quotes_inhibit_expansion = 0; /* Used to split words by history_tokenize_internal. */ -char *history_word_delimiters = HISTORY_WORD_DELIMITERS; +char *history_word_delimiters = (char*) HISTORY_WORD_DELIMITERS; /* If set, this points to a function that is called to verify that a particular history expansion should be performed. */ @@ -203,7 +203,7 @@ get_history_event (string, caller_index, delimiting_quote) } /* Only a closing `?' or a newline delimit a substring search string. */ - for (local_index = i; c = string[i]; i++) + for (local_index = i; (c = string[i]); i++) #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { diff --git a/cmd-line-utils/readline/histfile.c b/cmd-line-utils/readline/histfile.c index 7d340b346d4..a7d6a68098e 100644 --- a/cmd-line-utils/readline/histfile.c +++ b/cmd-line-utils/readline/histfile.c @@ -184,7 +184,8 @@ read_history_range (filename, from, to) file_size = (size_t)finfo.st_size; /* check for overflow on very large files */ - if (file_size != finfo.st_size || file_size + 1 < file_size) + if ((long long) file_size != (long long) finfo.st_size || + file_size + 1 < file_size) { errno = overflow_errno; goto error_and_exit; diff --git a/cmd-line-utils/readline/input.c b/cmd-line-utils/readline/input.c index 1981061eac6..b2f8016050d 100644 --- a/cmd-line-utils/readline/input.c +++ b/cmd-line-utils/readline/input.c @@ -405,7 +405,7 @@ rl_read_key () else { /* If input is coming from a macro, then use that. */ - if (c = _rl_next_macro_key ()) + if ((c= _rl_next_macro_key ())) return (c); /* If the user has an event function, then call it periodically. */ diff --git a/cmd-line-utils/readline/isearch.c b/cmd-line-utils/readline/isearch.c index f7b0f1404e9..9071695dda8 100644 --- a/cmd-line-utils/readline/isearch.c +++ b/cmd-line-utils/readline/isearch.c @@ -68,7 +68,7 @@ static char *prev_line_found; static char *last_isearch_string; static int last_isearch_string_len; -static char *default_isearch_terminators = "\033\012"; +static char *default_isearch_terminators = (char*) "\033\012"; /* Search backwards through the history looking for a string which is typed interactively. Start with the current line. */ @@ -94,9 +94,8 @@ rl_forward_search_history (sign, key) WHERE is the history list number of the current line. If it is -1, then this line is the starting one. */ static void -rl_display_search (search_string, reverse_p, where) - char *search_string; - int reverse_p, where; +rl_display_search (char *search_string, int reverse_p, + int where __attribute__((unused))) { char *message; int msglen, searchlen; @@ -143,8 +142,7 @@ rl_display_search (search_string, reverse_p, where) DIRECTION is which direction to search; >= 0 means forward, < 0 means backwards. */ static int -rl_search_history (direction, invoking_key) - int direction, invoking_key; +rl_search_history (int direction, int invoking_key __attribute__((unused))) { /* The string that the user types in to search for. */ char *search_string; diff --git a/cmd-line-utils/readline/kill.c b/cmd-line-utils/readline/kill.c index 061bdafcf9a..4d31a8ff170 100644 --- a/cmd-line-utils/readline/kill.c +++ b/cmd-line-utils/readline/kill.c @@ -76,8 +76,7 @@ static int rl_yank_nth_arg_internal PARAMS((int, int, int)); /* How to say that you only want to save a certain amount of kill material. */ int -rl_set_retained_kills (num) - int num; +rl_set_retained_kills (int num __attribute__((unused))) { return 0; } @@ -293,8 +292,8 @@ rl_backward_kill_line (direction, ignore) /* Kill the whole line, no matter where point is. */ int -rl_kill_full_line (count, ignore) - int count, ignore; +rl_kill_full_line (int count __attribute__((unused)), + int ignore __attribute__((unused))) { rl_begin_undo_group (); rl_point = 0; @@ -311,8 +310,7 @@ rl_kill_full_line (count, ignore) /* This does what C-w does in Unix. We can't prevent people from using behaviour that they expect. */ int -rl_unix_word_rubout (count, key) - int count, key; +rl_unix_word_rubout (int count, int key __attribute__((unused))) { int orig_point; @@ -344,8 +342,7 @@ rl_unix_word_rubout (count, key) /* This deletes one filename component in a Unix pathname. That is, it deletes backward to directory separator (`/') or whitespace. */ int -rl_unix_filename_rubout (count, key) - int count, key; +rl_unix_filename_rubout (int count, int key __attribute__((unused))) { int orig_point, c; @@ -388,8 +385,8 @@ rl_unix_filename_rubout (count, key) into the line at all, and if you aren't, then you know what you are doing. */ int -rl_unix_line_discard (count, key) - int count, key; +rl_unix_line_discard (int count __attribute__((unused)), + int key __attribute__((unused))) { if (rl_point == 0) rl_ding (); @@ -425,16 +422,16 @@ region_kill_internal (delete) /* Copy the text in the region to the kill ring. */ int -rl_copy_region_to_kill (count, ignore) - int count, ignore; +rl_copy_region_to_kill (int count __attribute__((unused)), + int key __attribute__((unused))) { return (region_kill_internal (0)); } /* Kill the text between the point and mark. */ int -rl_kill_region (count, ignore) - int count, ignore; +rl_kill_region (int count __attribute__((unused)), + int ignore __attribute__((unused))) { int r, npoint; @@ -498,8 +495,7 @@ rl_copy_backward_word (count, key) /* Yank back the last killed text. This ignores arguments. */ int -rl_yank (count, ignore) - int count, ignore; +rl_yank (int count __attribute__((unused)), int ignore __attribute__((unused))) { if (rl_kill_ring == 0) { @@ -517,8 +513,7 @@ rl_yank (count, ignore) delete that text from the line, rotate the index down, and yank back some other text. */ int -rl_yank_pop (count, key) - int count, key; +rl_yank_pop (int count __attribute__((unused)), int key __attribute__((unused))) { int l, n; diff --git a/cmd-line-utils/readline/macro.c b/cmd-line-utils/readline/macro.c index f7b77a831b8..8727285e181 100644 --- a/cmd-line-utils/readline/macro.c +++ b/cmd-line-utils/readline/macro.c @@ -189,8 +189,8 @@ _rl_kill_kbd_macro () definition to the end of the existing macro, and start by re-executing the existing macro. */ int -rl_start_kbd_macro (ignore1, ignore2) - int ignore1, ignore2; +rl_start_kbd_macro (int ignore1 __attribute__((unused)), + int ignore2 __attribute__((unused))) { if (RL_ISSTATE (RL_STATE_MACRODEF)) { @@ -214,8 +214,7 @@ rl_start_kbd_macro (ignore1, ignore2) A numeric argument says to execute the macro right now, that many times, counting the definition as the first time. */ int -rl_end_kbd_macro (count, ignore) - int count, ignore; +rl_end_kbd_macro (int count, int ignore __attribute__((unused))) { if (RL_ISSTATE (RL_STATE_MACRODEF) == 0) { @@ -234,8 +233,7 @@ rl_end_kbd_macro (count, ignore) /* Execute the most recently defined keyboard macro. COUNT says how many times to execute it. */ int -rl_call_last_kbd_macro (count, ignore) - int count, ignore; +rl_call_last_kbd_macro (int count, int ignore __attribute__((unused))) { if (current_macro == 0) _rl_abort_internal (); diff --git a/cmd-line-utils/readline/misc.c b/cmd-line-utils/readline/misc.c index 810b940edab..c8739d0d750 100644 --- a/cmd-line-utils/readline/misc.c +++ b/cmd-line-utils/readline/misc.c @@ -154,8 +154,7 @@ rl_digit_loop () /* Add the current digit to the argument in progress. */ int -rl_digit_argument (ignore, key) - int ignore, key; +rl_digit_argument (int ignore __attribute__((unused)), int key) { rl_execute_next (key); return (rl_digit_loop ()); @@ -184,8 +183,8 @@ _rl_init_argument () Read a key. If the key has nothing to do with arguments, then dispatch on it. If the key is the abort character then abort. */ int -rl_universal_argument (count, key) - int count, key; +rl_universal_argument (int count __attribute__((unused)), + int key __attribute__((unused))) { rl_numeric_arg *= 4; return (rl_digit_loop ()); @@ -314,9 +313,7 @@ _rl_history_set_point () } void -rl_replace_from_history (entry, flags) - HIST_ENTRY *entry; - int flags; /* currently unused */ +rl_replace_from_history (HIST_ENTRY *entry, int flags __attribute__((unused))) { /* Can't call with `1' because rl_undo_list might point to an undo list from a history entry, just like we're setting up here. */ @@ -342,16 +339,15 @@ rl_replace_from_history (entry, flags) /* Meta-< goes to the start of the history. */ int -rl_beginning_of_history (count, key) - int count, key; +rl_beginning_of_history (int count __attribute__((unused)), int key) { return (rl_get_previous_history (1 + where_history (), key)); } /* Meta-> goes to the end of the history. (The current line). */ int -rl_end_of_history (count, key) - int count, key; +rl_end_of_history (int count __attribute__((unused)), + int key __attribute__((unused))) { rl_maybe_replace_line (); using_history (); @@ -455,8 +451,7 @@ rl_get_previous_history (count, key) /* **************************************************************** */ /* How to toggle back and forth between editing modes. */ int -rl_vi_editing_mode (count, key) - int count, key; +rl_vi_editing_mode (int count __attribute__((unused)), int key) { #if defined (VI_MODE) _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */ @@ -468,8 +463,8 @@ rl_vi_editing_mode (count, key) } int -rl_emacs_editing_mode (count, key) - int count, key; +rl_emacs_editing_mode (int count __attribute__((unused)), + int key __attribute__((unused))) { rl_editing_mode = emacs_mode; _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */ @@ -479,8 +474,7 @@ rl_emacs_editing_mode (count, key) /* Function for the rest of the library to use to set insert/overwrite mode. */ void -_rl_set_insert_mode (im, force) - int im, force; +_rl_set_insert_mode (int im, int force __attribute__((unused))) { #ifdef CURSOR_MODE _rl_set_cursor (im, force); @@ -492,8 +486,7 @@ _rl_set_insert_mode (im, force) /* Toggle overwrite mode. A positive explicit argument selects overwrite mode. A negative or zero explicit argument selects insert mode. */ int -rl_overwrite_mode (count, key) - int count, key; +rl_overwrite_mode (int count, int key __attribute__((unused))) { if (rl_explicit_arg == 0) _rl_set_insert_mode (rl_insert_mode ^ 1, 0); diff --git a/cmd-line-utils/readline/nls.c b/cmd-line-utils/readline/nls.c index 4f28152f316..73ad0227195 100644 --- a/cmd-line-utils/readline/nls.c +++ b/cmd-line-utils/readline/nls.c @@ -111,7 +111,7 @@ _rl_init_eightbit () if (lspec == 0 || *lspec == 0) lspec = setlocale (LC_CTYPE, (char *)NULL); if (lspec == 0) - lspec = ""; + lspec = (char*) ""; t = setlocale (LC_CTYPE, lspec); if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0)) diff --git a/cmd-line-utils/readline/readline.c b/cmd-line-utils/readline/readline.c index e82db84c9dc..dd3724a86d7 100644 --- a/cmd-line-utils/readline/readline.c +++ b/cmd-line-utils/readline/readline.c @@ -83,7 +83,9 @@ static void bind_arrow_keys_internal PARAMS((Keymap)); static void bind_arrow_keys PARAMS((void)); static void readline_default_bindings PARAMS((void)); +#ifdef NOT_USED static void reset_default_bindings PARAMS((void)); +#endif /* **************************************************************** */ /* */ @@ -866,12 +868,14 @@ readline_default_bindings () /* Reset the default bindings for the terminal special characters we're interested in back to rl_insert and read the new ones. */ +#ifdef NOT_USED static void reset_default_bindings () { rl_tty_unset_default_bindings (_rl_keymap); rl_tty_set_default_bindings (_rl_keymap); } +#endif /* Bind some common arrow key sequences in MAP. */ static void diff --git a/cmd-line-utils/readline/rltty.c b/cmd-line-utils/readline/rltty.c index 3e9c71c8df1..ffbae1e08af 100644 --- a/cmd-line-utils/readline/rltty.c +++ b/cmd-line-utils/readline/rltty.c @@ -716,8 +716,7 @@ rl_deprep_terminal () /* **************************************************************** */ int -rl_restart_output (count, key) - int count, key; +rl_restart_output(int count __attribute__((unused)), int key __attribute__((unused))) { int fildes = fileno (rl_outstream); #if defined (TIOCSTART) @@ -749,8 +748,7 @@ rl_restart_output (count, key) } int -rl_stop_output (count, key) - int count, key; +rl_stop_output(int count __attribute__((unused)), int key __attribute__((unused))) { int fildes = fileno (rl_instream); @@ -867,7 +865,6 @@ rltty_set_default_bindings (kmap) { TIOTYPE ttybuff; int tty; - static int called = 0; tty = fileno (rl_instream); diff --git a/cmd-line-utils/readline/search.c b/cmd-line-utils/readline/search.c index 1878d2bf031..6479427be2f 100644 --- a/cmd-line-utils/readline/search.c +++ b/cmd-line-utils/readline/search.c @@ -303,8 +303,7 @@ noninc_search (dir, pchar) /* Search forward through the history list for a string. If the vi-mode code calls this, KEY will be `?'. */ int -rl_noninc_forward_search (count, key) - int count, key; +rl_noninc_forward_search (int count __attribute__((unused)), int key) { noninc_search (1, (key == '?') ? '?' : 0); return 0; @@ -313,8 +312,7 @@ rl_noninc_forward_search (count, key) /* Reverse search the history list for a string. If the vi-mode code calls this, KEY will be `/'. */ int -rl_noninc_reverse_search (count, key) - int count, key; +rl_noninc_reverse_search (int count __attribute__((unused)), int key) { noninc_search (-1, (key == '/') ? '/' : 0); return 0; @@ -323,8 +321,8 @@ rl_noninc_reverse_search (count, key) /* Search forward through the history list for the last string searched for. If there is no saved search string, abort. */ int -rl_noninc_forward_search_again (count, key) - int count, key; +rl_noninc_forward_search_again (int count __attribute__((unused)), + int key __attribute__((unused))) { if (!noninc_search_string) { @@ -338,8 +336,8 @@ rl_noninc_forward_search_again (count, key) /* Reverse search in the history list for the last string searched for. If there is no saved search string, abort. */ int -rl_noninc_reverse_search_again (count, key) - int count, key; +rl_noninc_reverse_search_again (int count __attribute__((unused)), + int key __attribute__((unused))) { if (!noninc_search_string) { diff --git a/cmd-line-utils/readline/terminal.c b/cmd-line-utils/readline/terminal.c index 3545fce5b85..4b900c5d860 100644 --- a/cmd-line-utils/readline/terminal.c +++ b/cmd-line-utils/readline/terminal.c @@ -344,7 +344,7 @@ get_term_capabilities (bp) #if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */ register int i; - for (i = 0; i < NUM_TC_STRINGS; i++) + for (i = 0; i < (int) NUM_TC_STRINGS; i++) *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp); #endif tcap_initialized = 1; @@ -410,7 +410,7 @@ _rl_init_terminal_io (terminal_name) /* Everything below here is used by the redisplay code (tputs). */ _rl_screenchars = _rl_screenwidth * _rl_screenheight; - _rl_term_cr = "\r"; + _rl_term_cr = (char*) "\r"; _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL; _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL; _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL; @@ -427,7 +427,7 @@ _rl_init_terminal_io (terminal_name) tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we change that later... */ PC = '\0'; - BC = _rl_term_backspace = "\b"; + BC = _rl_term_backspace = (char*) "\b"; UP = _rl_term_up; return 0; @@ -442,7 +442,7 @@ _rl_init_terminal_io (terminal_name) UP = _rl_term_up; if (!_rl_term_cr) - _rl_term_cr = "\r"; + _rl_term_cr = (char*) "\r"; _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn"); @@ -502,7 +502,7 @@ rl_get_termcap (cap) if (tcap_initialized == 0) return ((char *)NULL); - for (i = 0; i < NUM_TC_STRINGS; i++) + for (i = 0; i < (int) NUM_TC_STRINGS; i++) { if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0) return *(tc_strings[i].tc_value); diff --git a/cmd-line-utils/readline/text.c b/cmd-line-utils/readline/text.c index ad7b53ec422..89457be37cd 100644 --- a/cmd-line-utils/readline/text.c +++ b/cmd-line-utils/readline/text.c @@ -402,8 +402,7 @@ rl_backward (count, key) /* Move to the beginning of the line. */ int -rl_beg_of_line (count, key) - int count, key; +rl_beg_of_line (int count __attribute__((unused)), int key __attribute__((unused))) { rl_point = 0; return 0; @@ -411,8 +410,7 @@ rl_beg_of_line (count, key) /* Move to the end of the line. */ int -rl_end_of_line (count, key) - int count, key; +rl_end_of_line (int count __attribute__((unused)), int key __attribute__((unused))) { rl_point = rl_end; return 0; @@ -508,8 +506,7 @@ rl_backward_word (count, key) /* Clear the current line. Numeric argument to C-l does this. */ int -rl_refresh_line (ignore1, ignore2) - int ignore1, ignore2; +rl_refresh_line (int count __attribute__((unused)), int key __attribute__((unused))) { int curr_line; @@ -547,8 +544,7 @@ rl_clear_screen (count, key) } int -rl_arrow_keys (count, c) - int count, c; +rl_arrow_keys (int count, int c __attribute__((unused))) { int ch; @@ -596,7 +592,7 @@ rl_arrow_keys (count, c) #ifdef HANDLE_MULTIBYTE static char pending_bytes[MB_LEN_MAX]; static int pending_bytes_length = 0; -static mbstate_t ps = {0}; +static mbstate_t ps; #endif /* Insert the character C at the current location, moving point forward. @@ -832,8 +828,7 @@ rl_insert (count, c) /* Insert the next typed character verbatim. */ int -rl_quoted_insert (count, key) - int count, key; +rl_quoted_insert (int count, int key __attribute__((unused))) { int c; @@ -854,8 +849,7 @@ rl_quoted_insert (count, key) /* Insert a tab character. */ int -rl_tab_insert (count, key) - int count, key; +rl_tab_insert (int count, int key __attribute__((unused))) { return (_rl_insert_char (count, '\t')); } @@ -864,8 +858,7 @@ rl_tab_insert (count, key) KEY is the key that invoked this command. I guess it could have meaning in the future. */ int -rl_newline (count, key) - int count, key; +rl_newline (int count __attribute__((unused)), int key __attribute__((unused))) { rl_done = 1; @@ -898,8 +891,8 @@ rl_newline (count, key) is just a stub, you bind keys to it and the code in _rl_dispatch () is special cased. */ int -rl_do_lowercase_version (ignore1, ignore2) - int ignore1, ignore2; +rl_do_lowercase_version (int count __attribute__((unused)), + int key __attribute__((unused))) { return 0; } @@ -1093,8 +1086,8 @@ rl_rubout_or_delete (count, key) /* Delete all spaces and tabs around point. */ int -rl_delete_horizontal_space (count, ignore) - int count, ignore; +rl_delete_horizontal_space (int count __attribute__((unused)), + int key __attribute__((unused))) { int start = rl_point; @@ -1134,14 +1127,13 @@ rl_delete_or_show_completions (count, key) /* Turn the current line into a comment in shell history. A K*rn shell style function. */ int -rl_insert_comment (count, key) - int count, key; +rl_insert_comment (int count __attribute__((unused)), int key) { char *rl_comment_text; int rl_comment_len; rl_beg_of_line (1, key); - rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT; + rl_comment_text = _rl_comment_begin ? _rl_comment_begin : (char*) RL_COMMENT_BEGIN_DEFAULT; if (rl_explicit_arg == 0) rl_insert_text (rl_comment_text); @@ -1173,24 +1165,21 @@ rl_insert_comment (count, key) /* Uppercase the word at point. */ int -rl_upcase_word (count, key) - int count, key; +rl_upcase_word (int count, int key __attribute__((unused))) { return (rl_change_case (count, UpCase)); } /* Lowercase the word at point. */ int -rl_downcase_word (count, key) - int count, key; +rl_downcase_word (int count, int key __attribute__((unused))) { return (rl_change_case (count, DownCase)); } /* Upcase the first letter, downcase the rest. */ int -rl_capitalize_word (count, key) - int count, key; +rl_capitalize_word (int count, int key __attribute__((unused))) { return (rl_change_case (count, CapCase)); } @@ -1314,8 +1303,7 @@ rl_transpose_words (count, key) /* Transpose the characters at point. If point is at the end of the line, then transpose the characters before point. */ int -rl_transpose_chars (count, key) - int count, key; +rl_transpose_chars (int count, int key __attribute__((unused))) { #if defined (HANDLE_MULTIBYTE) char *dummy; @@ -1486,15 +1474,13 @@ _rl_char_search (count, fdir, bdir) #endif /* !HANDLE_MULTIBYTE */ int -rl_char_search (count, key) - int count, key; +rl_char_search (int count, int key __attribute__((unused))) { return (_rl_char_search (count, FFIND, BFIND)); } int -rl_backward_char_search (count, key) - int count, key; +rl_backward_char_search (int count, int key __attribute__((unused))) { return (_rl_char_search (count, BFIND, FFIND)); } @@ -1519,16 +1505,15 @@ _rl_set_mark_at_pos (position) /* A bindable command to set the mark. */ int -rl_set_mark (count, key) - int count, key; +rl_set_mark (int count, int key __attribute__((unused))) { return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point)); } /* Exchange the position of mark and point. */ int -rl_exchange_point_and_mark (count, key) - int count, key; +rl_exchange_point_and_mark (int count __attribute__((unused)), + int key __attribute__((unused))) { if (rl_mark > rl_end) rl_mark = -1; diff --git a/cmd-line-utils/readline/tilde.c b/cmd-line-utils/readline/tilde.c index c44357ffbea..91eead0d9e2 100644 --- a/cmd-line-utils/readline/tilde.c +++ b/cmd-line-utils/readline/tilde.c @@ -190,7 +190,7 @@ tilde_expand (string) int result_size, result_index; result_index = result_size = 0; - if (result = strchr (string, '~')) + if ((result = strchr (string, '~'))) result = (char *)xmalloc (result_size = (strlen (string) + 16)); else result = (char *)xmalloc (result_size = (strlen (string) + 1)); diff --git a/cmd-line-utils/readline/undo.c b/cmd-line-utils/readline/undo.c index 48baded332a..b4b5a6511ba 100644 --- a/cmd-line-utils/readline/undo.c +++ b/cmd-line-utils/readline/undo.c @@ -175,7 +175,7 @@ _rl_fix_last_undo_of_type (type, start, end) for (rl = rl_undo_list; rl; rl = rl->next) { - if (rl->what == type) + if (rl->what == (uint) type) { rl->start = start; rl->end = end; @@ -226,8 +226,7 @@ rl_modifying (start, end) /* Revert the current line to its previous state. */ int -rl_revert_line (count, key) - int count, key; +rl_revert_line (int count __attribute__((unused)), int key __attribute__((unused))) { if (!rl_undo_list) rl_ding (); @@ -241,8 +240,7 @@ rl_revert_line (count, key) /* Do some undoing of things that were done. */ int -rl_undo_command (count, key) - int count, key; +rl_undo_command (int count, int key __attribute__((unused))) { if (count < 0) return 0; /* Nothing to do. */ diff --git a/cmd-line-utils/readline/util.c b/cmd-line-utils/readline/util.c index 43478aaf1ac..d5fe51a7bf2 100644 --- a/cmd-line-utils/readline/util.c +++ b/cmd-line-utils/readline/util.c @@ -95,15 +95,13 @@ _rl_abort_internal () } int -rl_abort (count, key) - int count, key; +rl_abort (int count __attribute__((unused)), int key __attribute__((unused))) { return (_rl_abort_internal ()); } int -rl_tty_status (count, key) - int count, key; +rl_tty_status (int count __attribute__((unused)), int key __attribute__((unused))) { #if defined (TIOCSTAT) ioctl (1, TIOCSTAT, (char *)0); @@ -152,8 +150,7 @@ rl_extend_line_buffer (len) /* A function for simple tilde expansion. */ int -rl_tilde_expand (ignore, key) - int ignore, key; +rl_tilde_expand (int ignore __attribute__((unused)), int key __attribute__((unused))) { register int start, end; char *homedir, *temp; diff --git a/cmd-line-utils/readline/vi_mode.c b/cmd-line-utils/readline/vi_mode.c index 9a8cfdd7200..4d1cc56117d 100644 --- a/cmd-line-utils/readline/vi_mode.c +++ b/cmd-line-utils/readline/vi_mode.c @@ -112,7 +112,7 @@ _rl_vi_initialize_line () { register int i; - for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) + for (i = 0; i < (int) (sizeof (vi_mark_chars) / sizeof (int)); i++) vi_mark_chars[i] = -1; } @@ -166,8 +166,7 @@ _rl_vi_stuff_insert (count) redo a text modification command. The default for _rl_vi_last_command puts you back into insert mode. */ int -rl_vi_redo (count, c) - int count, c; +rl_vi_redo (int count, int c __attribute__((unused))) { int r; @@ -205,8 +204,7 @@ rl_vi_undo (count, key) /* Yank the nth arg from the previous line into this line at point. */ int -rl_vi_yank_arg (count, key) - int count, key; +rl_vi_yank_arg (int count, int key __attribute__((unused))) { /* Readline thinks that the first word on a line is the 0th, while vi thinks the first word on a line is the 1st. Compensate. */ @@ -286,8 +284,7 @@ rl_vi_search (count, key) /* Completion, from vi's point of view. */ int -rl_vi_complete (ignore, key) - int ignore, key; +rl_vi_complete (int ignore __attribute__((unused)), int key) { if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) { @@ -313,8 +310,7 @@ rl_vi_complete (ignore, key) /* Tilde expansion for vi mode. */ int -rl_vi_tilde_expand (ignore, key) - int ignore, key; +rl_vi_tilde_expand (int ignore __attribute__((unused)), int key) { rl_tilde_expand (0, key); rl_vi_start_inserting (key, 1, rl_arg_sign); @@ -384,8 +380,7 @@ rl_vi_end_word (count, key) /* Move forward a word the way that 'W' does. */ int -rl_vi_fWord (count, ignore) - int count, ignore; +rl_vi_fWord (int count, int ignore __attribute__((unused))) { while (count-- && rl_point < (rl_end - 1)) { @@ -401,8 +396,7 @@ rl_vi_fWord (count, ignore) } int -rl_vi_bWord (count, ignore) - int count, ignore; +rl_vi_bWord (int count, int ignore __attribute__((unused))) { while (count-- && rl_point > 0) { @@ -425,8 +419,7 @@ rl_vi_bWord (count, ignore) } int -rl_vi_eWord (count, ignore) - int count, ignore; +rl_vi_eWord(int count, int ignore __attribute__((unused))) { while (count-- && rl_point < (rl_end - 1)) { @@ -456,8 +449,7 @@ rl_vi_eWord (count, ignore) } int -rl_vi_fword (count, ignore) - int count, ignore; +rl_vi_fword (int count, int ignore __attribute__((unused))) { while (count-- && rl_point < (rl_end - 1)) { @@ -482,8 +474,7 @@ rl_vi_fword (count, ignore) } int -rl_vi_bword (count, ignore) - int count, ignore; +rl_vi_bword (int count, int ignore __attribute__((unused))) { while (count-- && rl_point > 0) { @@ -521,8 +512,7 @@ rl_vi_bword (count, ignore) } int -rl_vi_eword (count, ignore) - int count, ignore; +rl_vi_eword (int count, int ignore __attribute__((unused))) { while (count-- && rl_point < rl_end - 1) { @@ -546,8 +536,7 @@ rl_vi_eword (count, ignore) } int -rl_vi_insert_beg (count, key) - int count, key; +rl_vi_insert_beg (int count __attribute__((unused)), int key) { rl_beg_of_line (1, key); rl_vi_insertion_mode (1, key); @@ -555,8 +544,7 @@ rl_vi_insert_beg (count, key) } int -rl_vi_append_mode (count, key) - int count, key; +rl_vi_append_mode (int count __attribute__((unused)), int key) { if (rl_point < rl_end) { @@ -575,8 +563,7 @@ rl_vi_append_mode (count, key) } int -rl_vi_append_eol (count, key) - int count, key; +rl_vi_append_eol (int count __attribute__((unused)), int key) { rl_end_of_line (1, key); rl_vi_append_mode (1, key); @@ -585,8 +572,7 @@ rl_vi_append_eol (count, key) /* What to do in the case of C-d. */ int -rl_vi_eof_maybe (count, c) - int count, c; +rl_vi_eof_maybe (int count __attribute__((unused)), int c __attribute__((unused))) { return (rl_newline (1, '\n')); } @@ -596,8 +582,7 @@ rl_vi_eof_maybe (count, c) /* Switching from one mode to the other really just involves switching keymaps. */ int -rl_vi_insertion_mode (count, key) - int count, key; +rl_vi_insertion_mode (int count __attribute__((unused)), int key) { _rl_keymap = vi_insertion_keymap; _rl_vi_last_key_before_insert = key; @@ -659,8 +644,7 @@ _rl_vi_done_inserting () } int -rl_vi_movement_mode (count, key) - int count, key; +rl_vi_movement_mode (int count __attribute__((unused)), int key) { if (rl_point > 0) rl_backward_char (1, key); @@ -729,8 +713,7 @@ _rl_vi_change_mbchar_case (count) #endif int -rl_vi_change_case (count, ignore) - int count, ignore; +rl_vi_change_case (int count, int ignore __attribute__((unused))) { int c, p; @@ -959,8 +942,7 @@ rl_digit_loop1 () } int -rl_vi_delete_to (count, key) - int count, key; +rl_vi_delete_to (int count __attribute__((unused)), int key) { int c; @@ -985,8 +967,7 @@ rl_vi_delete_to (count, key) } int -rl_vi_change_to (count, key) - int count, key; +rl_vi_change_to (int count __attribute__((unused)), int key) { int c, start_pos; @@ -1038,8 +1019,7 @@ rl_vi_change_to (count, key) } int -rl_vi_yank_to (count, key) - int count, key; +rl_vi_yank_to (int count __attribute__((unused)), int key) { int c, save = rl_point; @@ -1094,8 +1074,7 @@ rl_vi_delete (count, key) } int -rl_vi_back_to_indent (count, key) - int count, key; +rl_vi_back_to_indent (int count __attribute__((unused)), int key) { rl_beg_of_line (1, key); while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) @@ -1104,8 +1083,7 @@ rl_vi_back_to_indent (count, key) } int -rl_vi_first_print (count, key) - int count, key; +rl_vi_first_print (int count __attribute__((unused)), int key) { return (rl_vi_back_to_indent (1, key)); } @@ -1173,8 +1151,7 @@ rl_vi_char_search (count, key) /* Match brackets */ int -rl_vi_match (ignore, key) - int ignore, key; +rl_vi_match (int ignore __attribute__((unused)), int key) { int count = 1, brack, pos, tmp, pre; @@ -1284,8 +1261,7 @@ rl_vi_bracktype (c) for test against 033 or ^C. Make sure that _rl_read_mbchar does this right. */ int -rl_vi_change_char (count, key) - int count, key; +rl_vi_change_char (int count, int key __attribute__((unused))) { int c, p; @@ -1389,8 +1365,7 @@ rl_vi_overstrike_delete (count, key) } int -rl_vi_replace (count, key) - int count, key; +rl_vi_replace (int count __attribute__((unused)), int key __attribute__((unused))) { int i; @@ -1450,8 +1425,7 @@ rl_vi_possible_completions() /* Functions to save and restore marks. */ int -rl_vi_set_mark (count, key) - int count, key; +rl_vi_set_mark (int count __attribute__((unused)), int key __attribute__((unused))) { int ch; @@ -1470,8 +1444,7 @@ rl_vi_set_mark (count, key) } int -rl_vi_goto_mark (count, key) - int count, key; +rl_vi_goto_mark (int count __attribute__((unused)), int key __attribute__((unused))) { int ch; diff --git a/config/ac-macros/ha_berkeley.m4 b/config/ac-macros/ha_berkeley.m4 index 732c7730816..82786436720 100644 --- a/config/ac-macros/ha_berkeley.m4 +++ b/config/ac-macros/ha_berkeley.m4 @@ -243,20 +243,20 @@ bdb_version_ok=yes ]) AC_DEFUN([MYSQL_TOP_BUILDDIR], [ + # Remove trailing "./" if any + [$1]=`echo $[$1] | sed -e 's,^\./,,'` case "$[$1]" in - /* ) ;; # don't do anything with an absolute path - "$srcdir"/* ) + "bdb" | "$srcdir/bdb" | "$top_srcdir/bdb" | "$abs_top_srcdir/bdb" ) # If BDB is under the source directory, we need to look under the # build directory for bdb/build_unix. - # NOTE: I'm being lazy, and assuming the user did not specify - # something like --with-berkeley-db=bdb (it would be missing "./"). - [$1]="\$(top_builddir)/"`echo "$[$1]" | sed -e "s,^$srcdir/,,"` + [$1]="\$(top_builddir)/bdb" ;; + /* ) ;; # Other absolute path is assume to be external BDB directory * ) AC_MSG_ERROR([The BDB directory must be directly under the MySQL source directory, or be specified using the full path. ('$srcdir'; '$[$1]')]) ;; esac - if test X"$[$1]" != "/" + if test X"$[$1]" != X"/" then [$1]=`echo $[$1] | sed -e 's,/$,,'` fi diff --git a/config/ac-macros/ha_innodb.m4 b/config/ac-macros/ha_innodb.m4 index 17f0fab3e90..f670eeb9751 100644 --- a/config/ac-macros/ha_innodb.m4 +++ b/config/ac-macros/ha_innodb.m4 @@ -20,7 +20,7 @@ AC_DEFUN([MYSQL_CHECK_INNODB], [ AC_MSG_RESULT([Using Innodb]) AC_DEFINE([HAVE_INNOBASE_DB], [1], [Using Innobase DB]) have_innodb="yes" - innodb_includes="-I../innobase/include" + innodb_includes="-I\$(top_builddir)/innobase/include -I\$(top_srcdir)/innobase/include" innodb_system_libs="" dnl Some libs are listed several times, in order for gcc to sort out dnl circular references. diff --git a/config/ac-macros/ha_ndbcluster.m4 b/config/ac-macros/ha_ndbcluster.m4 index 2ff598242e4..8e953544df9 100644 --- a/config/ac-macros/ha_ndbcluster.m4 +++ b/config/ac-macros/ha_ndbcluster.m4 @@ -140,7 +140,7 @@ AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [ AC_MSG_RESULT([Using NDB Cluster]) AC_DEFINE([HAVE_NDBCLUSTER_DB], [1], [Using Ndb Cluster DB]) have_ndbcluster="yes" - ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi -I../ndb/include/mgmapi" + ndbcluster_includes="-I\$(top_builddir)/ndb/include -I\$(top_srcdir)/ndb/include -I\$(top_srcdir)/ndb/include/ndbapi -I\$(top_srcdir)/ndb/include/mgmapi" ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a" ndbcluster_system_libs="" ndb_mgmclient_libs="\$(top_builddir)/ndb/src/mgmclient/libndbmgmclient.la" diff --git a/configure.in b/configure.in index d0c2cd87381..f6a6eedac70 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.30) +AM_INIT_AUTOMAKE(mysql, 5.0.32) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=30 +NDB_VERSION_BUILD=32 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? diff --git a/dbug/dbug_analyze.c b/dbug/dbug_analyze.c index 1db056d549c..f1caeea2be4 100644 --- a/dbug/dbug_analyze.c +++ b/dbug/dbug_analyze.c @@ -169,7 +169,7 @@ register unsigned long *child_time; *name_pos = temp->pos; *time_entered = temp->time; *child_time = temp->children; - DBUG_PRINT ("pop", ("%d %d %d",*name_pos,*time_entered,*child_time)); + DBUG_PRINT ("pop", ("%d %lu %lu",*name_pos,*time_entered,*child_time)); rtnval = stacktop--; } DBUG_RETURN (rtnval); @@ -334,12 +334,12 @@ FILE *inf; * function is found on the stack. */ while (pop (&oldpos, &oldtime, &oldchild)) { - DBUG_PRINT ("popped", ("%d %d", oldtime, oldchild)); + DBUG_PRINT ("popped", ("%lu %lu", oldtime, oldchild)); time = fn_time - oldtime; t = top (); t -> children += time; DBUG_PRINT ("update", ("%s", modules[t -> pos].name)); - DBUG_PRINT ("update", ("%d", t -> children)); + DBUG_PRINT ("update", ("%lu", t -> children)); time -= oldchild; modules[oldpos].m_time += time; modules[oldpos].m_calls++; @@ -520,19 +520,19 @@ register unsigned long int *s_calls, *s_time; unsigned long int calls, time; DBUG_ENTER ("out_body"); - DBUG_PRINT ("out_body", ("%d,%d",*s_calls,*s_time)); + DBUG_PRINT ("out_body", ("%lu,%lu",*s_calls,*s_time)); if (root == MAXPROCS) { - DBUG_PRINT ("out_body", ("%d,%d",*s_calls,*s_time)); + DBUG_PRINT ("out_body", ("%lu,%lu",*s_calls,*s_time)); } else { while (root != MAXPROCS) { out_body (outf, s_table[root].lchild,s_calls,s_time); out_item (outf, &modules[s_table[root].pos],&calls,&time); - DBUG_PRINT ("out_body", ("-- %d -- %d --", calls, time)); + DBUG_PRINT ("out_body", ("-- %lu -- %lu --", calls, time)); *s_calls += calls; *s_time += time; root = s_table[root].rchild; } - DBUG_PRINT ("out_body", ("%d,%d", *s_calls, *s_time)); + DBUG_PRINT ("out_body", ("%lu,%lu", *s_calls, *s_time)); } DBUG_VOID_RETURN; } diff --git a/extra/replace.c b/extra/replace.c index 9acf1620d49..cad3589819b 100644 --- a/extra/replace.c +++ b/extra/replace.c @@ -1052,8 +1052,10 @@ static int convert_file(REPLACE *rep, my_string name) { int error; FILE *in,*out; - char dir_buff[FN_REFLEN], tempname[FN_REFLEN]; - char link_name[FN_REFLEN], *org_name = name; + char dir_buff[FN_REFLEN], tempname[FN_REFLEN], *org_name = name; +#ifdef HAVE_READLINK + char link_name[FN_REFLEN]; +#endif File temp_file; DBUG_ENTER("convert_file"); diff --git a/extra/yassl/README b/extra/yassl/README index 2af4e98fe4c..fbeffd9db77 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -1,4 +1,56 @@ -yaSSL Release notes, version 1.4.0 (08/13/06) +yaSSL Release notes, version 1.5.0 (11/09/06) + + This release of yaSSL contains bug fixes, portability enhancements, + and full TLS 1.1 support. Use the functions: + + SSL_METHOD *TLSv1_1_server_method(void); + SSL_METHOD *TLSv1_1_client_method(void); + + or the SSLv23 versions (even though yaSSL doesn't support SSL 2.0 the v23 + means to pick the highest of SSL 3.0, TLS 1.0, or TLS 1.1. + + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0. + + + +****************yaSSL Release notes, version 1.4.5 (10/15/06) + + + This release of yaSSL contains bug fixes, portability enhancements, + zlib compression support, removal of assembly instructions at runtime if + not supported, and initial TLS 1.1 support. + + + Compression Notes: yaSSL uses zlib for compression and the compression + should only be used if yaSSL is at both ends because the implementation + details aren't yet standard. If you'd like to turn compression on use + the SSL_set_compression() function on the client before calling + SSL_connect(). If both the client and server were built with zlib support + then the connection will use compression. If the client isn't built with + support then SSL_set_compression() will return an error (-1). + + To build yaSSL with zlib support on Unix simply have zlib support on your + system and configure will find it if it's in the standard locations. If + it's somewhere else use the option ./configure --with-zlib=DIR. If you'd + like to disable compression support in yaSSL use ./configure --without-zlib. + + To build yaSSL with zlib support on Windows: + + 1) download zlib from http://www.zlib.net/ + 2) follow the instructions in zlib from projects/visualc6/README.txt + for how to add the zlib project into the yaSSL workspace noting that + you'll need to add configuration support for "Win32 Debug" and + "Win32 Release" in note 3 under "To use:". + 3) define HAVE_LIBZ when building yaSSL + + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0. + + +********************yaSSL Release notes, version 1.4.0 (08/13/06) This release of yaSSL contains bug fixes, portability enhancements, @@ -122,18 +174,6 @@ Choose (Re)Build All from the project workspace run Debug\testsuite.exe from yaSSL-Home\testsuite to test the build ---To enable ia32 assembly for TaoCrypt ciphers and message digests - - On MSVC this is always on - - On GCC **, use ./configure --enable-ia32-asm - - ** This isn't on by default because of the use of intel syntax and the - problem that olders versions of gas have with some addressing statements. - If you enable this and get assemler errors during compilation or can't - pass the TaoCrypt tests, please send todd@yassl.com a message and disable - this option in the meantime. - ***************** yaSSL Release notes, version 1.0.5 diff --git a/extra/yassl/examples/client/client.cpp b/extra/yassl/examples/client/client.cpp index d655011deb6..6c3cdf04dc1 100644 --- a/extra/yassl/examples/client/client.cpp +++ b/extra/yassl/examples/client/client.cpp @@ -5,6 +5,35 @@ //#define TEST_RESUME +void ClientError(SSL_CTX* ctx, SSL* ssl, SOCKET_T& sockfd, const char* msg) +{ + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + err_sys(msg); +} + + +#ifdef NON_BLOCKING + void NonBlockingSSL_Connect(SSL* ssl, SSL_CTX* ctx, SOCKET_T& sockfd) + { + int ret = SSL_connect(ssl); + while (ret =! SSL_SUCCESS && SSL_get_error(ssl, 0) == + SSL_ERROR_WANT_READ) { + printf("... client would block\n"); + #ifdef _WIN32 + Sleep(1000); + #else + sleep(1); + #endif + ret = SSL_connect(ssl); + } + if (ret != SSL_SUCCESS) + ClientError(ctx, ssl, sockfd, "SSL_connect failed"); + } +#endif + + void client_test(void* args) { #ifdef _WIN32 @@ -18,6 +47,9 @@ void client_test(void* args) set_args(argc, argv, *static_cast<func_args*>(args)); tcp_connect(sockfd); +#ifdef NON_BLOCKING + tcp_set_nonblocking(sockfd); +#endif SSL_METHOD* method = TLSv1_client_method(); SSL_CTX* ctx = SSL_CTX_new(method); @@ -27,13 +59,13 @@ void client_test(void* args) SSL_set_fd(ssl, sockfd); + +#ifdef NON_BLOCKING + NonBlockingSSL_Connect(ssl, ctx, sockfd); +#else if (SSL_connect(ssl) != SSL_SUCCESS) - { - SSL_CTX_free(ctx); - SSL_free(ssl); - tcp_close(sockfd); - err_sys("SSL_connect failed"); - } + ClientError(ctx, ssl, sockfd, "SSL_connect failed"); +#endif showPeer(ssl); const char* cipher = 0; @@ -49,16 +81,14 @@ void client_test(void* args) char msg[] = "hello yassl!"; if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) - { - SSL_CTX_free(ctx); - SSL_free(ssl); - tcp_close(sockfd); - err_sys("SSL_write failed"); - } + ClientError(ctx, ssl, sockfd, "SSL_write failed"); char reply[1024]; - reply[SSL_read(ssl, reply, sizeof(reply))] = 0; + int input = SSL_read(ssl, reply, sizeof(reply)); + if (input > 0) { + reply[input] = 0; printf("Server response: %s\n", reply); + } #ifdef TEST_RESUME SSL_SESSION* session = SSL_get_session(ssl); @@ -75,24 +105,17 @@ void client_test(void* args) SSL_set_session(sslResume, session); if (SSL_connect(sslResume) != SSL_SUCCESS) - { - SSL_CTX_free(ctx); - SSL_free(ssl); - tcp_close(sockfd); - err_sys("SSL resume failed"); - } + ClientError(ctx, sslResume, sockfd, "SSL_resume failed"); showPeer(sslResume); if (SSL_write(sslResume, msg, sizeof(msg)) != sizeof(msg)) - { - SSL_CTX_free(ctx); - SSL_free(ssl); - tcp_close(sockfd); - err_sys("SSL_write failed"); - } + ClientError(ctx, sslResume, sockfd, "SSL_write failed"); - reply[SSL_read(sslResume, reply, sizeof(reply))] = 0; + input = SSL_read(sslResume, reply, sizeof(reply)); + if (input > 0) { + reply[input] = 0; printf("Server response: %s\n", reply); + } SSL_shutdown(sslResume); SSL_free(sslResume); diff --git a/extra/yassl/examples/echoclient/echoclient.cpp b/extra/yassl/examples/echoclient/echoclient.cpp index 983254bf8a7..e2c33c7cda2 100644 --- a/extra/yassl/examples/echoclient/echoclient.cpp +++ b/extra/yassl/examples/echoclient/echoclient.cpp @@ -3,6 +3,15 @@ #include "../../testsuite/test.hpp" +void EchoClientError(SSL_CTX* ctx, SSL* ssl, SOCKET_T& sockfd, const char* msg) +{ + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + err_sys(msg); +} + + void echoclient_test(void* args) { #ifdef _WIN32 @@ -35,7 +44,7 @@ void echoclient_test(void* args) tcp_connect(sockfd); - SSL_METHOD* method = TLSv1_client_method(); + SSL_METHOD* method = SSLv23_client_method(); SSL_CTX* ctx = SSL_CTX_new(method); set_certs(ctx); SSL* ssl = SSL_new(ctx); @@ -43,12 +52,7 @@ void echoclient_test(void* args) SSL_set_fd(ssl, sockfd); if (SSL_connect(ssl) != SSL_SUCCESS) - { - SSL_CTX_free(ctx); - SSL_free(ssl); - tcp_close(sockfd); - err_sys("SSL_connect failed"); - } + EchoClientError(ctx, ssl, sockfd, "SSL_connect failed"); char send[1024]; char reply[1024]; @@ -57,12 +61,7 @@ void echoclient_test(void* args) int sendSz = strlen(send) + 1; if (SSL_write(ssl, send, sendSz) != sendSz) - { - SSL_CTX_free(ctx); - SSL_free(ssl); - tcp_close(sockfd); - err_sys("SSL_write failed"); - } + EchoClientError(ctx, ssl, sockfd, "SSL_write failed"); if (strncmp(send, "quit", 4) == 0) { fputs("sending server shutdown command: quit!\n", fout); diff --git a/extra/yassl/examples/echoserver/echoserver.cpp b/extra/yassl/examples/echoserver/echoserver.cpp index cd31fedddd8..92613744ba0 100644 --- a/extra/yassl/examples/echoserver/echoserver.cpp +++ b/extra/yassl/examples/echoserver/echoserver.cpp @@ -56,7 +56,7 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) tcp_listen(sockfd); - SSL_METHOD* method = TLSv1_server_method(); + SSL_METHOD* method = SSLv23_server_method(); SSL_CTX* ctx = SSL_CTX_new(method); set_serverCerts(ctx); @@ -87,8 +87,12 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); - if (SSL_accept(ssl) != SSL_SUCCESS) - EchoError(ctx, ssl, sockfd, clientfd, "SSL_accept failed"); + if (SSL_accept(ssl) != SSL_SUCCESS) { + printf("SSL_accept failed\n"); + SSL_free(ssl); + tcp_close(clientfd); + continue; + } char command[1024]; int echoSz(0); @@ -130,6 +134,7 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) if (SSL_write(ssl, command, echoSz) != echoSz) EchoError(ctx, ssl, sockfd, clientfd, "SSL_write failed"); } + SSL_shutdown(ssl); SSL_free(ssl); tcp_close(clientfd); } diff --git a/extra/yassl/examples/server/server.cpp b/extra/yassl/examples/server/server.cpp index d0bf70cd634..75ce4224770 100644 --- a/extra/yassl/examples/server/server.cpp +++ b/extra/yassl/examples/server/server.cpp @@ -13,6 +13,26 @@ void ServerError(SSL_CTX* ctx, SSL* ssl, SOCKET_T& sockfd, const char* msg) } +#ifdef NON_BLOCKING + void NonBlockingSSL_Accept(SSL* ssl, SSL_CTX* ctx, SOCKET_T& clientfd) + { + int ret = SSL_accept(ssl); + while (ret != SSL_SUCCESS && SSL_get_error(ssl, 0) == + SSL_ERROR_WANT_READ) { + printf("... server would block\n"); + #ifdef _WIN32 + Sleep(1000); + #else + sleep(1); + #endif + ret = SSL_accept(ssl); + } + if (ret != SSL_SUCCESS) + ServerError(ctx, ssl, clientfd, "SSL_accept failed"); + } +#endif + + THREAD_RETURN YASSL_API server_test(void* args) { #ifdef _WIN32 @@ -33,7 +53,7 @@ THREAD_RETURN YASSL_API server_test(void* args) SSL_METHOD* method = TLSv1_server_method(); SSL_CTX* ctx = SSL_CTX_new(method); - //SSL_CTX_set_cipher_list(ctx, "RC4-SHA"); + //SSL_CTX_set_cipher_list(ctx, "RC4-SHA:RC4-MD5"); SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0); set_serverCerts(ctx); DH* dh = set_tmpDH(ctx); @@ -41,15 +61,22 @@ THREAD_RETURN YASSL_API server_test(void* args) SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); +#ifdef NON_BLOCKING + NonBlockingSSL_Accept(ssl, ctx, clientfd); +#else if (SSL_accept(ssl) != SSL_SUCCESS) ServerError(ctx, ssl, clientfd, "SSL_accept failed"); +#endif showPeer(ssl); printf("Using Cipher Suite: %s\n", SSL_get_cipher(ssl)); char command[1024]; - command[SSL_read(ssl, command, sizeof(command))] = 0; + int input = SSL_read(ssl, command, sizeof(command)); + if (input > 0) { + command[input] = 0; printf("First client command: %s\n", command); + } char msg[] = "I hear you, fa shizzle!"; if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) @@ -57,6 +84,7 @@ THREAD_RETURN YASSL_API server_test(void* args) DH_free(dh); SSL_CTX_free(ctx); + SSL_shutdown(ssl); SSL_free(ssl); tcp_close(clientfd); @@ -82,3 +110,4 @@ THREAD_RETURN YASSL_API server_test(void* args) } #endif // NO_MAIN_DRIVER + diff --git a/extra/yassl/include/factory.hpp b/extra/yassl/include/factory.hpp index 04d742431dc..dc25cf0ee70 100644 --- a/extra/yassl/include/factory.hpp +++ b/extra/yassl/include/factory.hpp @@ -42,12 +42,7 @@ namespace STL = STL_NAMESPACE; -// VC60 workaround: it doesn't allow typename in some places -#if defined(_MSC_VER) && (_MSC_VER < 1300) - #define CPP_TYPENAME -#else - #define CPP_TYPENAME typename -#endif + namespace yaSSL { diff --git a/extra/yassl/include/openssl/prefix_ssl.h b/extra/yassl/include/openssl/prefix_ssl.h index aa3f799cf80..dc6e3ef81f0 100644 --- a/extra/yassl/include/openssl/prefix_ssl.h +++ b/extra/yassl/include/openssl/prefix_ssl.h @@ -52,6 +52,7 @@ #define SSL_set_session yaSSL_set_session #define SSL_get_session yaSSL_get_session #define SSL_SESSION_set_timeout yaSSL_SESSION_set_timeout +#define SSL_CTX_set_session_cache_mode yaSSL_CTX_set_session_cache_mode #define SSL_get_peer_certificate yaSSL_get_peer_certificate #define SSL_get_verify_result yaSSL_get_verify_result #define SSL_CTX_set_verify yaSSL_CTX_set_verify @@ -98,6 +99,8 @@ #define SSLv3_client_method yaSSLv3_client_method #define TLSv1_server_method yaTLSv1_server_method #define TLSv1_client_method yaTLSv1_client_method +#define TLSv1_1_server_method yaTLSv1_1_server_method +#define TLSv1_1_client_method yaTLSv1_1_client_method #define SSLv23_server_method yaSSLv23_server_method #define SSL_CTX_use_certificate_file yaSSL_CTX_use_certificate_file #define SSL_CTX_use_PrivateKey_file yaSSL_CTX_use_PrivateKey_file @@ -159,3 +162,4 @@ #define MD5_Init yaMD5_Init #define MD5_Update yaMD5_Update #define MD5_Final yaMD5_Final +#define SSL_set_compression yaSSL_set_compression diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 5e7290d2a7a..67c49a808fd 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -41,7 +41,7 @@ #include "rsa.h" -#define YASSL_VERSION "1.4.3" +#define YASSL_VERSION "1.5.0" #if defined(__cplusplus) @@ -228,6 +228,7 @@ void SSL_load_error_strings(void); int SSL_set_session(SSL *ssl, SSL_SESSION *session); SSL_SESSION* SSL_get_session(SSL* ssl); long SSL_SESSION_set_timeout(SSL_SESSION*, long); +long SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long mode); X509* SSL_get_peer_certificate(SSL*); long SSL_get_verify_result(SSL*); @@ -361,6 +362,8 @@ SSL_METHOD *SSLv3_server_method(void); SSL_METHOD *SSLv3_client_method(void); SSL_METHOD *TLSv1_server_method(void); SSL_METHOD *TLSv1_client_method(void); +SSL_METHOD *TLSv1_1_server_method(void); +SSL_METHOD *TLSv1_1_client_method(void); SSL_METHOD *SSLv23_server_method(void); int SSL_CTX_use_certificate_file(SSL_CTX*, const char*, int); @@ -531,6 +534,10 @@ void MD5_Final(unsigned char*, MD5_CTX*); #define SSL_DEFAULT_CIPHER_LIST "" /* default all */ +/* yaSSL adds */ +int SSL_set_compression(SSL*); /* turn on yaSSL zlib compression */ + + #if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE) diff --git a/extra/yassl/include/socket_wrapper.hpp b/extra/yassl/include/socket_wrapper.hpp index 9fc0d62f90e..bc82384d85e 100644 --- a/extra/yassl/include/socket_wrapper.hpp +++ b/extra/yassl/include/socket_wrapper.hpp @@ -70,8 +70,8 @@ typedef unsigned char byte; // Wraps Windows Sockets and BSD Sockets class Socket { socket_t socket_; // underlying socket descriptor - bool wouldBlock_; // for non-blocking data - bool blocking_; // is option set + bool wouldBlock_; // if non-blocking data, for last read + bool nonBlocking_; // is option set public: explicit Socket(socket_t s = INVALID_SOCKET); ~Socket(); @@ -85,7 +85,7 @@ public: bool wait(); bool WouldBlock() const; - bool IsBlocking() const; + bool IsNonBlocking() const; void closeSocket(); void shutDown(int how = SD_SEND); diff --git a/extra/yassl/include/yassl_error.hpp b/extra/yassl/include/yassl_error.hpp index 72b79b05dbd..f820e5811d9 100644 --- a/extra/yassl/include/yassl_error.hpp +++ b/extra/yassl/include/yassl_error.hpp @@ -56,7 +56,10 @@ enum YasslError { receive_error = 114, certificate_error = 115, privateKey_error = 116, - badVersion_error = 117 + badVersion_error = 117, + compress_error = 118, + decompress_error = 119, + pms_version_error = 120 // !!!! add error message to .cpp !!!! diff --git a/extra/yassl/include/yassl_imp.hpp b/extra/yassl/include/yassl_imp.hpp index 180d7fe7fe1..f51a902b2a5 100644 --- a/extra/yassl/include/yassl_imp.hpp +++ b/extra/yassl/include/yassl_imp.hpp @@ -132,7 +132,6 @@ class Data : public Message { public: Data(); Data(uint16 len, opaque* b); - Data(uint16 len, const opaque* w); friend output_buffer& operator<<(output_buffer&, const Data&); @@ -141,9 +140,9 @@ public: ContentType get_type() const; uint16 get_length() const; - const opaque* get_buffer() const; void set_length(uint16 l); opaque* set_buffer(); + void SetData(uint16, const opaque*); void Process(input_buffer&, SSL&); private: Data(const Data&); // hide copy @@ -232,11 +231,11 @@ public: void Process(input_buffer&, SSL&); const opaque* get_random() const; - friend void buildClientHello(SSL&, ClientHello&, CompressionMethod); + friend void buildClientHello(SSL&, ClientHello&); friend void ProcessOldClientHello(input_buffer& input, SSL& ssl); ClientHello(); - explicit ClientHello(ProtocolVersion pv); + ClientHello(ProtocolVersion pv, bool useCompression); private: ClientHello(const ClientHello&); // hide copy ClientHello& operator=(const ClientHello&); // and assign @@ -253,7 +252,7 @@ class ServerHello : public HandShakeBase { opaque cipher_suite_[SUITE_LEN]; CompressionMethod compression_method_; public: - explicit ServerHello(ProtocolVersion pv); + ServerHello(ProtocolVersion pv, bool useCompression); ServerHello(); friend input_buffer& operator>>(input_buffer&, ServerHello&); @@ -629,8 +628,11 @@ struct Connection { bool send_server_key_; // server key exchange? bool master_clean_; // master secret clean? bool TLS_; // TLSv1 or greater + bool TLSv1_1_; // TLSv1.1 or greater bool sessionID_Set_; // do we have a session - ProtocolVersion version_; + bool compression_; // zlib compression? + ProtocolVersion version_; // negotiated version + ProtocolVersion chVersion_; // client hello version RandomPool& random_; Connection(ProtocolVersion v, RandomPool& ran); @@ -640,6 +642,7 @@ struct Connection { void CleanPreMaster(); void CleanMaster(); void TurnOffTLS(); + void TurnOffTLS1_1(); private: Connection(const Connection&); // hide copy Connection& operator=(const Connection&); // and assign diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp index 0edff289b61..4a3c0ba4e20 100644 --- a/extra/yassl/include/yassl_int.hpp +++ b/extra/yassl/include/yassl_int.hpp @@ -431,6 +431,7 @@ private: DH_Parms dhParms_; pem_password_cb passwordCb_; void* userData_; + bool sessionCacheOff_; Stats stats_; Mutex mutex_; // for Stats public: @@ -445,6 +446,7 @@ public: const Stats& GetStats() const; pem_password_cb GetPasswordCb() const; void* GetUserData() const; + bool GetSessionCacheOff() const; void setVerifyPeer(); void setVerifyNone(); @@ -453,6 +455,7 @@ public: bool SetDH(const DH&); void SetPasswordCb(pem_password_cb cb); void SetUserData(void*); + void SetSessionCacheOff(); void IncrementStats(StatsField); void AddCA(x509* ca); @@ -600,6 +603,7 @@ public: const Socket& getSocket() const; YasslError GetError() const; bool GetMultiProtocol() const; + bool CompressionOn() const; Crypto& useCrypto(); Security& useSecurity(); @@ -617,9 +621,12 @@ public: void set_preMaster(const opaque*, uint); void set_masterSecret(const opaque*); void SetError(YasslError); + int SetCompression(); + void UnSetCompression(); // helpers bool isTLS() const; + bool isTLSv1_1() const; void order_error(); void makeMasterSecret(); void makeTLSMasterSecret(); @@ -653,6 +660,10 @@ private: }; +// compression +int Compress(const byte*, int, input_buffer&); +int DeCompress(input_buffer&, int, input_buffer&); + // conversion functions void c32to24(uint32, uint24&); diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp index e602ee180bf..646c71afddf 100644 --- a/extra/yassl/include/yassl_types.hpp +++ b/extra/yassl/include/yassl_types.hpp @@ -211,6 +211,7 @@ const int FINISHED_LABEL_SZ = 15; // TLS finished lable length const int SEED_LEN = RAN_LEN * 2; // TLS seed, client + server random const int DEFAULT_TIMEOUT = 500; // Default Session timeout in seconds const int MAX_RECORD_SIZE = 16384; // 2^14, max size by standard +const int COMPRESS_EXTRA = 1024; // extra compression possible addition typedef uint8 Cipher; // first byte is always 0x00 for SSLv3 & TLS @@ -222,7 +223,7 @@ typedef opaque* DistinguishedName; typedef bool IsExportable; -enum CompressionMethod { no_compression = 0 }; +enum CompressionMethod { no_compression = 0, zlib = 221 }; enum CipherType { stream, block }; diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am index 910bbbdd13f..bc57e7d05ba 100644 --- a/extra/yassl/src/Makefile.am +++ b/extra/yassl/src/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../taocrypt/include -I../taocrypt/mySTL +INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../taocrypt/include -I$(srcdir)/../taocrypt/mySTL noinst_LTLIBRARIES = libyassl.la libyassl_la_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index 25f36c4ea8c..c03d72ff2ef 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -40,9 +40,11 @@ namespace yaSSL { // Build a client hello message from cipher suites and compression method -void buildClientHello(SSL& ssl, ClientHello& hello, - CompressionMethod compression = no_compression) +void buildClientHello(SSL& ssl, ClientHello& hello) { + // store for pre master secret + ssl.useSecurity().use_connection().chVersion_ = hello.client_version_; + ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN); if (ssl.getSecurity().get_resuming()) { hello.id_len_ = ID_LEN; @@ -55,7 +57,6 @@ void buildClientHello(SSL& ssl, ClientHello& hello, memcpy(hello.cipher_suites_, ssl.getSecurity().get_parms().suites_, hello.suite_len_); hello.comp_len_ = 1; - hello.compression_methods_ = compression; hello.set_length(sizeof(ProtocolVersion) + RAN_LEN + @@ -83,7 +84,7 @@ void buildServerHello(SSL& ssl, ServerHello& hello) hello.cipher_suite_[0] = ssl.getSecurity().get_parms().suite_[0]; hello.cipher_suite_[1] = ssl.getSecurity().get_parms().suite_[1]; - hello.compression_method_ = no_compression; + hello.compression_method_ = hello.compression_method_; hello.set_length(sizeof(ProtocolVersion) + RAN_LEN + ID_LEN + sizeof(hello.id_len_) + SUITE_LEN + SIZEOF_ENUM); @@ -151,12 +152,18 @@ void buildHeaders(SSL& ssl, HandShakeHeader& hsHeader, // add handshake from buffer into md5 and sha hashes, exclude record header -void hashHandShake(SSL& ssl, const output_buffer& output) +void hashHandShake(SSL& ssl, const output_buffer& output, bool removeIV = false) { uint sz = output.get_size() - RECORD_HEADER; const opaque* buffer = output.get_buffer() + RECORD_HEADER; + if (removeIV) { // TLSv1_1 IV + uint blockSz = ssl.getCrypto().get_cipher().get_blockSize(); + sz -= blockSz; + buffer += blockSz; + } + ssl.useHashes().use_MD5().update(buffer, sz); ssl.useHashes().use_SHA().update(buffer, sz); } @@ -229,6 +236,18 @@ void decrypt_message(SSL& ssl, input_buffer& input, uint sz) ssl.useCrypto().use_cipher().decrypt(plain.get_buffer(), cipher, sz); memcpy(cipher, plain.get_buffer(), sz); ssl.useSecurity().use_parms().encrypt_size_ = sz; + + if (ssl.isTLSv1_1()) // IV + input.set_current(input.get_current() + + ssl.getCrypto().get_cipher().get_blockSize()); +} + + +// output operator for input_buffer +output_buffer& operator<<(output_buffer& output, const input_buffer& input) +{ + output.write(input.get_buffer(), input.get_size()); + return output; } @@ -239,9 +258,12 @@ void cipherFinished(SSL& ssl, Finished& fin, output_buffer& output) uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ; uint sz = RECORD_HEADER + HANDSHAKE_HEADER + finishedSz + digestSz; uint pad = 0; + uint blockSz = ssl.getCrypto().get_cipher().get_blockSize(); + if (ssl.getSecurity().get_parms().cipher_type_ == block) { + if (ssl.isTLSv1_1()) + sz += blockSz; // IV sz += 1; // pad byte - uint blockSz = ssl.getCrypto().get_cipher().get_blockSize(); pad = (sz - RECORD_HEADER) % blockSz; pad = blockSz - pad; sz += pad; @@ -252,14 +274,21 @@ void cipherFinished(SSL& ssl, Finished& fin, output_buffer& output) buildHeaders(ssl, hsHeader, rlHeader, fin); rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac // and pad, hanshake doesn't + input_buffer iv; + if (ssl.isTLSv1_1() && ssl.getSecurity().get_parms().cipher_type_== block){ + iv.allocate(blockSz); + ssl.getCrypto().get_random().Fill(iv.get_buffer(), blockSz); + iv.add_size(blockSz); + } + uint ivSz = iv.get_size(); output.allocate(sz); - output << rlHeader << hsHeader << fin; + output << rlHeader << iv << hsHeader << fin; - hashHandShake(ssl, output); + hashHandShake(ssl, output, ssl.isTLSv1_1() ? true : false); opaque digest[SHA_LEN]; // max size if (ssl.isTLS()) - TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER, - output.get_size() - RECORD_HEADER, handshake); + TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER + ivSz, + output.get_size() - RECORD_HEADER - ivSz, handshake); else hmac(ssl, digest, output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER, handshake); @@ -282,9 +311,12 @@ void buildMessage(SSL& ssl, output_buffer& output, const Message& msg) uint digestSz = ssl.getCrypto().get_digest().get_digestSize(); uint sz = RECORD_HEADER + msg.get_length() + digestSz; uint pad = 0; + uint blockSz = ssl.getCrypto().get_cipher().get_blockSize(); + if (ssl.getSecurity().get_parms().cipher_type_ == block) { + if (ssl.isTLSv1_1()) // IV + sz += blockSz; sz += 1; // pad byte - uint blockSz = ssl.getCrypto().get_cipher().get_blockSize(); pad = (sz - RECORD_HEADER) % blockSz; pad = blockSz - pad; sz += pad; @@ -294,13 +326,21 @@ void buildMessage(SSL& ssl, output_buffer& output, const Message& msg) buildHeader(ssl, rlHeader, msg); rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac // and pad, hanshake doesn't + input_buffer iv; + if (ssl.isTLSv1_1() && ssl.getSecurity().get_parms().cipher_type_== block){ + iv.allocate(blockSz); + ssl.getCrypto().get_random().Fill(iv.get_buffer(), blockSz); + iv.add_size(blockSz); + } + + uint ivSz = iv.get_size(); output.allocate(sz); - output << rlHeader << msg; + output << rlHeader << iv << msg; opaque digest[SHA_LEN]; // max size if (ssl.isTLS()) - TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER, - output.get_size() - RECORD_HEADER, msg.get_type()); + TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER + ivSz, + output.get_size() - RECORD_HEADER - ivSz, msg.get_type()); else hmac(ssl, digest, output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER, msg.get_type()); @@ -456,6 +496,10 @@ void buildSHA_CertVerify(SSL& ssl, byte* digest) // some clients still send sslv2 client hello void ProcessOldClientHello(input_buffer& input, SSL& ssl) { + if (input.get_remaining() < 2) { + ssl.SetError(bad_input); + return; + } byte b0 = input[AUTO]; byte b1 = input[AUTO]; @@ -721,6 +765,7 @@ int DoProcessReply(SSL& ssl) // each message in record, can be more than 1 if not encrypted if (ssl.getSecurity().get_parms().pending_ == false) // cipher on decrypt_message(ssl, buffer, hdr.length_); + mySTL::auto_ptr<Message> msg(mf.CreateObject(hdr.type_)); if (!msg.get()) { ssl.SetError(factory_error); @@ -744,13 +789,13 @@ void processReply(SSL& ssl) if (DoProcessReply(ssl)) // didn't complete process - if (!ssl.getSocket().IsBlocking()) { - // keep trying now + if (!ssl.getSocket().IsNonBlocking()) { + // keep trying now, blocking ok while (!ssl.GetError()) if (DoProcessReply(ssl) == 0) break; } else - // user will have try again later + // user will have try again later, non blocking ssl.SetError(YasslError(SSL_ERROR_WANT_READ)); } @@ -761,7 +806,8 @@ void sendClientHello(SSL& ssl) ssl.verifyState(serverNull); if (ssl.GetError()) return; - ClientHello ch(ssl.getSecurity().get_connection().version_); + ClientHello ch(ssl.getSecurity().get_connection().version_, + ssl.getSecurity().get_connection().compression_); RecordLayerHeader rlHeader; HandShakeHeader hsHeader; output_buffer out; @@ -859,6 +905,7 @@ void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer) buildFinished(ssl, ssl.useHashes().use_verify(), client); // client } else { + if (!ssl.getSecurity().GetContext()->GetSessionCacheOff()) GetSessions().add(ssl); // store session if (side == client_end) buildFinished(ssl, ssl.useHashes().use_verify(), server); // server @@ -885,7 +932,20 @@ int sendData(SSL& ssl, const void* buffer, int sz) for (;;) { int len = min(sz - sent, MAX_RECORD_SIZE); output_buffer out; - const Data data(len, static_cast<const opaque*>(buffer) + sent); + input_buffer tmp; + + Data data; + + if (ssl.CompressionOn()) { + if (Compress(static_cast<const opaque*>(buffer) + sent, len, + tmp) == -1) { + ssl.SetError(compress_error); + return -1; + } + data.SetData(tmp.get_size(), tmp.get_buffer()); + } + else + data.SetData(len, static_cast<const opaque*>(buffer) + sent); buildMessage(ssl, out, data); ssl.Send(out.get_buffer(), out.get_size()); @@ -947,7 +1007,8 @@ void sendServerHello(SSL& ssl, BufferOutput buffer) ssl.verifyState(clientHelloComplete); if (ssl.GetError()) return; - ServerHello sh(ssl.getSecurity().get_connection().version_); + ServerHello sh(ssl.getSecurity().get_connection().version_, + ssl.getSecurity().get_connection().compression_); RecordLayerHeader rlHeader; HandShakeHeader hsHeader; mySTL::auto_ptr<output_buffer> out(NEW_YS output_buffer); diff --git a/extra/yassl/src/make.bat b/extra/yassl/src/make.bat index 148427a6f41..dde305721a7 100644 --- a/extra/yassl/src/make.bat +++ b/extra/yassl/src/make.bat @@ -1,7 +1,7 @@ REM quick and dirty build file for testing different MSDEVs setlocal -set myFLAGS= /I../include /I../mySTL /I../taocrypt/include /W3 /c /ZI +set myFLAGS= /I../include /I../taocrypt/mySTL /I../taocrypt/include /W3 /c /ZI cl %myFLAGS% buffer.cpp cl %myFLAGS% cert_wrapper.cpp diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp index 70944831884..f281b81a24a 100644 --- a/extra/yassl/src/socket_wrapper.cpp +++ b/extra/yassl/src/socket_wrapper.cpp @@ -63,7 +63,7 @@ namespace yaSSL { Socket::Socket(socket_t s) - : socket_(s), wouldBlock_(false), blocking_(false) + : socket_(s), wouldBlock_(false), nonBlocking_(false) {} @@ -148,8 +148,8 @@ uint Socket::receive(byte* buf, unsigned int sz, int flags) if (recvd == -1) { if (get_lastError() == SOCKET_EWOULDBLOCK || get_lastError() == SOCKET_EAGAIN) { - wouldBlock_ = true; - blocking_ = true; // socket can block, only way to tell for win32 + wouldBlock_ = true; // would have blocked this time only + nonBlocking_ = true; // socket nonblocking, win32 only way to tell return 0; } } @@ -191,9 +191,9 @@ bool Socket::WouldBlock() const } -bool Socket::IsBlocking() const +bool Socket::IsNonBlocking() const { - return blocking_; + return nonBlocking_; } diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index a008ea7228b..aa98465069c 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -122,7 +122,7 @@ int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) EVP_BytesToKey(info.name, "MD5", info.iv, (byte*)password, passwordSz, 1, key, iv); - STL::auto_ptr<BulkCipher> cipher; + mySTL::auto_ptr<BulkCipher> cipher; if (strncmp(info.name, "DES-CBC", 7) == 0) cipher.reset(NEW_YS DES); else if (strncmp(info.name, "DES-EDE3-CBC", 13) == 0) @@ -138,7 +138,7 @@ int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) return SSL_BAD_FILE; } cipher->set_decryptKey(key, info.iv); - STL::auto_ptr<x509> newx(NEW_YS x509(x->get_length())); + mySTL::auto_ptr<x509> newx(NEW_YS x509(x->get_length())); cipher->decrypt(newx->use_buffer(), x->get_buffer(), x->get_length()); ysDelete(x); @@ -184,10 +184,22 @@ SSL_METHOD* TLSv1_client_method() } +SSL_METHOD* TLSv1_1_server_method() +{ + return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2)); +} + + +SSL_METHOD* TLSv1_1_client_method() +{ + return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2)); +} + + SSL_METHOD* SSLv23_server_method() { // compatibility only, no version 2 support, but does SSL 3 and TLS 1 - return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,1), true); + return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2), true); } @@ -196,7 +208,7 @@ SSL_METHOD* SSLv23_client_method() // compatibility only, no version 2 support, but does SSL 3 and TLS 1 // though it sends TLS1 hello not SSLv2 so SSLv3 only servers will decline // TODO: maybe add support to send SSLv2 hello ??? - return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,1), true); + return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2), true); } @@ -407,7 +419,6 @@ int SSL_shutdown(SSL* ssl) Alert alert(warning, close_notify); sendAlert(*ssl, alert); ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true); - ssl->useSocket().closeSocket(); GetErrors().Remove(); @@ -415,8 +426,21 @@ int SSL_shutdown(SSL* ssl) } +/* on by default but allow user to turn off */ +long SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long mode) +{ + if (mode == SSL_SESS_CACHE_OFF) + ctx->SetSessionCacheOff(); + + return SSL_SUCCESS; +} + + SSL_SESSION* SSL_get_session(SSL* ssl) { + if (ssl->getSecurity().GetContext()->GetSessionCacheOff()) + return 0; + return GetSessions().lookup( ssl->getSecurity().get_connection().sessionID_); } @@ -424,6 +448,9 @@ SSL_SESSION* SSL_get_session(SSL* ssl) int SSL_set_session(SSL* ssl, SSL_SESSION* session) { + if (ssl->getSecurity().GetContext()->GetSessionCacheOff()) + return SSL_FAILURE; + ssl->set_session(session); return SSL_SUCCESS; } @@ -512,6 +539,19 @@ int SSL_get_error(SSL* ssl, int /*previous*/) } + +/* turn on yaSSL zlib compression + returns 0 for success, else error (not built in) + only need to turn on for client, becuase server on by default if built in + but calling for server will tell you whether it's available or not +*/ +int SSL_set_compression(SSL* ssl) +{ + return ssl->SetCompression(); +} + + + X509* SSL_get_peer_certificate(SSL* ssl) { return ssl->getCrypto().get_certManager().get_peerX509(); @@ -918,7 +958,7 @@ void ERR_print_errors_fp(FILE* /*fp*/) char* ERR_error_string(unsigned long errNumber, char* buffer) { - static char* msg = "Please supply a buffer for error string"; + static char* msg = (char*) "Please supply a buffer for error string"; if (buffer) { SetErrorString(YasslError(errNumber), buffer); @@ -1359,6 +1399,56 @@ int SSL_pending(SSL* ssl) } +void SSL_CTX_set_default_passwd_cb(SSL_CTX* ctx, pem_password_cb cb) +{ + ctx->SetPasswordCb(cb); +} + + +int SSLeay_add_ssl_algorithms() // compatibility only +{ + return 1; +} + + +void ERR_remove_state(unsigned long) +{ + GetErrors().Remove(); +} + + +int ERR_GET_REASON(int l) +{ + return l & 0xfff; +} + + +unsigned long err_helper(bool peek = false) +{ + int ysError = GetErrors().Lookup(peek); + + // translate cert error for libcurl, it uses OpenSSL hex code + switch (ysError) { + case TaoCrypt::SIG_OTHER_E: + return CERTFICATE_ERROR; + break; + default : + return 0; + } +} + + +unsigned long ERR_peek_error() +{ + return err_helper(true); +} + + +unsigned long ERR_get_error() +{ + return err_helper(); +} + // functions for stunnel @@ -1477,13 +1567,6 @@ int SSL_pending(SSL* ssl) } - long SSL_CTX_set_session_cache_mode(SSL_CTX*, long) - { - // TDOD: - return SSL_SUCCESS; - } - - long SSL_CTX_set_timeout(SSL_CTX*, long) { // TDOD: @@ -1498,12 +1581,6 @@ int SSL_pending(SSL* ssl) } - void SSL_CTX_set_default_passwd_cb(SSL_CTX* ctx, pem_password_cb cb) - { - ctx->SetPasswordCb(cb); - } - - int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int) { // TDOD: @@ -1555,49 +1632,6 @@ int SSL_pending(SSL* ssl) } - int SSLeay_add_ssl_algorithms() // compatibility only - { - return 1; - } - - - void ERR_remove_state(unsigned long) - { - GetErrors().Remove(); - } - - - int ERR_GET_REASON(int l) - { - return l & 0xfff; - } - - unsigned long err_helper(bool peek = false) - { - int ysError = GetErrors().Lookup(peek); - - // translate cert error for libcurl, it uses OpenSSL hex code - switch (ysError) { - case TaoCrypt::SIG_OTHER_E: - return CERTFICATE_ERROR; - break; - default : - return 0; - } - } - - - unsigned long ERR_peek_error() - { - return err_helper(true); - } - - - unsigned long ERR_get_error() - { - return err_helper(); - } - // end stunnel needs diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp index 3531c0a2c74..25c595f40bc 100644 --- a/extra/yassl/src/yassl_error.cpp +++ b/extra/yassl/src/yassl_error.cpp @@ -133,6 +133,18 @@ void SetErrorString(YasslError error, char* buffer) strncpy(buffer, "protocl version mismatch", max); break; + case compress_error : + strncpy(buffer, "compression error", max); + break; + + case decompress_error : + strncpy(buffer, "decompression error", max); + break; + + case pms_version_error : + strncpy(buffer, "bad PreMasterSecret version error", max); + break; + // openssl errors case SSL_ERROR_WANT_READ : strncpy(buffer, "the read operation would block", max); diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index bd07f8b70f2..bf10c4b8932 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -87,7 +87,7 @@ void EncryptedPreMasterSecret::build(SSL& ssl) opaque tmp[SECRET_LEN]; memset(tmp, 0, sizeof(tmp)); ssl.getCrypto().get_random().Fill(tmp, SECRET_LEN); - ProtocolVersion pv = ssl.getSecurity().get_connection().version_; + ProtocolVersion pv = ssl.getSecurity().get_connection().chVersion_; tmp[0] = pv.major_; tmp[1] = pv.minor_; ssl.set_preMaster(tmp, SECRET_LEN); @@ -233,6 +233,10 @@ void EncryptedPreMasterSecret::read(SSL& ssl, input_buffer& input) rsa.decrypt(preMasterSecret, secret_, length_, ssl.getCrypto().get_random()); + ProtocolVersion pv = ssl.getSecurity().get_connection().chVersion_; + if (pv.major_ != preMasterSecret[0] || pv.minor_ != preMasterSecret[1]) + ssl.SetError(pms_version_error); // continue deriving for timing attack + ssl.set_preMaster(preMasterSecret, SECRET_LEN); ssl.makeMasterSecret(); } @@ -437,6 +441,7 @@ Parameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers, ProtocolVersion pv, bool haveDH) : entity_(ce) { pending_ = true; // suite not set yet + strncpy(cipher_name_, "NONE", 5); if (ciphers.setSuites_) { // use user set list suites_size_ = ciphers.suiteSz_; @@ -445,6 +450,7 @@ Parameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers, } else SetSuites(pv, ce == server_end && !haveDH); // defaults + } @@ -613,14 +619,18 @@ output_buffer& operator<<(output_buffer& output, const HandShakeHeader& hdr) void HandShakeHeader::Process(input_buffer& input, SSL& ssl) { ssl.verifyState(*this); + if (ssl.GetError()) return; const HandShakeFactory& hsf = ssl.getFactory().getHandShake(); mySTL::auto_ptr<HandShakeBase> hs(hsf.CreateObject(type_)); if (!hs.get()) { ssl.SetError(factory_error); return; } - hashHandShake(ssl, input, c24to32(length_)); + uint len = c24to32(length_); + hashHandShake(ssl, input, len); + + hs->set_length(len); input >> *hs; hs->Process(input, ssl); } @@ -849,11 +859,17 @@ void Alert::Process(input_buffer& input, SSL& ssl) opaque mac[SHA_LEN]; input.read(mac, digestSz); + if (ssl.getSecurity().get_parms().cipher_type_ == block) { + int ivExtra = 0; opaque fill; - int padSz = ssl.getSecurity().get_parms().encrypt_size_ - aSz - - digestSz; + + if (ssl.isTLSv1_1()) + ivExtra = ssl.getCrypto().get_cipher().get_blockSize(); + int padSz = ssl.getSecurity().get_parms().encrypt_size_ - ivExtra - + aSz - digestSz; for (int i = 0; i < padSz; i++) fill = input[AUTO]; + } // verify if (memcmp(mac, verify, digestSz)) { @@ -879,9 +895,13 @@ Data::Data(uint16 len, opaque* b) {} -Data::Data(uint16 len, const opaque* w) - : length_(len), buffer_(0), write_buffer_(w) -{} +void Data::SetData(uint16 len, const opaque* buffer) +{ + assert(write_buffer_ == 0); + + length_ = len; + write_buffer_ = buffer; +} input_buffer& Data::set(input_buffer& in) { @@ -907,17 +927,12 @@ uint16 Data::get_length() const } -const opaque* Data::get_buffer() const -{ - return write_buffer_; -} - - void Data::set_length(uint16 l) { length_ = l; } + opaque* Data::set_buffer() { return buffer_; @@ -937,27 +952,42 @@ void Data::Process(input_buffer& input, SSL& ssl) { int msgSz = ssl.getSecurity().get_parms().encrypt_size_; int pad = 0, padByte = 0; + int ivExtra = 0; + if (ssl.getSecurity().get_parms().cipher_type_ == block) { - pad = *(input.get_buffer() + input.get_current() + msgSz - 1); + if (ssl.isTLSv1_1()) // IV + ivExtra = ssl.getCrypto().get_cipher().get_blockSize(); + pad = *(input.get_buffer() + input.get_current() + msgSz -ivExtra - 1); padByte = 1; } int digestSz = ssl.getCrypto().get_digest().get_digestSize(); - int dataSz = msgSz - digestSz - pad - padByte; + int dataSz = msgSz - ivExtra - digestSz - pad - padByte; opaque verify[SHA_LEN]; + const byte* rawData = input.get_buffer() + input.get_current(); + // read data - if (dataSz) { + if (dataSz) { // could be compressed + if (ssl.CompressionOn()) { + input_buffer tmp; + if (DeCompress(input, dataSz, tmp) == -1) { + ssl.SetError(decompress_error); + return; + } + ssl.addData(NEW_YS input_buffer(tmp.get_size(), + tmp.get_buffer(), tmp.get_size())); + } + else { input_buffer* data; ssl.addData(data = NEW_YS input_buffer(dataSz)); input.read(data->get_buffer(), dataSz); data->add_size(dataSz); + } if (ssl.isTLS()) - TLS_hmac(ssl, verify, data->get_buffer(), dataSz, application_data, - true); + TLS_hmac(ssl, verify, rawData, dataSz, application_data, true); else - hmac(ssl, verify, data->get_buffer(), dataSz, application_data, - true); + hmac(ssl, verify, rawData, dataSz, application_data, true); } // read mac and fill @@ -1220,6 +1250,13 @@ void ServerHello::Process(input_buffer&, SSL& ssl) if (ssl.isTLS() && server_version_.minor_ < 1) // downgrade to SSLv3 ssl.useSecurity().use_connection().TurnOffTLS(); + else if (ssl.isTLSv1_1() && server_version_.minor_ == 1) + // downdrage to TLSv1 + ssl.useSecurity().use_connection().TurnOffTLS1_1(); + } + else if (ssl.isTLSv1_1() && server_version_.minor_ < 2) { + ssl.SetError(badVersion_error); + return; } else if (ssl.isTLS() && server_version_.minor_ < 1) { ssl.SetError(badVersion_error); @@ -1252,6 +1289,10 @@ void ServerHello::Process(input_buffer&, SSL& ssl) ssl.useSecurity().set_resuming(false); ssl.useLog().Trace("server denied resumption"); } + + if (ssl.CompressionOn() && !compression_method_) + ssl.UnSetCompression(); // server isn't supporting yaSSL zlib request + ssl.useStates().useClient() = serverHelloComplete; } @@ -1263,8 +1304,9 @@ ServerHello::ServerHello() } -ServerHello::ServerHello(ProtocolVersion pv) - : server_version_(pv) +ServerHello::ServerHello(ProtocolVersion pv, bool useCompression) + : server_version_(pv), + compression_method_(useCompression ? zlib : no_compression) { memset(random_, 0, RAN_LEN); memset(session_id_, 0, ID_LEN); @@ -1341,6 +1383,8 @@ opaque* ClientKeyBase::get_clientKey() const // input operator for Client Hello input_buffer& operator>>(input_buffer& input, ClientHello& hello) { + uint begin = input.get_current(); // could have extensions at end + // Protocol hello.client_version_.major_ = input[AUTO]; hello.client_version_.minor_ = input[AUTO]; @@ -1361,8 +1405,19 @@ input_buffer& operator>>(input_buffer& input, ClientHello& hello) // Compression hello.comp_len_ = input[AUTO]; - while (hello.comp_len_--) // ignore for now - hello.compression_methods_ = CompressionMethod(input[AUTO]); + hello.compression_methods_ = no_compression; + while (hello.comp_len_--) { + CompressionMethod cm = CompressionMethod(input[AUTO]); + if (cm == zlib) + hello.compression_methods_ = zlib; + } + + uint read = input.get_current() - begin; + uint expected = hello.get_length(); + + // ignore client hello extensions for now + if (read < expected) + input.set_current(input.get_current() + expected - read); return input; } @@ -1400,6 +1455,13 @@ output_buffer& operator<<(output_buffer& output, const ClientHello& hello) // Client Hello processing handler void ClientHello::Process(input_buffer&, SSL& ssl) { + // store version for pre master secret + ssl.useSecurity().use_connection().chVersion_ = client_version_; + + if (client_version_.major_ != 3) { + ssl.SetError(badVersion_error); + return; + } if (ssl.GetMultiProtocol()) { // SSLv23 support if (ssl.isTLS() && client_version_.minor_ < 1) { // downgrade to SSLv3 @@ -1407,20 +1469,29 @@ void ClientHello::Process(input_buffer&, SSL& ssl) ProtocolVersion pv = ssl.getSecurity().get_connection().version_; ssl.useSecurity().use_parms().SetSuites(pv); // reset w/ SSL suites } + else if (ssl.isTLSv1_1() && client_version_.minor_ == 1) + // downgrade to TLSv1, but use same suites + ssl.useSecurity().use_connection().TurnOffTLS1_1(); + } + else if (ssl.isTLSv1_1() && client_version_.minor_ < 2) { + ssl.SetError(badVersion_error); + return; } else if (ssl.isTLS() && client_version_.minor_ < 1) { ssl.SetError(badVersion_error); return; } - else if (!ssl.isTLS() && (client_version_.major_ == 3 && - client_version_.minor_ >= 1)) { + else if (!ssl.isTLS() && client_version_.minor_ >= 1) { ssl.SetError(badVersion_error); return; } + ssl.set_random(random_, client_end); while (id_len_) { // trying to resume - SSL_SESSION* session = GetSessions().lookup(session_id_); + SSL_SESSION* session = 0; + if (!ssl.getSecurity().GetContext()->GetSessionCacheOff()) + session = GetSessions().lookup(session_id_); if (!session) { ssl.useLog().Trace("session lookup failed"); break; @@ -1444,6 +1515,9 @@ void ClientHello::Process(input_buffer&, SSL& ssl) ssl.matchSuite(cipher_suites_, suite_len_); ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]); + if (compression_methods_ == zlib) + ssl.SetCompression(); + ssl.useStates().useServer() = clientHelloComplete; } @@ -1478,8 +1552,9 @@ ClientHello::ClientHello() } -ClientHello::ClientHello(ProtocolVersion pv) - : client_version_(pv) +ClientHello::ClientHello(ProtocolVersion pv, bool useCompression) + : client_version_(pv), + compression_methods_(useCompression ? zlib : no_compression) { memset(random_, 0, RAN_LEN); } @@ -1943,8 +2018,13 @@ void Finished::Process(input_buffer& input, SSL& ssl) int digestSz = ssl.getCrypto().get_digest().get_digestSize(); input.read(mac, digestSz); + uint ivExtra = 0; + if (ssl.getSecurity().get_parms().cipher_type_ == block) + if (ssl.isTLSv1_1()) + ivExtra = ssl.getCrypto().get_cipher().get_blockSize(); + opaque fill; - int padSz = ssl.getSecurity().get_parms().encrypt_size_ - + int padSz = ssl.getSecurity().get_parms().encrypt_size_ - ivExtra - HANDSHAKE_HEADER - finishedSz - digestSz; for (int i = 0; i < padSz; i++) fill = input[AUTO]; @@ -2018,7 +2098,9 @@ void clean(volatile opaque* p, uint sz, RandomPool& ran) Connection::Connection(ProtocolVersion v, RandomPool& ran) : pre_master_secret_(0), sequence_number_(0), peer_sequence_number_(0), pre_secret_len_(0), send_server_key_(false), master_clean_(false), - TLS_(v.major_ >= 3 && v.minor_ >= 1), version_(v), random_(ran) + TLS_(v.major_ >= 3 && v.minor_ >= 1), + TLSv1_1_(v.major_ >= 3 && v.minor_ >= 2), compression_(false), + version_(v), random_(ran) { memset(sessionID_, 0, sizeof(sessionID_)); } @@ -2043,6 +2125,13 @@ void Connection::TurnOffTLS() } +void Connection::TurnOffTLS1_1() +{ + TLSv1_1_ = false; + version_.minor_ = 1; +} + + // wipeout master secret void Connection::CleanMaster() { diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index 5288acb2bcd..1a407ca8ba5 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -38,6 +38,11 @@ #endif +#ifdef HAVE_LIBZ + #include "zlib.h" +#endif + + #ifdef YASSL_PURE_C void* operator new(size_t sz, yaSSL::new_t) @@ -727,6 +732,32 @@ void SSL::set_preMaster(const opaque* pre, uint sz) } +// set yaSSL zlib type compression +int SSL::SetCompression() +{ +#ifdef HAVE_LIBZ + secure_.use_connection().compression_ = true; + return 0; +#else + return -1; // not built in +#endif +} + + +// unset yaSSL zlib type compression +void SSL::UnSetCompression() +{ + secure_.use_connection().compression_ = false; +} + + +// is yaSSL zlib compression on +bool SSL::CompressionOn() const +{ + return secure_.get_connection().compression_; +} + + // store master secret void SSL::set_masterSecret(const opaque* sec) { @@ -1109,6 +1140,11 @@ void SSL::verifyState(const RecordLayerHeader& rlHeader) { if (GetError()) return; + if (rlHeader.version_.major_ != 3 || rlHeader.version_.minor_ > 2) { + SetError(badVersion_error); + return; + } + if (states_.getRecord() == recordNotReady || (rlHeader.type_ == application_data && // data and handshake states_.getHandShake() != handShakeReady) ) // isn't complete yet @@ -1247,6 +1283,9 @@ void SSL::matchSuite(const opaque* peer, uint length) void SSL::set_session(SSL_SESSION* s) { + if (getSecurity().GetContext()->GetSessionCacheOff()) + return; + if (s && GetSessions().lookup(s->GetID(), &secure_.use_resume())) { secure_.set_resuming(true); crypto_.use_certManager().setPeerX509(s->GetPeerX509()); @@ -1344,6 +1383,12 @@ bool SSL::isTLS() const } +bool SSL::isTLSv1_1() const +{ + return secure_.get_connection().TLSv1_1_; +} + + void SSL::addData(input_buffer* data) { buffers_.useData().push_back(data); @@ -1703,7 +1748,7 @@ bool SSL_METHOD::multipleProtocol() const SSL_CTX::SSL_CTX(SSL_METHOD* meth) : method_(meth), certificate_(0), privateKey_(0), passwordCb_(0), - userData_(0) + userData_(0), sessionCacheOff_(false) {} @@ -1784,12 +1829,24 @@ void* SSL_CTX::GetUserData() const } +bool SSL_CTX::GetSessionCacheOff() const +{ + return sessionCacheOff_; +} + + void SSL_CTX::SetUserData(void* data) { userData_ = data; } +void SSL_CTX::SetSessionCacheOff() +{ + sessionCacheOff_ = true; +} + + void SSL_CTX::setVerifyPeer() { method_->setVerifyPeer(); @@ -2312,9 +2369,110 @@ ASN1_STRING* StringHolder::GetString() } +#ifdef HAVE_LIBZ + + void* myAlloc(void* /* opaque */, unsigned int item, unsigned int size) + { + return NEW_YS unsigned char[item * size]; + } + + + void myFree(void* /* opaque */, void* memory) + { + unsigned char* ptr = static_cast<unsigned char*>(memory); + yaSSL::ysArrayDelete(ptr); + } + + + // put size in front of compressed data + int Compress(const byte* in, int sz, input_buffer& buffer) + { + byte tmp[LENGTH_SZ]; + z_stream c_stream; /* compression stream */ + + buffer.allocate(sz + sizeof(uint16) + COMPRESS_EXTRA); + + c_stream.zalloc = myAlloc; + c_stream.zfree = myFree; + c_stream.opaque = (voidpf)0; + + c_stream.next_in = const_cast<byte*>(in); + c_stream.avail_in = sz; + c_stream.next_out = buffer.get_buffer() + sizeof(tmp); + c_stream.avail_out = buffer.get_capacity() - sizeof(tmp); + + if (deflateInit(&c_stream, 8) != Z_OK) return -1; + int err = deflate(&c_stream, Z_FINISH); + deflateEnd(&c_stream); + if (err != Z_OK && err != Z_STREAM_END) return -1; + + c16toa(sz, tmp); + memcpy(buffer.get_buffer(), tmp, sizeof(tmp)); + buffer.add_size(c_stream.total_out + sizeof(tmp)); + + return 0; + } + + + // get uncompressed size in front + int DeCompress(input_buffer& in, int sz, input_buffer& out) + { + byte tmp[LENGTH_SZ]; + + in.read(tmp, sizeof(tmp)); + + uint16 len; + ato16(tmp, len); + + out.allocate(len); + + z_stream d_stream; /* decompression stream */ + + d_stream.zalloc = myAlloc; + d_stream.zfree = myFree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = in.get_buffer() + in.get_current(); + d_stream.avail_in = sz - sizeof(tmp); + d_stream.next_out = out.get_buffer(); + d_stream.avail_out = out.get_capacity(); + + if (inflateInit(&d_stream) != Z_OK) return -1; + int err = inflate(&d_stream, Z_FINISH); + inflateEnd(&d_stream); + if (err != Z_OK && err != Z_STREAM_END) return -1; + + out.add_size(d_stream.total_out); + in.set_current(in.get_current() + sz - sizeof(tmp)); + + return 0; + } + + +#else // LIBZ + + // these versions should never get called + int Compress(const byte* in, int sz, input_buffer& buffer) + { + assert(0); + return -1; + } + + + int DeCompress(input_buffer& in, int sz, input_buffer& out) + { + assert(0); + return -1; + } + + +#endif // LIBZ + + } // namespace + extern "C" void yaSSL_CleanUp() { TaoCrypt::CleanUp(); diff --git a/extra/yassl/taocrypt/benchmark/Makefile.am b/extra/yassl/taocrypt/benchmark/Makefile.am index a5b1713427c..674406d8ad6 100644 --- a/extra/yassl/taocrypt/benchmark/Makefile.am +++ b/extra/yassl/taocrypt/benchmark/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../mySTL +INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../mySTL bin_PROGRAMS = benchmark benchmark_SOURCES = benchmark.cpp benchmark_LDADD = $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la diff --git a/extra/yassl/taocrypt/benchmark/benchmark.dsp b/extra/yassl/taocrypt/benchmark/benchmark.dsp index ed8fef316bb..878dc2b2783 100644 --- a/extra/yassl/taocrypt/benchmark/benchmark.dsp +++ b/extra/yassl/taocrypt/benchmark/benchmark.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\include" /I "..\..\mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\include" /I "..\mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -65,7 +65,7 @@ LINK32=link.exe # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\..\mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/extra/yassl/taocrypt/benchmark/make.bat b/extra/yassl/taocrypt/benchmark/make.bat index 4ebe4b32417..bf1383f5e97 100644 --- a/extra/yassl/taocrypt/benchmark/make.bat +++ b/extra/yassl/taocrypt/benchmark/make.bat @@ -1,7 +1,7 @@ REM quick and dirty build file for testing different MSDEVs setlocal -set myFLAGS= /I../include /I../../mySTL /c /W3 /G6 /O2 +set myFLAGS= /I../include /I../mySTL /c /W3 /G6 /O2 cl %myFLAGS% benchmark.cpp diff --git a/extra/yassl/taocrypt/include/aes.hpp b/extra/yassl/taocrypt/include/aes.hpp index cb70f5c0e7e..5c53fc39411 100644 --- a/extra/yassl/taocrypt/include/aes.hpp +++ b/extra/yassl/taocrypt/include/aes.hpp @@ -34,6 +34,12 @@ #include "modes.hpp" +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_AES_ASM +#endif + + + namespace TaoCrypt { @@ -46,15 +52,14 @@ public: enum { BLOCK_SIZE = AES_BLOCK_SIZE }; AES(CipherDir DIR, Mode MODE) - : Mode_BASE(BLOCK_SIZE), dir_(DIR), mode_(MODE) {} + : Mode_BASE(BLOCK_SIZE, DIR, MODE) {} +#ifdef DO_AES_ASM void Process(byte*, const byte*, word32); +#endif void SetKey(const byte* key, word32 sz, CipherDir fake = ENCRYPTION); void SetIV(const byte* iv) { memcpy(r_, iv, BLOCK_SIZE); } private: - CipherDir dir_; - Mode mode_; - static const word32 rcon_[]; word32 rounds_; diff --git a/extra/yassl/taocrypt/include/algebra.hpp b/extra/yassl/taocrypt/include/algebra.hpp index 07fc405f093..9cfbcf06ece 100644 --- a/extra/yassl/taocrypt/include/algebra.hpp +++ b/extra/yassl/taocrypt/include/algebra.hpp @@ -75,7 +75,8 @@ public: typedef Integer Element; AbstractRing() : AbstractGroup() {m_mg.m_pRing = this;} - AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;} + AbstractRing(const AbstractRing &source) : AbstractGroup() + {m_mg.m_pRing = this;} AbstractRing& operator=(const AbstractRing &source) {return *this;} virtual bool IsUnit(const Element &a) const =0; diff --git a/extra/yassl/taocrypt/include/arc4.hpp b/extra/yassl/taocrypt/include/arc4.hpp index 05b0921f5a1..ddd5082f557 100644 --- a/extra/yassl/taocrypt/include/arc4.hpp +++ b/extra/yassl/taocrypt/include/arc4.hpp @@ -46,7 +46,6 @@ public: ARC4() {} void Process(byte*, const byte*, word32); - void AsmProcess(byte*, const byte*, word32); void SetKey(const byte*, word32); private: byte x_; @@ -55,6 +54,8 @@ private: ARC4(const ARC4&); // hide copy const ARC4 operator=(const ARC4&); // and assign + + void AsmProcess(byte*, const byte*, word32); }; } // namespace diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp index dbee54be6f1..1151f3c944e 100644 --- a/extra/yassl/taocrypt/include/asn.hpp +++ b/extra/yassl/taocrypt/include/asn.hpp @@ -34,7 +34,11 @@ #include "misc.hpp" #include "block.hpp" #include "error.hpp" -#include STL_LIST_FILE +#ifdef USE_SYS_STL + #include <list> +#else + #include "list.hpp" +#endif namespace STL = STL_NAMESPACE; diff --git a/extra/yassl/taocrypt/include/block.hpp b/extra/yassl/taocrypt/include/block.hpp index a931158a83d..0cf27d0b6b5 100644 --- a/extra/yassl/taocrypt/include/block.hpp +++ b/extra/yassl/taocrypt/include/block.hpp @@ -34,7 +34,12 @@ #include "misc.hpp" #include <string.h> // memcpy #include <stddef.h> // ptrdiff_t -#include STL_ALGORITHM_FILE + +#ifdef USE_SYS_STL + #include <algorithm> +#else + #include "algorithm.hpp" +#endif namespace STL = STL_NAMESPACE; diff --git a/extra/yassl/taocrypt/include/blowfish.hpp b/extra/yassl/taocrypt/include/blowfish.hpp index 40953624232..4d6ad1b034b 100644 --- a/extra/yassl/taocrypt/include/blowfish.hpp +++ b/extra/yassl/taocrypt/include/blowfish.hpp @@ -32,12 +32,21 @@ #include "misc.hpp" #include "modes.hpp" -#include STL_ALGORITHM_FILE +#ifdef USE_SYS_STL + #include <algorithm> +#else + #include "algorithm.hpp" +#endif namespace STL = STL_NAMESPACE; +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_BLOWFISH_ASM +#endif + + namespace TaoCrypt { enum { BLOWFISH_BLOCK_SIZE = 8 }; @@ -49,15 +58,14 @@ public: enum { BLOCK_SIZE = BLOWFISH_BLOCK_SIZE, ROUNDS = 16 }; Blowfish(CipherDir DIR, Mode MODE) - : Mode_BASE(BLOCK_SIZE), dir_(DIR), mode_(MODE) {} + : Mode_BASE(BLOCK_SIZE, DIR, MODE) {} +#ifdef DO_BLOWFISH_ASM void Process(byte*, const byte*, word32); +#endif void SetKey(const byte* key, word32 sz, CipherDir fake = ENCRYPTION); void SetIV(const byte* iv) { memcpy(r_, iv, BLOCK_SIZE); } private: - CipherDir dir_; - Mode mode_; - static const word32 p_init_[ROUNDS + 2]; static const word32 s_init_[4 * 256]; diff --git a/extra/yassl/taocrypt/include/des.hpp b/extra/yassl/taocrypt/include/des.hpp index 48bb1e9119d..19273821f98 100644 --- a/extra/yassl/taocrypt/include/des.hpp +++ b/extra/yassl/taocrypt/include/des.hpp @@ -34,6 +34,12 @@ #include "misc.hpp" #include "modes.hpp" + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_DES_ASM +#endif + + namespace TaoCrypt { @@ -53,13 +59,9 @@ protected: class DES : public Mode_BASE, public BasicDES { public: DES(CipherDir DIR, Mode MODE) - : Mode_BASE(DES_BLOCK_SIZE), dir_(DIR), mode_(MODE) {} + : Mode_BASE(DES_BLOCK_SIZE, DIR, MODE) {} - void Process(byte*, const byte*, word32); private: - CipherDir dir_; - Mode mode_; - void ProcessAndXorBlock(const byte*, const byte*, byte*) const; DES(const DES&); // hide copy @@ -71,14 +73,10 @@ private: class DES_EDE2 : public Mode_BASE { public: DES_EDE2(CipherDir DIR, Mode MODE) - : Mode_BASE(DES_BLOCK_SIZE), dir_(DIR), mode_(MODE) {} + : Mode_BASE(DES_BLOCK_SIZE, DIR, MODE) {} void SetKey(const byte*, word32, CipherDir dir); - void Process(byte*, const byte*, word32); private: - CipherDir dir_; - Mode mode_; - BasicDES des1_; BasicDES des2_; @@ -94,15 +92,14 @@ private: class DES_EDE3 : public Mode_BASE { public: DES_EDE3(CipherDir DIR, Mode MODE) - : Mode_BASE(DES_BLOCK_SIZE), dir_(DIR), mode_(MODE) {} + : Mode_BASE(DES_BLOCK_SIZE, DIR, MODE) {} void SetKey(const byte*, word32, CipherDir dir); void SetIV(const byte* iv) { memcpy(r_, iv, DES_BLOCK_SIZE); } +#ifdef DO_DES_ASM void Process(byte*, const byte*, word32); +#endif private: - CipherDir dir_; - Mode mode_; - BasicDES des1_; BasicDES des2_; BasicDES des3_; diff --git a/extra/yassl/taocrypt/include/integer.hpp b/extra/yassl/taocrypt/include/integer.hpp index 70b4dc79e73..751c79102c4 100644 --- a/extra/yassl/taocrypt/include/integer.hpp +++ b/extra/yassl/taocrypt/include/integer.hpp @@ -45,7 +45,11 @@ #include "random.hpp" #include "file.hpp" #include <string.h> -#include STL_ALGORITHM_FILE +#ifdef USE_SYS_STL + #include <algorithm> +#else + #include "algorithm.hpp" +#endif #ifdef TAOCRYPT_X86ASM_AVAILABLE @@ -67,7 +71,8 @@ #endif // SSE2 intrinsics work in GCC 3.3 or later -#if defined(__SSE2__) && (__GNUC_MAJOR__ > 3 || __GNUC_MINOR__ > 2) +#if defined(__SSE2__) && (__GNUC__ == 4 || __GNUC_MAJOR__ > 3 || \ + __GNUC_MINOR__ > 2) #define SSE2_INTRINSICS_AVAILABLE #endif @@ -106,7 +111,6 @@ namespace TaoCrypt { #endif }; - template class TAOCRYPT_DLL AlignedAllocator<word>; typedef Block<word, AlignedAllocator<word> > AlignedWordBlock; #else typedef WordBlock AlignedWordBlock; diff --git a/extra/yassl/taocrypt/include/md5.hpp b/extra/yassl/taocrypt/include/md5.hpp index 30d14d54fbf..f607a922155 100644 --- a/extra/yassl/taocrypt/include/md5.hpp +++ b/extra/yassl/taocrypt/include/md5.hpp @@ -31,6 +31,11 @@ #include "hash.hpp" + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_MD5_ASM +#endif + namespace TaoCrypt { @@ -49,7 +54,9 @@ public: MD5(const MD5&); MD5& operator= (const MD5&); +#ifdef DO_MD5_ASM void Update(const byte*, word32); +#endif void Init(); void Swap(MD5&); diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp index 3d2d4c62466..cc20b60d528 100644 --- a/extra/yassl/taocrypt/include/misc.hpp +++ b/extra/yassl/taocrypt/include/misc.hpp @@ -151,6 +151,17 @@ void CleanUp(); #endif +#ifdef TAOCRYPT_X86ASM_AVAILABLE + bool HaveCpuId(); + bool IsPentium(); + void CpuId(word32 input, word32 *output); + + extern bool isMMX; +#endif + + + + // Turn on ia32 ASM for Ciphers and Message Digests // Seperate define since these are more complex, use member offsets // and user may want to turn off while leaving Big Integer optos on @@ -200,17 +211,9 @@ void CleanUp(); #ifdef USE_SYS_STL // use system STL - #define STL_VECTOR_FILE <vector> - #define STL_LIST_FILE <list> - #define STL_ALGORITHM_FILE <algorithm> - #define STL_MEMORY_FILE <memory> #define STL_NAMESPACE std #else // use mySTL - #define STL_VECTOR_FILE "vector.hpp" - #define STL_LIST_FILE "list.hpp" - #define STL_ALGORITHM_FILE "algorithm.hpp" - #define STL_MEMORY_FILE "memory.hpp" #define STL_NAMESPACE mySTL #endif diff --git a/extra/yassl/taocrypt/include/modes.hpp b/extra/yassl/taocrypt/include/modes.hpp index 65b7318661e..d77f855385c 100644 --- a/extra/yassl/taocrypt/include/modes.hpp +++ b/extra/yassl/taocrypt/include/modes.hpp @@ -38,6 +38,7 @@ namespace TaoCrypt { enum Mode { ECB, CBC }; + // BlockCipher abstraction template<CipherDir DIR, class T, Mode MODE> class BlockCipher { @@ -63,14 +64,16 @@ class Mode_BASE : public virtual_base { public: enum { MaxBlockSz = 16 }; - explicit Mode_BASE(int sz) + explicit Mode_BASE(int sz, CipherDir dir, Mode mode) : blockSz_(sz), reg_(reinterpret_cast<byte*>(r_)), - tmp_(reinterpret_cast<byte*>(t_)) + tmp_(reinterpret_cast<byte*>(t_)), dir_(dir), mode_(mode) { assert(sz <= MaxBlockSz); } virtual ~Mode_BASE() {} + virtual void Process(byte*, const byte*, word32); + void SetIV(const byte* iv) { memcpy(reg_, iv, blockSz_); } protected: int blockSz_; @@ -80,6 +83,9 @@ protected: word32 r_[MaxBlockSz / sizeof(word32)]; // align reg_ on word32 word32 t_[MaxBlockSz / sizeof(word32)]; // align tmp_ on word32 + CipherDir dir_; + Mode mode_; + void ECB_Process(byte*, const byte*, word32); void CBC_Encrypt(byte*, const byte*, word32); void CBC_Decrypt(byte*, const byte*, word32); @@ -92,6 +98,18 @@ private: }; +inline void Mode_BASE::Process(byte* out, const byte* in, word32 sz) +{ + if (mode_ == ECB) + ECB_Process(out, in, sz); + else if (mode_ == CBC) + if (dir_ == ENCRYPTION) + CBC_Encrypt(out, in, sz); + else + CBC_Decrypt(out, in, sz); +} + + // ECB Process blocks inline void Mode_BASE::ECB_Process(byte* out, const byte* in, word32 sz) { diff --git a/extra/yassl/taocrypt/include/ripemd.hpp b/extra/yassl/taocrypt/include/ripemd.hpp index 2e594b7604d..5d443769662 100644 --- a/extra/yassl/taocrypt/include/ripemd.hpp +++ b/extra/yassl/taocrypt/include/ripemd.hpp @@ -31,6 +31,11 @@ #include "hash.hpp" + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_RIPEMD_ASM +#endif + namespace TaoCrypt { @@ -49,7 +54,9 @@ public: RIPEMD160(const RIPEMD160&); RIPEMD160& operator= (const RIPEMD160&); +#ifdef DO_RIPEMD_ASM void Update(const byte*, word32); +#endif void Init(); void Swap(RIPEMD160&); private: diff --git a/extra/yassl/taocrypt/include/rsa.hpp b/extra/yassl/taocrypt/include/rsa.hpp index 1b531b9d0c0..c33e21b76a3 100644 --- a/extra/yassl/taocrypt/include/rsa.hpp +++ b/extra/yassl/taocrypt/include/rsa.hpp @@ -239,7 +239,8 @@ bool RSA_Encryptor<Pad>::SSL_Verify(const byte* message, word32 sz, const byte* sig) { ByteBlock plain(PK_Lengths(key_.GetModulus()).FixedMaxPlaintextLength()); - SSL_Decrypt(key_, sig, plain.get_buffer()); + if (SSL_Decrypt(key_, sig, plain.get_buffer()) != sz) + return false; // not right justified or bad padding if ( (memcmp(plain.get_buffer(), message, sz)) == 0) return true; diff --git a/extra/yassl/taocrypt/include/sha.hpp b/extra/yassl/taocrypt/include/sha.hpp index 2d65932dc17..510c516b1a4 100644 --- a/extra/yassl/taocrypt/include/sha.hpp +++ b/extra/yassl/taocrypt/include/sha.hpp @@ -31,6 +31,11 @@ #include "hash.hpp" + +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_SHA_ASM +#endif + namespace TaoCrypt { @@ -46,7 +51,9 @@ public: word32 getDigestSize() const { return DIGEST_SIZE; } word32 getPadSize() const { return PAD_SIZE; } +#ifdef DO_SHA_ASM void Update(const byte* data, word32 len); +#endif void Init(); SHA(const SHA&); diff --git a/extra/yassl/taocrypt/include/twofish.hpp b/extra/yassl/taocrypt/include/twofish.hpp index ba144d2defb..8cad4923262 100644 --- a/extra/yassl/taocrypt/include/twofish.hpp +++ b/extra/yassl/taocrypt/include/twofish.hpp @@ -32,12 +32,20 @@ #include "misc.hpp" #include "modes.hpp" -#include STL_ALGORITHM_FILE +#ifdef USE_SYS_STL + #include <algorithm> +#else + #include "algorithm.hpp" +#endif namespace STL = STL_NAMESPACE; +#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) + #define DO_TWOFISH_ASM +#endif + namespace TaoCrypt { enum { TWOFISH_BLOCK_SIZE = 16 }; @@ -49,15 +57,14 @@ public: enum { BLOCK_SIZE = TWOFISH_BLOCK_SIZE }; Twofish(CipherDir DIR, Mode MODE) - : Mode_BASE(BLOCK_SIZE), dir_(DIR), mode_(MODE) {} + : Mode_BASE(BLOCK_SIZE, DIR, MODE) {} +#ifdef DO_TWOFISH_ASM void Process(byte*, const byte*, word32); +#endif void SetKey(const byte* key, word32 sz, CipherDir fake = ENCRYPTION); void SetIV(const byte* iv) { memcpy(r_, iv, BLOCK_SIZE); } private: - CipherDir dir_; - Mode mode_; - static const byte q_[2][256]; static const word32 mds_[4][256]; diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am index 6d02a625275..61032d4c381 100644 --- a/extra/yassl/taocrypt/src/Makefile.am +++ b/extra/yassl/taocrypt/src/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../mySTL +INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../mySTL noinst_LTLIBRARIES = libtaocrypt.la diff --git a/extra/yassl/taocrypt/src/aes.cpp b/extra/yassl/taocrypt/src/aes.cpp index 574a88a736c..2940f06c074 100644 --- a/extra/yassl/taocrypt/src/aes.cpp +++ b/extra/yassl/taocrypt/src/aes.cpp @@ -34,33 +34,19 @@ #include "aes.hpp" -#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) - #define DO_AES_ASM -#endif - - namespace TaoCrypt { -#if !defined(DO_AES_ASM) - -// Generic Version -void AES::Process(byte* out, const byte* in, word32 sz) -{ - if (mode_ == ECB) - ECB_Process(out, in, sz); - else if (mode_ == CBC) - if (dir_ == ENCRYPTION) - CBC_Encrypt(out, in, sz); - else - CBC_Decrypt(out, in, sz); -} - -#else +#if defined(DO_AES_ASM) // ia32 optimized version void AES::Process(byte* out, const byte* in, word32 sz) { + if (!isMMX) { + Mode_BASE::Process(out, in, sz); + return; + } + word32 blocks = sz / BLOCK_SIZE; if (mode_ == ECB) diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp index 375cd6cd524..76c4e99323d 100644 --- a/extra/yassl/taocrypt/src/algebra.cpp +++ b/extra/yassl/taocrypt/src/algebra.cpp @@ -29,7 +29,11 @@ #include "runtime.hpp" #include "algebra.hpp" -#include STL_VECTOR_FILE +#ifdef USE_SYS_STL + #include <vector> +#else + #include "vector.hpp" +#endif namespace STL = STL_NAMESPACE; diff --git a/extra/yassl/taocrypt/src/arc4.cpp b/extra/yassl/taocrypt/src/arc4.cpp index ea1e084014c..90b5170c59e 100644 --- a/extra/yassl/taocrypt/src/arc4.cpp +++ b/extra/yassl/taocrypt/src/arc4.cpp @@ -80,12 +80,18 @@ inline unsigned int MakeByte(word32& x, word32& y, byte* s) } // namespace -#ifndef DO_ARC4_ASM void ARC4::Process(byte* out, const byte* in, word32 length) { if (length == 0) return; +#ifdef DO_ARC4_ASM + if (isMMX) { + AsmProcess(out, in, length); + return; + } +#endif + byte *const s = state_; word32 x = x_; word32 y = y_; @@ -100,13 +106,16 @@ void ARC4::Process(byte* out, const byte* in, word32 length) y_ = y; } -#else // DO_ARC4_ASM +#ifdef DO_ARC4_ASM + #ifdef _MSC_VER __declspec(naked) +#else + __attribute__ ((noinline)) #endif -void ARC4::Process(byte* out, const byte* in, word32 length) +void ARC4::AsmProcess(byte* out, const byte* in, word32 length) { #ifdef __GNUC__ #define AS1(x) asm(#x); diff --git a/extra/yassl/taocrypt/src/blowfish.cpp b/extra/yassl/taocrypt/src/blowfish.cpp index 40ae1a17e6c..d736292fb19 100644 --- a/extra/yassl/taocrypt/src/blowfish.cpp +++ b/extra/yassl/taocrypt/src/blowfish.cpp @@ -37,34 +37,21 @@ -#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) - #define DO_BLOWFISH_ASM -#endif - namespace TaoCrypt { -#if !defined(DO_BLOWFISH_ASM) - -// Generic Version -void Blowfish::Process(byte* out, const byte* in, word32 sz) -{ - if (mode_ == ECB) - ECB_Process(out, in, sz); - else if (mode_ == CBC) - if (dir_ == ENCRYPTION) - CBC_Encrypt(out, in, sz); - else - CBC_Decrypt(out, in, sz); -} - -#else +#if defined(DO_BLOWFISH_ASM) // ia32 optimized version void Blowfish::Process(byte* out, const byte* in, word32 sz) { + if (!isMMX) { + Mode_BASE::Process(out, in, sz); + return; + } + word32 blocks = sz / BLOCK_SIZE; if (mode_ == ECB) diff --git a/extra/yassl/taocrypt/src/des.cpp b/extra/yassl/taocrypt/src/des.cpp index 2628e142bae..94428ac587e 100644 --- a/extra/yassl/taocrypt/src/des.cpp +++ b/extra/yassl/taocrypt/src/des.cpp @@ -34,16 +34,16 @@ #include "runtime.hpp" #include "des.hpp" -#include STL_ALGORITHM_FILE +#ifdef USE_SYS_STL + #include <algorithm> +#else + #include "algorithm.hpp" +#endif namespace STL = STL_NAMESPACE; -#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) - #define DO_DES_ASM -#endif - namespace TaoCrypt { @@ -357,18 +357,6 @@ void BasicDES::RawProcessBlock(word32& lIn, word32& rIn) const } -void DES::Process(byte* out, const byte* in, word32 sz) -{ - if (mode_ == ECB) - ECB_Process(out, in, sz); - else if (mode_ == CBC) - if (dir_ == ENCRYPTION) - CBC_Encrypt(out, in, sz); - else - CBC_Decrypt(out, in, sz); -} - - typedef BlockGetAndPut<word32, BigEndian> Block; @@ -386,17 +374,6 @@ void DES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const } -void DES_EDE2::Process(byte* out, const byte* in, word32 sz) -{ - if (mode_ == ECB) - ECB_Process(out, in, sz); - else if (mode_ == CBC) - if (dir_ == ENCRYPTION) - CBC_Encrypt(out, in, sz); - else - CBC_Decrypt(out, in, sz); -} - void DES_EDE2::SetKey(const byte* key, word32 sz, CipherDir dir) { des1_.SetKey(key, sz, dir); @@ -429,25 +406,16 @@ void DES_EDE3::SetKey(const byte* key, word32 sz, CipherDir dir) -#if !defined(DO_DES_ASM) - -// Generic Version -void DES_EDE3::Process(byte* out, const byte* in, word32 sz) -{ - if (mode_ == ECB) - ECB_Process(out, in, sz); - else if (mode_ == CBC) - if (dir_ == ENCRYPTION) - CBC_Encrypt(out, in, sz); - else - CBC_Decrypt(out, in, sz); -} - -#else +#if defined(DO_DES_ASM) // ia32 optimized version void DES_EDE3::Process(byte* out, const byte* in, word32 sz) { + if (!isMMX) { + Mode_BASE::Process(out, in, sz); + return; + } + word32 blocks = sz / DES_BLOCK_SIZE; if (mode_ == CBC) diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 500160cfe37..1ed69ce34dc 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -55,12 +55,15 @@ extern "C" word myUMULH(word, word); #pragma intrinsic (myUMULH) #endif +#ifdef __GNUC__ + #include <signal.h> + #include <setjmp.h> +#endif + #ifdef SSE2_INTRINSICS_AVAILABLE #ifdef __GNUC__ #include <xmmintrin.h> - #include <signal.h> - #include <setjmp.h> #ifdef TAOCRYPT_MEMALIGN_AVAILABLE #include <malloc.h> #else @@ -1015,44 +1018,20 @@ void Portable::Multiply8Bottom(word *R, const word *A, const word *B) // ************** x86 feature detection *************** -static bool s_sse2Enabled = true; - -static void CpuId(word32 input, word32 *output) -{ -#ifdef __GNUC__ - __asm__ - ( - // save ebx in case -fPIC is being used - "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" - : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d"(output[3]) - : "a" (input) - ); -#else - __asm - { - mov eax, input - cpuid - mov edi, output - mov [edi], eax - mov [edi+4], ebx - mov [edi+8], ecx - mov [edi+12], edx - } -#endif -} #ifdef SSE2_INTRINSICS_AVAILABLE + #ifndef _MSC_VER -static jmp_buf s_env; -static void SigIllHandler(int) -{ + static jmp_buf s_env; + static void SigIllHandler(int) + { longjmp(s_env, 1); -} + } #endif static bool HasSSE2() { - if (!s_sse2Enabled) + if (!IsPentium()) return false; word32 cpuid[4]; @@ -1081,23 +1060,22 @@ static bool HasSSE2() if (setjmp(s_env)) result = false; else - __asm __volatile ("xorps %xmm0, %xmm0"); + __asm __volatile ("xorpd %xmm0, %xmm0"); signal(SIGILL, oldHandler); return result; #endif } -#endif +#endif // SSE2_INTRINSICS_AVAILABLE + static bool IsP4() { - word32 cpuid[4]; - - CpuId(0, cpuid); - STL::swap(cpuid[2], cpuid[3]); - if (memcmp(cpuid+1, "GenuineIntel", 12) != 0) + if (!IsPentium()) return false; + word32 cpuid[4]; + CpuId(1, cpuid); return ((cpuid[0] >> 8) & 0xf) == 0xf; } @@ -1147,7 +1125,12 @@ static PMul s_pMul4, s_pMul8, s_pMul8B; static void SetPentiumFunctionPointers() { - if (IsP4()) + if (!IsPentium()) + { + s_pAdd = &Portable::Add; + s_pSub = &Portable::Subtract; + } + else if (IsP4()) { s_pAdd = &P4Optimized::Add; s_pSub = &P4Optimized::Subtract; @@ -1159,7 +1142,13 @@ static void SetPentiumFunctionPointers() } #ifdef SSE2_INTRINSICS_AVAILABLE - if (HasSSE2()) + if (!IsPentium()) + { + s_pMul4 = &Portable::Multiply4; + s_pMul8 = &Portable::Multiply8; + s_pMul8B = &Portable::Multiply8Bottom; + } + else if (HasSSE2()) { s_pMul4 = &P4Optimized::Multiply4; s_pMul8 = &P4Optimized::Multiply8; @@ -1177,11 +1166,6 @@ static void SetPentiumFunctionPointers() static const char s_RunAtStartupSetPentiumFunctionPointers = (SetPentiumFunctionPointers(), 0); -void DisableSSE2() -{ - s_sse2Enabled = false; - SetPentiumFunctionPointers(); -} class LowLevel : public PentiumOptimized { @@ -3984,6 +3968,9 @@ Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, template hword DivideThreeWordsByTwo<hword, Word>(hword*, hword, hword, Word*); #endif template word DivideThreeWordsByTwo<word, DWord>(word*, word, word, DWord*); +#ifdef SSE2_INTRINSICS_AVAILABLE +template class AlignedAllocator<word>; +#endif #endif diff --git a/extra/yassl/taocrypt/src/make.bat b/extra/yassl/taocrypt/src/make.bat index ecf7e8f8469..0aa1350f7d8 100644 --- a/extra/yassl/taocrypt/src/make.bat +++ b/extra/yassl/taocrypt/src/make.bat @@ -1,7 +1,7 @@ REM quick and dirty build file for testing different MSDEVs setlocal -set myFLAGS= /I../include /I../../mySTL /c /W3 /G6 /O2 +set myFLAGS= /I../include /I../mySTL /c /W3 /G6 /O2 cl %myFLAGS% aes.cpp cl %myFLAGS% aestables.cpp @@ -21,6 +21,7 @@ cl %myFLAGS% file.cpp cl %myFLAGS% hash.cpp cl %myFLAGS% integer.cpp cl %myFLAGS% md2.cpp +cl %myFLAGS% md4.cpp cl %myFLAGS% md5.cpp cl %myFLAGS% misc.cpp @@ -33,5 +34,5 @@ cl %myFLAGS% template_instnt.cpp cl %myFLAGS% tftables.cpp cl %myFLAGS% twofish.cpp -link.exe -lib /out:taocrypt.lib aes.obj aestables.obj algebra.obj arc4.obj asn.obj bftables.obj blowfish.obj coding.obj des.obj dh.obj dsa.obj file.obj hash.obj integer.obj md2.obj md5.obj misc.obj random.obj ripemd.obj rsa.obj sha.obj template_instnt.obj tftables.obj twofish.obj +link.exe -lib /out:taocrypt.lib aes.obj aestables.obj algebra.obj arc4.obj asn.obj bftables.obj blowfish.obj coding.obj des.obj dh.obj dsa.obj file.obj hash.obj integer.obj md2.obj md4.obj md5.obj misc.obj random.obj ripemd.obj rsa.obj sha.obj template_instnt.obj tftables.obj twofish.obj diff --git a/extra/yassl/taocrypt/src/md4.cpp b/extra/yassl/taocrypt/src/md4.cpp index 0dee8bf40cb..1efda04fbb8 100644 --- a/extra/yassl/taocrypt/src/md4.cpp +++ b/extra/yassl/taocrypt/src/md4.cpp @@ -28,7 +28,11 @@ #include "runtime.hpp" #include "md4.hpp" -#include STL_ALGORITHM_FILE +#ifdef USE_SYS_STL + #include <algorithm> +#else + #include "algorithm.hpp" +#endif namespace STL = STL_NAMESPACE; diff --git a/extra/yassl/taocrypt/src/md5.cpp b/extra/yassl/taocrypt/src/md5.cpp index 2bddc7fe308..bf485d11b95 100644 --- a/extra/yassl/taocrypt/src/md5.cpp +++ b/extra/yassl/taocrypt/src/md5.cpp @@ -28,15 +28,16 @@ #include "runtime.hpp" #include "md5.hpp" -#include STL_ALGORITHM_FILE +#ifdef USE_SYS_STL + #include <algorithm> +#else + #include "algorithm.hpp" +#endif namespace STL = STL_NAMESPACE; -#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) - #define DO_MD5_ASM -#endif namespace TaoCrypt { @@ -84,10 +85,17 @@ void MD5::Swap(MD5& other) } -// Update digest with data of size len, do in blocks +#ifdef DO_MD5_ASM + +// Update digest with data of size len void MD5::Update(const byte* data, word32 len) { - byte* local = (byte*)buffer_; + if (!isMMX) { + HASHwithTransform::Update(data, len); + return; + } + + byte* local = reinterpret_cast<byte*>(buffer_); // remove buffered data if possible if (buffLen_) { @@ -99,27 +107,14 @@ void MD5::Update(const byte* data, word32 len) len -= add; if (buffLen_ == BLOCK_SIZE) { - ByteReverseIf(local, local, BLOCK_SIZE, LittleEndianOrder); Transform(); AddLength(BLOCK_SIZE); buffLen_ = 0; } } - // do block size transforms or all at once for asm + // at once for asm if (buffLen_ == 0) { - #ifndef DO_MD5_ASM - while (len >= BLOCK_SIZE) { - memcpy(&local[0], data, BLOCK_SIZE); - - data += BLOCK_SIZE; - len -= BLOCK_SIZE; - - ByteReverseIf(local, local, BLOCK_SIZE, LittleEndianOrder); - Transform(); - AddLength(BLOCK_SIZE); - } - #else word32 times = len / BLOCK_SIZE; if (times) { AsmTransform(data, times); @@ -128,7 +123,6 @@ void MD5::Update(const byte* data, word32 len) len -= add; data += add; } - #endif } // cache any data left @@ -139,7 +133,6 @@ void MD5::Update(const byte* data, word32 len) } -#ifdef DO_MD5_ASM /* diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp index 084a263a4ae..7ab05582e95 100644 --- a/extra/yassl/taocrypt/src/misc.cpp +++ b/extra/yassl/taocrypt/src/misc.cpp @@ -30,6 +30,20 @@ #include "misc.hpp" +#ifdef __GNUC__ + #include <signal.h> + #include <setjmp.h> +#endif + +#ifdef USE_SYS_STL + #include <algorithm> +#else + #include "algorithm.hpp" +#endif + +namespace STL = STL_NAMESPACE; + + #ifdef YASSL_PURE_C void* operator new(size_t sz, TaoCrypt::new_t) @@ -156,5 +170,129 @@ unsigned long Crop(unsigned long value, unsigned int size) } + +#ifdef TAOCRYPT_X86ASM_AVAILABLE + +#ifndef _MSC_VER + static jmp_buf s_env; + static void SigIllHandler(int) + { + longjmp(s_env, 1); + } +#endif + + +bool HaveCpuId() +{ +#ifdef _MSC_VER + __try + { + __asm + { + mov eax, 0 + cpuid + } + } + __except (1) + { + return false; + } + return true; +#else + typedef void (*SigHandler)(int); + + SigHandler oldHandler = signal(SIGILL, SigIllHandler); + if (oldHandler == SIG_ERR) + return false; + + bool result = true; + if (setjmp(s_env)) + result = false; + else + __asm__ __volatile + ( + // save ebx in case -fPIC is being used + "push %%ebx; mov $0, %%eax; cpuid; pop %%ebx" + : + : + : "%eax", "%ecx", "%edx" + ); + + signal(SIGILL, oldHandler); + return result; +#endif +} + + +void CpuId(word32 input, word32 *output) +{ +#ifdef __GNUC__ + __asm__ + ( + // save ebx in case -fPIC is being used + "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" + : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d"(output[3]) + : "a" (input) + ); +#else + __asm + { + mov eax, input + cpuid + mov edi, output + mov [edi], eax + mov [edi+4], ebx + mov [edi+8], ecx + mov [edi+12], edx + } +#endif +} + + +bool IsPentium() +{ + if (!HaveCpuId()) + return false; + + word32 cpuid[4]; + + CpuId(0, cpuid); + STL::swap(cpuid[2], cpuid[3]); + if (memcmp(cpuid+1, "GenuineIntel", 12) != 0) + return false; + + CpuId(1, cpuid); + byte family = ((cpuid[0] >> 8) & 0xf); + if (family < 5) + return false; + + return true; +} + + + +static bool IsMmx() +{ + if (!IsPentium()) + return false; + + word32 cpuid[4]; + + CpuId(1, cpuid); + if ((cpuid[3] & (1 << 23)) == 0) + return false; + + return true; +} + + +bool isMMX = IsMmx(); + + +#endif // TAOCRYPT_X86ASM_AVAILABLE + + + + } // namespace diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp index c7bb6ae9549..3fab1ddba23 100644 --- a/extra/yassl/taocrypt/src/random.cpp +++ b/extra/yassl/taocrypt/src/random.cpp @@ -50,8 +50,11 @@ namespace TaoCrypt { RandomNumberGenerator::RandomNumberGenerator() { byte key[32]; + byte junk[256]; + seed_.GenerateSeed(key, sizeof(key)); cipher_.SetKey(key, sizeof(key)); + GenerateBlock(junk, sizeof(junk)); // rid initial state } diff --git a/extra/yassl/taocrypt/src/ripemd.cpp b/extra/yassl/taocrypt/src/ripemd.cpp index 03c09edde84..98bfe4b2645 100644 --- a/extra/yassl/taocrypt/src/ripemd.cpp +++ b/extra/yassl/taocrypt/src/ripemd.cpp @@ -28,15 +28,16 @@ #include "runtime.hpp" #include "ripemd.hpp" -#include STL_ALGORITHM_FILE +#ifdef USE_SYS_STL + #include <algorithm> +#else + #include "algorithm.hpp" +#endif namespace STL = STL_NAMESPACE; -#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) - #define DO_RIPEMD_ASM -#endif namespace TaoCrypt { @@ -86,10 +87,17 @@ void RIPEMD160::Swap(RIPEMD160& other) } -// Update digest with data of size len, do in blocks +#ifdef DO_RIPEMD_ASM + +// Update digest with data of size len void RIPEMD160::Update(const byte* data, word32 len) { - byte* local = (byte*)buffer_; + if (!isMMX) { + HASHwithTransform::Update(data, len); + return; + } + + byte* local = reinterpret_cast<byte*>(buffer_); // remove buffered data if possible if (buffLen_) { @@ -101,27 +109,14 @@ void RIPEMD160::Update(const byte* data, word32 len) len -= add; if (buffLen_ == BLOCK_SIZE) { - ByteReverseIf(local, local, BLOCK_SIZE, LittleEndianOrder); Transform(); AddLength(BLOCK_SIZE); buffLen_ = 0; } } - // do block size transforms or all at once for asm + // all at once for asm if (buffLen_ == 0) { - #ifndef DO_RIPEMD_ASM - while (len >= BLOCK_SIZE) { - memcpy(&local[0], data, BLOCK_SIZE); - - data += BLOCK_SIZE; - len -= BLOCK_SIZE; - - ByteReverseIf(local, local, BLOCK_SIZE, LittleEndianOrder); - Transform(); - AddLength(BLOCK_SIZE); - } - #else word32 times = len / BLOCK_SIZE; if (times) { AsmTransform(data, times); @@ -130,7 +125,6 @@ void RIPEMD160::Update(const byte* data, word32 len) len -= add; data += add; } - #endif } // cache any data left @@ -140,6 +134,8 @@ void RIPEMD160::Update(const byte* data, word32 len) } } +#endif // DO_RIPEMD_ASM + // for all #define F(x, y, z) (x ^ y ^ z) diff --git a/extra/yassl/taocrypt/src/sha.cpp b/extra/yassl/taocrypt/src/sha.cpp index 280d42fb3d4..b1273d9da8f 100644 --- a/extra/yassl/taocrypt/src/sha.cpp +++ b/extra/yassl/taocrypt/src/sha.cpp @@ -28,16 +28,16 @@ #include "runtime.hpp" #include <string.h> #include "sha.hpp" -#include STL_ALGORITHM_FILE +#ifdef USE_SYS_STL + #include <algorithm> +#else + #include "algorithm.hpp" +#endif namespace STL = STL_NAMESPACE; -#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) - #define DO_SHA_ASM -#endif - namespace TaoCrypt { @@ -108,10 +108,18 @@ void SHA::Swap(SHA& other) } -// Update digest with data of size len, do in blocks + +#ifdef DO_SHA_ASM + +// Update digest with data of size len void SHA::Update(const byte* data, word32 len) { - byte* local = (byte*)buffer_; + if (!isMMX) { + HASHwithTransform::Update(data, len); + return; + } + + byte* local = reinterpret_cast<byte*>(buffer_); // remove buffered data if possible if (buffLen_) { @@ -123,27 +131,15 @@ void SHA::Update(const byte* data, word32 len) len -= add; if (buffLen_ == BLOCK_SIZE) { - ByteReverseIf(local, local, BLOCK_SIZE, BigEndianOrder); + ByteReverse(local, local, BLOCK_SIZE); Transform(); AddLength(BLOCK_SIZE); buffLen_ = 0; } } - // do block size transforms or all at once for asm + // all at once for asm if (buffLen_ == 0) { - #ifndef DO_SHA_ASM - while (len >= BLOCK_SIZE) { - memcpy(&local[0], data, BLOCK_SIZE); - - data += BLOCK_SIZE; - len -= BLOCK_SIZE; - - ByteReverseIf(local, local, BLOCK_SIZE, BigEndianOrder); - Transform(); - AddLength(BLOCK_SIZE); - } - #else word32 times = len / BLOCK_SIZE; if (times) { AsmTransform(data, times); @@ -152,7 +148,6 @@ void SHA::Update(const byte* data, word32 len) len -= add; data += add; } - #endif } // cache any data left @@ -162,6 +157,8 @@ void SHA::Update(const byte* data, word32 len) } } +#endif // DO_SHA_ASM + void SHA::Transform() { diff --git a/extra/yassl/taocrypt/src/twofish.cpp b/extra/yassl/taocrypt/src/twofish.cpp index a16a8f0d169..bb385331519 100644 --- a/extra/yassl/taocrypt/src/twofish.cpp +++ b/extra/yassl/taocrypt/src/twofish.cpp @@ -35,33 +35,20 @@ #include "twofish.hpp" -#if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) - #define DO_TWOFISH_ASM -#endif - namespace TaoCrypt { -#if !defined(DO_TWOFISH_ASM) - -// Generic Version -void Twofish::Process(byte* out, const byte* in, word32 sz) -{ - if (mode_ == ECB) - ECB_Process(out, in, sz); - else if (mode_ == CBC) - if (dir_ == ENCRYPTION) - CBC_Encrypt(out, in, sz); - else - CBC_Decrypt(out, in, sz); -} - -#else +#if defined(DO_TWOFISH_ASM) // ia32 optimized version void Twofish::Process(byte* out, const byte* in, word32 sz) { + if (!isMMX) { + Mode_BASE::Process(out, in, sz); + return; + } + word32 blocks = sz / BLOCK_SIZE; if (mode_ == ECB) diff --git a/extra/yassl/taocrypt/taocrypt.dsp b/extra/yassl/taocrypt/taocrypt.dsp index 19edf7b2f22..3f1b47990ad 100644 --- a/extra/yassl/taocrypt/taocrypt.dsp +++ b/extra/yassl/taocrypt/taocrypt.dsp @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "include" /I "..\mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -64,7 +64,7 @@ LIB32=link.exe -lib # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c # SUBTRACT CPP /Fr # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" diff --git a/extra/yassl/taocrypt/taocrypt.vcproj b/extra/yassl/taocrypt/taocrypt.vcproj index 7eef7b82db7..7ffcb664346 100755 --- a/extra/yassl/taocrypt/taocrypt.vcproj +++ b/extra/yassl/taocrypt/taocrypt.vcproj @@ -21,7 +21,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories="include,..\mySTL" + AdditionalIncludeDirectories="include,mySTL" PreprocessorDefinitions="WIN32;_DEBUG;_LIB" ExceptionHandling="FALSE" BasicRuntimeChecks="3" @@ -75,7 +75,7 @@ Name="VCCLCompilerTool" Optimization="2" InlineFunctionExpansion="1" - AdditionalIncludeDirectories="include,..\mySTL" + AdditionalIncludeDirectories="include,mySTL" PreprocessorDefinitions="WIN32;NDEBUG;_LIB" StringPooling="TRUE" ExceptionHandling="FALSE" diff --git a/extra/yassl/taocrypt/test.dsp b/extra/yassl/taocrypt/test.dsp index a5e05ed0ac0..1084f8e06e3 100644 --- a/extra/yassl/taocrypt/test.dsp +++ b/extra/yassl/taocrypt/test.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /O2 /I "include" /I "../mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD CPP /nologo /MT /W3 /O2 /I "include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -66,7 +66,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "../mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/extra/yassl/taocrypt/test/Makefile.am b/extra/yassl/taocrypt/test/Makefile.am index 988d00c7bef..25e1a98fc94 100644 --- a/extra/yassl/taocrypt/test/Makefile.am +++ b/extra/yassl/taocrypt/test/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../mySTL +INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../mySTL bin_PROGRAMS = test test_SOURCES = test.cpp test_LDADD = $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la diff --git a/extra/yassl/taocrypt/test/make.bat b/extra/yassl/taocrypt/test/make.bat index 5f01db68d0d..7b53e9abc90 100644 --- a/extra/yassl/taocrypt/test/make.bat +++ b/extra/yassl/taocrypt/test/make.bat @@ -1,7 +1,7 @@ REM quick and dirty build file for testing different MSDEVs setlocal -set myFLAGS= /I../include /I../../mySTL /c /W3 /G6 /O2 +set myFLAGS= /I../include /I../mySTL /c /W3 /G6 /O2 cl %myFLAGS% test.cpp diff --git a/extra/yassl/taocrypt/test/test.cpp b/extra/yassl/taocrypt/test/test.cpp index 28ef73dfac8..9e3ef709a78 100644 --- a/extra/yassl/taocrypt/test/test.cpp +++ b/extra/yassl/taocrypt/test/test.cpp @@ -247,6 +247,8 @@ void taocrypt_test(void* args) args.argv = argv; taocrypt_test(&args); + TaoCrypt::CleanUp(); + return args.return_code; } diff --git a/extra/yassl/testsuite/Makefile.am b/extra/yassl/testsuite/Makefile.am index e8abffd6bb0..138077300f9 100644 --- a/extra/yassl/testsuite/Makefile.am +++ b/extra/yassl/testsuite/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../taocrypt/include -I../taocrypt/mySTL +INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../taocrypt/include -I$(srcdir)/../taocrypt/mySTL bin_PROGRAMS = testsuite testsuite_SOURCES = testsuite.cpp ../taocrypt/test/test.cpp \ ../examples/client/client.cpp ../examples/server/server.cpp \ diff --git a/extra/yassl/testsuite/make.bat b/extra/yassl/testsuite/make.bat index 1bc7ce0513d..ea2677db481 100644 --- a/extra/yassl/testsuite/make.bat +++ b/extra/yassl/testsuite/make.bat @@ -1,7 +1,7 @@ REM quick and dirty build file for testing different MSDEVs setlocal -set myFLAGS= /I../include /I../taocrypt/include /I../mySTL /c /W3 /G6 /O2 /MT /D"WIN32" /D"NO_MAIN_DRIVER" +set myFLAGS= /I../include /I../taocrypt/include /I../taocrypt/mySTL /c /W3 /G6 /O2 /MT /D"WIN32" /D"NO_MAIN_DRIVER" cl %myFLAGS% testsuite.cpp cl %myFLAGS% ../examples/client/client.cpp diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp index b23b36f0ba2..b2fed37f4e5 100644 --- a/extra/yassl/testsuite/test.hpp +++ b/extra/yassl/testsuite/test.hpp @@ -9,6 +9,8 @@ #include <stdlib.h> #include <assert.h> +//#define NON_BLOCKING // test server and client example (not echos) + #ifdef _WIN32 #include <winsock2.h> #include <process.h> @@ -23,16 +25,17 @@ #include <sys/types.h> #include <sys/socket.h> #include <pthread.h> +#ifdef NON_BLOCKING + #include <fcntl.h> +#endif #define SOCKET_T int #endif /* _WIN32 */ -#if !defined(_SOCKLEN_T) && defined(_WIN32) +#if !defined(_SOCKLEN_T) && \ + (defined(_WIN32) || defined(__NETWARE__) || defined(__APPLE__)) typedef int socklen_t; #endif -#if !defined(_SOCKLEN_T) && defined(__NETWARE__) - typedef size_t socklen_t; -#endif // Check type of third arg to accept @@ -262,6 +265,20 @@ inline void set_args(int& argc, char**& argv, func_args& args) } +inline void tcp_set_nonblocking(SOCKET_T& sockfd) +{ +#ifdef NON_BLOCKING + #ifdef _WIN32 + unsigned long blocking = 1; + int ret = ioctlsocket(sockfd, FIONBIO, &blocking); + #else + int flags = fcntl(sockfd, F_GETFL, 0); + int ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); + #endif +#endif +} + + inline void tcp_socket(SOCKET_T& sockfd, sockaddr_in& addr) { sockfd = socket(AF_INET, SOCK_STREAM, 0); @@ -289,8 +306,7 @@ inline void tcp_connect(SOCKET_T& sockfd) sockaddr_in addr; tcp_socket(sockfd, addr); - if (connect(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) - { + if (connect(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) { tcp_close(sockfd); err_sys("tcp connect failed"); } @@ -302,19 +318,18 @@ inline void tcp_listen(SOCKET_T& sockfd) sockaddr_in addr; tcp_socket(sockfd, addr); - if (bind(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) - { + if (bind(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) { tcp_close(sockfd); err_sys("tcp bind failed"); } - if (listen(sockfd, 3) != 0) - { + if (listen(sockfd, 3) != 0) { tcp_close(sockfd); err_sys("tcp listen failed"); } } + inline void tcp_accept(SOCKET_T& sockfd, SOCKET_T& clientfd, func_args& args) { tcp_listen(sockfd); @@ -333,11 +348,14 @@ inline void tcp_accept(SOCKET_T& sockfd, SOCKET_T& clientfd, func_args& args) clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); - if (clientfd == -1) - { + if (clientfd == -1) { tcp_close(sockfd); err_sys("tcp accept failed"); } + +#ifdef NON_BLOCKING + tcp_set_nonblocking(clientfd); +#endif } @@ -363,25 +381,30 @@ inline void showPeer(SSL* ssl) inline DH* set_tmpDH(SSL_CTX* ctx) { - static unsigned char dh512_p[] = + static unsigned char dh1024_p[] = { - 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, - 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, - 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, - 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, - 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, - 0x47,0x74,0xE8,0x33, + 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3, + 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E, + 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59, + 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2, + 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD, + 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF, + 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02, + 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C, + 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7, + 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50, + 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B, }; - static unsigned char dh512_g[] = + static unsigned char dh1024_g[] = { 0x02, }; DH* dh; if ( (dh = DH_new()) ) { - dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), 0); - dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), 0); + dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0); + dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0); } if (!dh->p || !dh->g) { DH_free(dh); diff --git a/extra/yassl/testsuite/testsuite.cpp b/extra/yassl/testsuite/testsuite.cpp index 1cf6a78ebe7..49113a552cd 100644 --- a/extra/yassl/testsuite/testsuite.cpp +++ b/extra/yassl/testsuite/testsuite.cpp @@ -86,8 +86,8 @@ int main(int argc, char** argv) // input output compare byte input[TaoCrypt::MD5::DIGEST_SIZE]; byte output[TaoCrypt::MD5::DIGEST_SIZE]; - file_test("input", input); - file_test("output", output); + file_test((char*) "input", input); + file_test((char*) "output", output); assert(memcmp(input, output, sizeof(input)) == 0); printf("\nAll tests passed!\n"); diff --git a/extra/yassl/testsuite/testsuite.dsp b/extra/yassl/testsuite/testsuite.dsp index 24c325fa878..2a7f5a77433 100644 --- a/extra/yassl/testsuite/testsuite.dsp +++ b/extra/yassl/testsuite/testsuite.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /O2 /I "../taocrypt/include" /I "../include" /I "../mySTL" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /YX /FD /c +# ADD CPP /nologo /MT /W3 /O2 /I "../taocrypt/include" /I "../include" /I "../taocrypt/mySTL" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -67,7 +67,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "../taocrypt/include" /I "../include" /I "../mySTL" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "../taocrypt/include" /I "../include" /I "../taocrypt/mySTL" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/extra/yassl/yassl.dsp b/extra/yassl/yassl.dsp index 58c016da448..f9b1699e667 100644 --- a/extra/yassl/yassl.dsp +++ b/extra/yassl/yassl.dsp @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /YX /FD /c -# ADD CPP /nologo /MT /W3 /O2 /I "include" /I "taocrypt\include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /YX /FD /c +# ADD CPP /nologo /MT /W3 /O2 /I "include" /I "taocrypt\include" /I "taocrypt\mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -64,7 +64,7 @@ LIB32=link.exe -lib # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "taocrypt\include" /I "mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "taocrypt\include" /I "taocrypt\mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/extra/yassl/yassl.vcproj b/extra/yassl/yassl.vcproj index a7688ac4583..ec7dceb5096 100755 --- a/extra/yassl/yassl.vcproj +++ b/extra/yassl/yassl.vcproj @@ -21,7 +21,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories="include,taocrypt\include,mySTL" + AdditionalIncludeDirectories="include,taocrypt\include,taocrypt\mySTL" PreprocessorDefinitions="WIN32;_DEBUG;_LIB;YASSL_PREFIX" ExceptionHandling="FALSE" BasicRuntimeChecks="3" @@ -75,7 +75,7 @@ Name="VCCLCompilerTool" Optimization="2" InlineFunctionExpansion="1" - AdditionalIncludeDirectories="include,taocrypt\include,mySTL" + AdditionalIncludeDirectories="include,taocrypt\include,taocrypt\mySTL" PreprocessorDefinitions="WIN32;NDEBUG;_LIB;YASSL_PREFIX" StringPooling="TRUE" ExceptionHandling="FALSE" diff --git a/heap/_check.c b/heap/_check.c index cc832f8ed5b..c861fdb582f 100644 --- a/heap/_check.c +++ b/heap/_check.c @@ -88,7 +88,8 @@ int heap_check_heap(HP_INFO *info, my_bool print_status) if (records != share->records || deleted != share->deleted) { DBUG_PRINT("error",("Found rows: %lu (%lu) deleted %lu (%lu)", - records, share->records, deleted, share->deleted)); + records, (ulong) share->records, + deleted, (ulong) share->deleted)); error= 1; } *info= save_info; @@ -100,9 +101,9 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, ulong blength, my_bool print_status) { int error; - uint i,found,max_links,seek,links; - uint rec_link; /* Only used with debugging */ - uint hash_buckets_found; + ulong i,found,max_links,seek,links; + ulong rec_link; /* Only used with debugging */ + ulong hash_buckets_found; HASH_INFO *hash_info; error=0; @@ -123,7 +124,9 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, blength, records)) != i) { - DBUG_PRINT("error",("Record in wrong link: Link %d Record: 0x%lx Record-link %d", i,hash_info->ptr_to_rec,rec_link)); + DBUG_PRINT("error", + ("Record in wrong link: Link %lu Record: 0x%lx Record-link %lu", + i, (long) hash_info->ptr_to_rec, rec_link)); error=1; } else @@ -141,18 +144,18 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, if (keydef->hash_buckets != hash_buckets_found) { DBUG_PRINT("error",("Found %ld buckets, stats shows %ld buckets", - hash_buckets_found, keydef->hash_buckets)); + hash_buckets_found, (long) keydef->hash_buckets)); error=1; } DBUG_PRINT("info", - ("records: %ld seeks: %d max links: %d hitrate: %.2f " - "buckets: %d", + ("records: %ld seeks: %lu max links: %lu hitrate: %.2f " + "buckets: %lu", records,seek,max_links, (float) seek / (float) (records ? records : 1), hash_buckets_found)); if (print_status) - printf("Key: %d records: %ld seeks: %d max links: %d " - "hitrate: %.2f buckets: %d\n", + printf("Key: %d records: %ld seeks: %lu max links: %lu " + "hitrate: %.2f buckets: %lu\n", keynr, records, seek, max_links, (float) seek / (float) (records ? records : 1), hash_buckets_found); @@ -180,8 +183,8 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records, key_length, SEARCH_FIND | SEARCH_SAME, not_used)) { error= 1; - DBUG_PRINT("error",("Record in wrong link: key: %d Record: 0x%lx\n", - keynr, recpos)); + DBUG_PRINT("error",("Record in wrong link: key: %u Record: 0x%lx\n", + keynr, (long) recpos)); } else found++; diff --git a/heap/hp_clear.c b/heap/hp_clear.c index 596d71ebe9c..b491f8eba15 100644 --- a/heap/hp_clear.c +++ b/heap/hp_clear.c @@ -36,7 +36,8 @@ void hp_clear(HP_SHARE *info) (byte*) 0)); info->block.levels=0; hp_clear_keys(info); - info->records=info->deleted=info->data_length=0; + info->records= info->deleted= 0; + info->data_length= 0; info->blength=1; info->changed=0; info->del_link=0; diff --git a/heap/hp_delete.c b/heap/hp_delete.c index f18c5e7054c..2ef57624e77 100644 --- a/heap/hp_delete.c +++ b/heap/hp_delete.c @@ -24,7 +24,7 @@ int heap_delete(HP_INFO *info, const byte *record) HP_SHARE *share=info->s; HP_KEYDEF *keydef, *end, *p_lastinx; DBUG_ENTER("heap_delete"); - DBUG_PRINT("enter",("info: %lx record: 0x%lx",info,record)); + DBUG_PRINT("enter",("info: 0x%lx record: 0x%lx", (long) info, (long) record)); test_active(info); @@ -144,7 +144,7 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, info->current_hash_ptr=last_ptr; info->current_ptr = last_ptr ? last_ptr->ptr_to_rec : 0; DBUG_PRINT("info",("Corrected current_ptr to point at: 0x%lx", - info->current_ptr)); + (long) info->current_ptr)); } empty=pos; if (gpos) diff --git a/heap/hp_hash.c b/heap/hp_hash.c index 77f3cf6d80b..6a537906929 100644 --- a/heap/hp_hash.c +++ b/heap/hp_hash.c @@ -120,7 +120,7 @@ byte *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key, { switch (nextflag) { case 0: /* Search after key */ - DBUG_PRINT("exit",("found key at %d",pos->ptr_to_rec)); + DBUG_PRINT("exit", ("found key at 0x%lx", (long) pos->ptr_to_rec)); info->current_hash_ptr=pos; DBUG_RETURN(info->current_ptr= pos->ptr_to_rec); case 1: /* Search next */ diff --git a/heap/hp_open.c b/heap/hp_open.c index fd937229b0d..f50478c8b3d 100644 --- a/heap/hp_open.c +++ b/heap/hp_open.c @@ -64,7 +64,8 @@ HP_INFO *heap_open(const char *name, int mode) info->opt_flag= READ_CHECK_USED; /* Check when changing */ #endif DBUG_PRINT("exit",("heap: 0x%lx reclength: %d records_in_block: %d", - info,share->reclength,share->block.records_in_block)); + (long) info, share->reclength, + share->block.records_in_block)); DBUG_RETURN(info); } @@ -82,7 +83,7 @@ HP_SHARE *hp_find_named_heap(const char *name) info= (HP_SHARE*) pos->data; if (!strcmp(name, info->name)) { - DBUG_PRINT("exit", ("Old heap_database: 0x%lx",info)); + DBUG_PRINT("exit", ("Old heap_database: 0x%lx", (long) info)); DBUG_RETURN(info); } } diff --git a/heap/hp_rkey.c b/heap/hp_rkey.c index f5f22a877a1..f02d44cc456 100644 --- a/heap/hp_rkey.c +++ b/heap/hp_rkey.c @@ -23,7 +23,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key, HP_SHARE *share= info->s; HP_KEYDEF *keyinfo= share->keydef + inx; DBUG_ENTER("heap_rkey"); - DBUG_PRINT("enter",("base: 0x%lx inx: %d",info,inx)); + DBUG_PRINT("enter",("info: 0x%lx inx: %d", (long) info, inx)); if ((uint) inx >= share->keys) { diff --git a/heap/hp_rrnd.c b/heap/hp_rrnd.c index 4daa3a06377..2f8556484a4 100644 --- a/heap/hp_rrnd.c +++ b/heap/hp_rrnd.c @@ -29,7 +29,7 @@ int heap_rrnd(register HP_INFO *info, byte *record, byte *pos) { HP_SHARE *share=info->s; DBUG_ENTER("heap_rrnd"); - DBUG_PRINT("enter",("info: 0x%lx pos: %lx",info,pos)); + DBUG_PRINT("enter",("info: 0x%lx pos: %lx",(long) info, (long) pos)); info->lastinx= -1; if (!(info->current_ptr= pos)) @@ -44,7 +44,7 @@ int heap_rrnd(register HP_INFO *info, byte *record, byte *pos) } info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV; memcpy(record,info->current_ptr,(size_t) share->reclength); - DBUG_PRINT("exit",("found record at 0x%lx",info->current_ptr)); + DBUG_PRINT("exit", ("found record at 0x%lx", (long) info->current_ptr)); info->current_hash_ptr=0; /* Can't use rnext */ DBUG_RETURN(0); } /* heap_rrnd */ diff --git a/heap/hp_write.c b/heap/hp_write.c index bc94e3bfae4..c83ae65c966 100644 --- a/heap/hp_write.c +++ b/heap/hp_write.c @@ -68,7 +68,7 @@ int heap_write(HP_INFO *info, const byte *record) DBUG_RETURN(0); err: - DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef)); + DBUG_PRINT("info",("Duplicate key: %d", (int) (keydef - share->keydef))); info->errkey= keydef - share->keydef; if (keydef->algorithm == HA_KEY_ALG_BTREE) { @@ -138,7 +138,7 @@ static byte *next_free_record_pos(HP_SHARE *info) pos=info->del_link; info->del_link= *((byte**) pos); info->deleted--; - DBUG_PRINT("exit",("Used old position: 0x%lx",pos)); + DBUG_PRINT("exit",("Used old position: 0x%lx",(long) pos)); DBUG_RETURN(pos); } if (!(block_pos=(info->records % info->block.records_in_block))) @@ -153,9 +153,9 @@ static byte *next_free_record_pos(HP_SHARE *info) DBUG_RETURN(NULL); info->data_length+=length; } - DBUG_PRINT("exit",("Used new position: %lx", - (byte*) info->block.level_info[0].last_blocks+block_pos* - info->block.recbuffer)); + DBUG_PRINT("exit",("Used new position: 0x%lx", + (long) ((byte*) info->block.level_info[0].last_blocks+ + block_pos * info->block.recbuffer))); DBUG_RETURN((byte*) info->block.level_info[0].last_blocks+ block_pos*info->block.recbuffer); } diff --git a/include/Makefile.am b/include/Makefile.am index c4fe41e8a06..aa20cf892c1 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -15,14 +15,17 @@ # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA -BUILT_SOURCES = mysql_version.h my_config.h -pkginclude_HEADERS = my_dbug.h m_string.h my_sys.h my_list.h my_xml.h \ - mysql.h mysql_com.h mysql_embed.h \ - my_semaphore.h my_pthread.h my_no_pthread.h raid.h \ - errmsg.h my_global.h my_net.h my_alloc.h \ - my_getopt.h sslopt-longopts.h my_dir.h typelib.h \ +BUILT_SOURCES = $(HEADERS_GEN) abi_check +HEADERS_GEN = mysql_version.h my_config.h +HEADERS_ABI = mysql.h mysql_com.h mysql_time.h \ + my_list.h my_alloc.h typelib.h +pkginclude_HEADERS = $(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \ + my_xml.h mysql_embed.h \ + my_semaphore.h my_pthread.h my_no_pthread.h raid.h \ + errmsg.h my_global.h my_net.h \ + my_getopt.h sslopt-longopts.h my_dir.h \ sslopt-vars.h sslopt-case.h sql_common.h keycache.h \ - mysql_time.h m_ctype.h $(BUILT_SOURCES) + m_ctype.h $(HEADERS_GEN) noinst_HEADERS = config-win.h config-os2.h config-netware.h \ heap.h my_bitmap.h\ myisam.h myisampack.h myisammrg.h ft_global.h\ @@ -59,8 +62,7 @@ dist-hook: # # Create a icheck file and compare it to the reference -abi_check: mysql.h mysql_version.h mysql_com.h mysql_time.h my_list.h \ - my_alloc.h typelib.h mysql_h.ic +abi_check: $(HEADERS_ABI) mysql_version.h mysql_h.ic @set -ex; \ if [ @ICHECK@ != no ] ; then \ @ICHECK@ --canonify --skip-from-re /usr/ -o $@.ic mysql.h; \ @@ -69,8 +71,5 @@ abi_check: mysql.h mysql_version.h mysql_com.h mysql_time.h my_list.h \ fi; \ touch abi_check; -all: abi_check - - # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/include/config-win.h b/include/config-win.h index 75133ddc837..3c76dee40a1 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -249,7 +249,6 @@ inline double ulonglong2double(ulonglong value) #define tell(A) _telli64(A) #endif -#define set_timespec(ABSTIME,SEC) { (ABSTIME).tv_sec=time((time_t*)0) + (time_t) (SEC); (ABSTIME).tv_nsec=0; } #define STACK_DIRECTION -1 diff --git a/include/errmsg.h b/include/errmsg.h index 1dd5759c104..aca7c4b6a1f 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -97,6 +97,7 @@ extern const char *client_errors[]; /* Error messages */ #define CR_NO_STMT_METADATA 2052 #define CR_NO_RESULT_SET 2053 #define CR_NOT_IMPLEMENTED 2054 -#define CR_ERROR_LAST /*Copy last error nr:*/ 2054 +#define CR_SERVER_LOST_EXTENDED 2055 +#define CR_ERROR_LAST /*Copy last error nr:*/ 2055 /* Add error numbers before CR_ERROR_LAST and change it accordingly. */ diff --git a/include/heap.h b/include/heap.h index cfbb6113f86..4255ee52b18 100644 --- a/include/heap.h +++ b/include/heap.h @@ -46,8 +46,8 @@ typedef struct st_heapinfo /* Struct from heap_info */ ulong records; /* Records in database */ ulong deleted; /* Deleted records in database */ ulong max_records; - ulong data_length; - ulong index_length; + ulonglong data_length; + ulonglong index_length; uint reclength; /* Length of one record */ int errkey; ulonglong auto_increment; @@ -135,7 +135,7 @@ typedef struct st_heap_share HP_BLOCK block; HP_KEYDEF *keydef; ulong min_records,max_records; /* Params to open */ - ulong data_length,index_length,max_table_size; + ulonglong data_length,index_length,max_table_size; uint key_stat_version; /* version to indicate insert/delete */ uint records; /* records */ uint blength; /* records rounded up to 2^n */ @@ -187,7 +187,7 @@ typedef struct st_heap_create_info { uint auto_key; /* keynr [1 - maxkey] for auto key */ uint auto_key_type; - ulong max_table_size; + ulonglong max_table_size; ulonglong auto_increment; my_bool with_auto_increment; } HP_CREATE_INFO; diff --git a/include/m_ctype.h b/include/m_ctype.h index 35d2889bdd5..ffecadd9836 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -178,8 +178,8 @@ typedef struct my_charset_handler_st unsigned char *s,unsigned char *e); /* Functions for case and sort convertion */ - void (*caseup_str)(struct charset_info_st *, char *); - void (*casedn_str)(struct charset_info_st *, char *); + uint (*caseup_str)(struct charset_info_st *, char *); + uint (*casedn_str)(struct charset_info_st *, char *); uint (*caseup)(struct charset_info_st *, char *src, uint srclen, char *dst, uint dstlen); uint (*casedn)(struct charset_info_st *, char *src, uint srclen, @@ -311,8 +311,8 @@ extern uint my_instr_simple(struct charset_info_st *, /* Functions for 8bit */ -extern void my_caseup_str_8bit(CHARSET_INFO *, char *); -extern void my_casedn_str_8bit(CHARSET_INFO *, char *); +extern uint my_caseup_str_8bit(CHARSET_INFO *, char *); +extern uint my_casedn_str_8bit(CHARSET_INFO *, char *); extern uint my_caseup_8bit(CHARSET_INFO *, char *src, uint srclen, char *dst, uint dstlen); extern uint my_casedn_8bit(CHARSET_INFO *, char *src, uint srclen, @@ -399,8 +399,8 @@ int my_mbcharlen_8bit(CHARSET_INFO *, uint c); /* Functions for multibyte charsets */ -extern void my_caseup_str_mb(CHARSET_INFO *, char *); -extern void my_casedn_str_mb(CHARSET_INFO *, char *); +extern uint my_caseup_str_mb(CHARSET_INFO *, char *); +extern uint my_casedn_str_mb(CHARSET_INFO *, char *); extern uint my_caseup_mb(CHARSET_INFO *, char *src, uint srclen, char *dst, uint dstlen); extern uint my_casedn_mb(CHARSET_INFO *, char *src, uint srclen, diff --git a/include/my_global.h b/include/my_global.h index f94cedbc91a..d297f6f543c 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1010,41 +1010,7 @@ typedef char bool; /* Ordinary boolean values 0 1 */ #define MY_HOW_OFTEN_TO_ALARM 2 /* How often we want info on screen */ #define MY_HOW_OFTEN_TO_WRITE 1000 /* How often we want info on screen */ -#ifdef HAVE_TIMESPEC_TS_SEC -#ifndef set_timespec -#define set_timespec(ABSTIME,SEC) \ -{ \ - (ABSTIME).ts_sec=time(0) + (time_t) (SEC); \ - (ABSTIME).ts_nsec=0; \ -} -#endif /* !set_timespec */ -#ifndef set_timespec_nsec -#define set_timespec_nsec(ABSTIME,NSEC) \ -{ \ - ulonglong now= my_getsystime() + (NSEC/100); \ - (ABSTIME).ts_sec= (now / ULL(10000000)); \ - (ABSTIME).ts_nsec= (now % ULL(10000000) * 100 + ((NSEC) % 100)); \ -} -#endif /* !set_timespec_nsec */ -#else -#ifndef set_timespec -#define set_timespec(ABSTIME,SEC) \ -{\ - struct timeval tv;\ - gettimeofday(&tv,0);\ - (ABSTIME).tv_sec=tv.tv_sec+(time_t) (SEC);\ - (ABSTIME).tv_nsec=tv.tv_usec*1000;\ -} -#endif /* !set_timespec */ -#ifndef set_timespec_nsec -#define set_timespec_nsec(ABSTIME,NSEC) \ -{\ - ulonglong now= my_getsystime() + (NSEC/100); \ - (ABSTIME).tv_sec= (now / ULL(10000000)); \ - (ABSTIME).tv_nsec= (now % ULL(10000000) * 100 + ((NSEC) % 100)); \ -} -#endif /* !set_timespec_nsec */ -#endif /* HAVE_TIMESPEC_TS_SEC */ + /* Define-funktions for reading and storing in machine independent format diff --git a/include/my_pthread.h b/include/my_pthread.h index 3e4388413e0..631ca1d7c03 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -69,14 +69,6 @@ typedef struct { #endif } pthread_cond_t; - -#ifndef OS2 -struct timespec { /* For pthread_cond_timedwait() */ - time_t tv_sec; - long tv_nsec; -}; -#endif - typedef int pthread_mutexattr_t; #define win_pthread_self my_thread_var->pthread_self #ifdef OS2 @@ -87,6 +79,36 @@ typedef void * (_Optlink *pthread_handler)(void *); typedef void * (__cdecl *pthread_handler)(void *); #endif +/* + Struct and macros to be used in combination with the + windows implementation of pthread_cond_timedwait +*/ + +/* + Declare a union to make sure FILETIME is properly aligned + so it can be used directly as a 64 bit value. The value + stored is in 100ns units. + */ + union ft64 { + FILETIME ft; + __int64 i64; + }; +struct timespec { + union ft64 tv; + /* The max timeout value in millisecond for pthread_cond_timedwait */ + long max_timeout_msec; +}; +#define set_timespec(ABSTIME,SEC) { \ + GetSystemTimeAsFileTime(&((ABSTIME).tv.ft)); \ + (ABSTIME).tv.i64+= (__int64)(SEC)*10000000; \ + (ABSTIME).max_timeout_msec= (long)((SEC)*1000); \ +} +#define set_timespec_nsec(ABSTIME,NSEC) { \ + GetSystemTimeAsFileTime(&((ABSTIME).tv.ft)); \ + (ABSTIME).tv.i64+= (__int64)(NSEC)/100; \ + (ABSTIME).max_timeout_msec= (long)((NSEC)/1000000); \ +} + void win_pthread_init(void); int win_pthread_setspecific(void *A,void *B,uint length); int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *); @@ -164,8 +186,6 @@ extern int pthread_mutex_destroy (pthread_mutex_t *); #define pthread_condattr_init(A) #define pthread_condattr_destroy(A) -/*Irena: compiler does not like this: */ -/*#define my_pthread_getprio(pthread_t thread_id) pthread_dummy(0) */ #define my_pthread_getprio(thread_id) pthread_dummy(0) #elif defined(HAVE_UNIXWARE7_THREADS) @@ -473,6 +493,47 @@ void my_pthread_attr_getstacksize(pthread_attr_t *attrib, size_t *size); int my_pthread_mutex_trylock(pthread_mutex_t *mutex); #endif +/* + The defines set_timespec and set_timespec_nsec should be used + for calculating an absolute time at which + pthread_cond_timedwait should timeout +*/ +#ifdef HAVE_TIMESPEC_TS_SEC +#ifndef set_timespec +#define set_timespec(ABSTIME,SEC) \ +{ \ + (ABSTIME).ts_sec=time(0) + (time_t) (SEC); \ + (ABSTIME).ts_nsec=0; \ +} +#endif /* !set_timespec */ +#ifndef set_timespec_nsec +#define set_timespec_nsec(ABSTIME,NSEC) \ +{ \ + ulonglong now= my_getsystime() + (NSEC/100); \ + (ABSTIME).ts_sec= (now / ULL(10000000)); \ + (ABSTIME).ts_nsec= (now % ULL(10000000) * 100 + ((NSEC) % 100)); \ +} +#endif /* !set_timespec_nsec */ +#else +#ifndef set_timespec +#define set_timespec(ABSTIME,SEC) \ +{\ + struct timeval tv;\ + gettimeofday(&tv,0);\ + (ABSTIME).tv_sec=tv.tv_sec+(time_t) (SEC);\ + (ABSTIME).tv_nsec=tv.tv_usec*1000;\ +} +#endif /* !set_timespec */ +#ifndef set_timespec_nsec +#define set_timespec_nsec(ABSTIME,NSEC) \ +{\ + ulonglong now= my_getsystime() + (NSEC/100); \ + (ABSTIME).tv_sec= (time_t) (now / ULL(10000000)); \ + (ABSTIME).tv_nsec= (long) (now % ULL(10000000) * 100 + ((NSEC) % 100)); \ +} +#endif /* !set_timespec_nsec */ +#endif /* HAVE_TIMESPEC_TS_SEC */ + /* safe_mutex adds checking to mutex for easier debugging */ #if defined(__NETWARE__) && !defined(SAFE_MUTEX_DETECT_DESTROY) @@ -677,14 +738,13 @@ struct st_my_thread_var }; extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const)); +extern uint my_thread_end_wait_time; #define my_thread_var (_my_thread_var()) #define my_errno my_thread_var->thr_errno /* Keep track of shutdown,signal, and main threads so that my_end() will not report errors with them */ -extern pthread_t shutdown_th, main_th, signal_th; - /* statistics_xxx functions are for not essential statistic */ #ifndef thread_safe_increment diff --git a/include/my_sys.h b/include/my_sys.h index ebb518314b2..d19091a85e8 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -842,12 +842,6 @@ my_bool my_gethwaddr(uchar *to); #endif #define my_mmap(a,b,c,d,e,f) mmap(a,b,c,d,e,f) -#ifdef HAVE_GETPAGESIZE -#define my_getpagesize() getpagesize() -#else -/* qnx ? */ -#define my_getpagesize() 8192 -#endif #define my_munmap(a,b) munmap((a),(b)) #else @@ -863,11 +857,17 @@ my_bool my_gethwaddr(uchar *to); #define HAVE_MMAP #endif -int my_getpagesize(void); void *my_mmap(void *, size_t, int, int, int, my_off_t); int my_munmap(void *, size_t); #endif +/* my_getpagesize */ +#ifdef HAVE_GETPAGESIZE +#define my_getpagesize() getpagesize() +#else +int my_getpagesize(void); +#endif + int my_msync(int, void *, size_t, int); /* character sets */ diff --git a/include/my_time.h b/include/my_time.h index 574f1a49c5a..5361c47d57f 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -67,6 +67,8 @@ typedef long my_time_t; #define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + \ TIME_MAX_SECOND) +my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date, + ulong flags, int *was_cut); enum enum_mysql_timestamp_type str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, uint flags, int *was_cut); diff --git a/include/my_tree.h b/include/my_tree.h index 03dc9d5c829..a047f914e55 100644 --- a/include/my_tree.h +++ b/include/my_tree.h @@ -59,7 +59,8 @@ typedef struct st_tree_element { typedef struct st_tree { TREE_ELEMENT *root,null_element; TREE_ELEMENT **parents[MAX_TREE_HEIGHT]; - uint offset_to_key,elements_in_tree,size_of_element,memory_limit,allocated; + uint offset_to_key,elements_in_tree,size_of_element; + ulong memory_limit, allocated; qsort_cmp2 compare; void *custom_arg; MEM_ROOT mem_root; @@ -69,7 +70,7 @@ typedef struct st_tree { } TREE; /* Functions on whole tree */ -void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit, +void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit, int size, qsort_cmp2 compare, my_bool with_delete, tree_element_free free_element, void *custom_arg); void delete_tree(TREE*); diff --git a/include/mysql.h b/include/mysql.h index f2a82c99fc3..99d6fc27407 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -65,9 +65,9 @@ typedef int my_socket; #endif /* my_socket_defined */ #endif /* _global_h */ +#include "mysql_version.h" #include "mysql_com.h" #include "mysql_time.h" -#include "mysql_version.h" #include "typelib.h" #include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */ diff --git a/include/mysql_h.ic b/include/mysql_h.ic index 7aec1e8a627..5a9daee6f9f 100644 --- a/include/mysql_h.ic +++ b/include/mysql_h.ic @@ -575,6 +575,7 @@ enum mysql_enum_shutdown_level SHUTDOWN_WAIT_UPDATES = (unsigned char)((1 << 3)), SHUTDOWN_WAIT_ALL_BUFFERS = ((unsigned char)((1 << 3)) << 1), SHUTDOWN_WAIT_CRITICAL_BUFFERS = (((unsigned char)((1 << 3)) << 1) + 1), + KILL_QUERY = 254, KILL_CONNECTION = 255, }; # 154 "mysql.h" diff --git a/innobase/CMakeLists.txt b/innobase/CMakeLists.txt index f9661963d56..c244364a800 100755 --- a/innobase/CMakeLists.txt +++ b/innobase/CMakeLists.txt @@ -2,6 +2,43 @@ #SET(CMAKE_C_FLAGS_DEBUG "-DSAFEMALLOC -DSAFE_MUTEX") ADD_DEFINITIONS(-DMYSQL_SERVER -D_WIN32 -DWIN32 -D_LIB) +# Bug#19424 - InnoDB: Possibly a memory overrun of the buffer being freed (64-bit Visual C) +# Removing Win64 compiler optimizations for all innodb files. +IF(CMAKE_GENERATOR MATCHES "Visual Studio 8 2005 Win64") + SET_SOURCE_FILES_PROPERTIES(btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c + buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c + data/data0data.c data/data0type.c + dict/dict0boot.c dict/dict0crea.c dict/dict0dict.c dict/dict0load.c dict/dict0mem.c + dyn/dyn0dyn.c + eval/eval0eval.c eval/eval0proc.c + fil/fil0fil.c + fsp/fsp0fsp.c + fut/fut0fut.c fut/fut0lst.c + ha/ha0ha.c ha/hash0hash.c + ibuf/ibuf0ibuf.c + pars/lexyy.c pars/pars0grm.c pars/pars0opt.c pars/pars0pars.c pars/pars0sym.c + lock/lock0lock.c + log/log0log.c log/log0recv.c + mach/mach0data.c + mem/mem0mem.c mem/mem0pool.c + mtr/mtr0log.c mtr/mtr0mtr.c + os/os0file.c os/os0proc.c os/os0sync.c os/os0thread.c + page/page0cur.c page/page0page.c + que/que0que.c + read/read0read.c + rem/rem0cmp.c rem/rem0rec.c + row/row0ins.c row/row0mysql.c row/row0purge.c row/row0row.c row/row0sel.c row/row0uins.c + row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c + srv/srv0que.c srv/srv0srv.c srv/srv0start.c + sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c + thr/thr0loc.c + trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c + trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c + usr/usr0sess.c + ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c + PROPERTIES COMPILE_FLAGS -Od) +ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 8 2005 Win64") + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include include) ADD_LIBRARY(innobase btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c @@ -33,3 +70,8 @@ ADD_LIBRARY(innobase btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c usr/usr0sess.c ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ) + +# (Bug#19424) Removing Win64 compiler optimizations innobase project. +IF(CMAKE_GENERATOR MATCHES "Visual Studio 8 2005 Win64") + SET_TARGET_PROPERTIES(innobase PROPERTIES COMPILE_FLAGS "/Od") +ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 8 2005 Win64") diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 075005c3611..5e5c4b19eb0 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -1718,7 +1718,7 @@ os_file_set_size( } /* Print about progress for each 100 MB written */ - if ((current_size + n_bytes) / (ib_longlong)(100 * 1024 * 1024) + if ((ib_longlong) (current_size + n_bytes) / (ib_longlong)(100 * 1024 * 1024) != current_size / (ib_longlong)(100 * 1024 * 1024)) { fprintf(stderr, " %lu00", diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index c2d98a81042..dc6d658fcdf 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -89,8 +89,8 @@ DEFS = -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \ -DSHAREDIR="\"$(MYSQLSHAREdir)\"" $(target_defs) if HAVE_YASSL -yassl_las = $(top_srcdir)/extra/yassl/src/libyassl.la \ - $(top_srcdir)/extra/yassl/taocrypt/src/libtaocrypt.la +yassl_las = $(top_builddir)/extra/yassl/src/libyassl.la \ + $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la endif # The automatic dependencies miss this diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index 9e1d70a47df..59089d5ec18 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -82,6 +82,7 @@ const char *client_errors[]= "Prepared statement contains no metadata", "Attempt to read a row while there is no result set associated with the statement", "This feature is not implemented yet", + "Lost connection to MySQL server at '%s', system error: %d", "" }; @@ -145,6 +146,7 @@ const char *client_errors[]= "Prepared statement contains no metadata", "Attempt to read a row while there is no result set associated with the statement", "This feature is not implemented yet", + "Lost connection to MySQL server at '%s', system error: %d", "" }; @@ -206,6 +208,7 @@ const char *client_errors[]= "Prepared statement contains no metadata", "Attempt to read a row while there is no result set associated with the statement", "This feature is not implemented yet", + "Lost connection to MySQL server at '%s', system error: %d", "" }; #endif diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 21fb84fb19a..304c20132ff 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -175,6 +175,9 @@ void STDCALL mysql_server_end() #ifdef EMBEDDED_LIBRARY end_embedded_server(); #endif + finish_client_errs(); + vio_end(); + /* If library called my_init(), free memory allocated by it */ if (!org_my_init_done) { @@ -185,10 +188,11 @@ void STDCALL mysql_server_end() #endif } else + { + free_charsets(); mysql_thread_end(); - finish_client_errs(); - free_charsets(); - vio_end(); + } + mysql_client_init= org_my_init_done= 0; #ifdef EMBEDDED_SERVER if (stderror_file) @@ -2100,7 +2104,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length) } stmt->bind= stmt->params + stmt->param_count; stmt->state= MYSQL_STMT_PREPARE_DONE; - DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count)); + DBUG_PRINT("info", ("Parameter count: %u", stmt->param_count)); DBUG_RETURN(0); } @@ -2443,10 +2447,10 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param) { NET *net= &stmt->mysql->net; DBUG_ENTER("store_param"); - DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %lu is_null: %d", + DBUG_PRINT("enter",("type: %d buffer: 0x%lx length: %lu is_null: %d", param->buffer_type, - param->buffer ? param->buffer : "0", *param->length, - *param->is_null)); + (long) (param->buffer ? param->buffer : NullS), + *param->length, *param->is_null)); if (*param->is_null) store_param_null(net, param); @@ -2478,6 +2482,8 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length) NET *net= &mysql->net; char buff[4 /* size of stmt id */ + 5 /* execution flags */]; + my_bool res; + DBUG_ENTER("execute"); DBUG_DUMP("packet", packet, length); @@ -2485,16 +2491,18 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length) int4store(buff, stmt->stmt_id); /* Send stmt id to server */ buff[4]= (char) stmt->flags; int4store(buff+5, 1); /* iteration count */ - if (cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff), - packet, length, 1, NULL) || - (*mysql->methods->read_query_result)(mysql)) + + res= test(cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff), + packet, length, 1, NULL) || + (*mysql->methods->read_query_result)(mysql)); + stmt->affected_rows= mysql->affected_rows; + stmt->server_status= mysql->server_status; + stmt->insert_id= mysql->insert_id; + if (res) { set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); DBUG_RETURN(1); } - stmt->affected_rows= mysql->affected_rows; - stmt->server_status= mysql->server_status; - stmt->insert_id= mysql->insert_id; DBUG_RETURN(0); } @@ -3325,8 +3333,8 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number, MYSQL_BIND *param; DBUG_ENTER("mysql_stmt_send_long_data"); DBUG_ASSERT(stmt != 0); - DBUG_PRINT("enter",("param no : %d, data : %lx, length : %ld", - param_number, data, length)); + DBUG_PRINT("enter",("param no: %d data: 0x%lx, length : %ld", + param_number, (long) data, length)); /* We only need to check for stmt->param_count, if it's not null @@ -4409,7 +4417,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) ulong bind_count= stmt->field_count; uint param_count= 0; DBUG_ENTER("mysql_stmt_bind_result"); - DBUG_PRINT("enter",("field_count: %d", bind_count)); + DBUG_PRINT("enter",("field_count: %lu", bind_count)); if (!bind_count) { @@ -4769,14 +4777,6 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) DBUG_RETURN(1); } - if (result->data) - { - free_root(&result->alloc, MYF(MY_KEEP_PREALLOC)); - result->data= NULL; - result->rows= 0; - stmt->data_cursor= NULL; - } - if (stmt->update_max_length && !stmt->bind_result_done) { /* diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am index aaf81add00b..062acccda07 100644 --- a/libmysql_r/Makefile.am +++ b/libmysql_r/Makefile.am @@ -29,8 +29,6 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ ## automake barfs if you don't use $(srcdir) or $(top_srcdir) in include include $(top_srcdir)/libmysql/Makefile.shared -libmysql_dir = $(top_srcdir)/libmysql - libmysqlclient_r_la_SOURCES = $(target_sources) libmysqlclient_r_la_LIBADD = $(target_libadd) $(yassl_las) libmysqlclient_r_la_LDFLAGS = $(target_ldflags) @@ -38,7 +36,9 @@ libmysqlclient_r_la_LDFLAGS = $(target_ldflags) # This is called from the toplevel makefile link_sources: set -x; \ - for f in `cd $(libmysql_dir) && echo *.[ch]`; do \ - rm -f $$f; \ - @LN_CP_F@ $(libmysql_dir)/$$f $$f; \ + for d in $(top_srcdir)/libmysql $(top_builddir)/libmysql; do \ + for f in `cd $$d && echo *.[ch]`; do \ + rm -f $$f; \ + @LN_CP_F@ $$d/$$f $$f; \ + done; \ done diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 89b473fb815..cdd71724166 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -25,9 +25,10 @@ DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \ -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ -DSHAREDIR="\"$(MYSQLSHAREdir)\"" -INCLUDES= @bdb_includes@ \ +INCLUDES= @bdb_includes@ @innodb_includes@ @ndbcluster_includes@ \ -I$(top_builddir)/include -I$(top_srcdir)/include \ - -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples \ + -I$(top_builddir)/sql -I$(top_srcdir)/sql \ + -I$(top_srcdir)/sql/examples \ -I$(top_srcdir)/regex \ $(openssl_includes) @ZLIB_INCLUDES@ @@ -118,16 +119,28 @@ endif #libmysqld_la_LDFLAGS = -version-info @SHARED_LIB_VERSION@ #CLEANFILES = $(libmysqld_la_LIBADD) libmysqld.la -# This is called from the toplevel makefile +# This is called from the toplevel makefile. If we can link now +# to an existing file in source, we do that, else we assume it +# will show up in the build tree eventually (generated file). link_sources: set -x; \ for f in $(sqlsources); do \ rm -f $$f; \ - @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \ + if test -e $(top_srcdir)/sql/$$f ; \ + then \ + @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \ + else \ + @LN_CP_F@ $(top_builddir)/sql/$$f $$f; \ + fi ; \ done; \ for f in $(libmysqlsources); do \ rm -f $$f; \ - @LN_CP_F@ $(top_srcdir)/libmysql/$$f $$f; \ + if test -e $(top_srcdir)/libmysql/$$f ; \ + then \ + @LN_CP_F@ $(top_srcdir)/libmysql/$$f $$f; \ + else \ + @LN_CP_F@ $(top_builddir)/libmysql/$$f $$f; \ + fi ; \ done; \ for f in $(sqlexamplessources); do \ rm -f $$f; \ diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 98c75dfe719..97bcb9d87ca 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -100,6 +100,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, mysql->affected_rows= ~(my_ulonglong) 0; mysql->field_count= 0; net->last_errno= 0; + thd->current_stmt= stmt; thd->store_globals(); // Fix if more than one connect /* @@ -277,26 +278,27 @@ static int emb_stmt_execute(MYSQL_STMT *stmt) { DBUG_ENTER("emb_stmt_execute"); char header[5]; - MYSQL_DATA *res; THD *thd; + my_bool res; int4store(header, stmt->stmt_id); header[4]= stmt->flags; thd= (THD*)stmt->mysql->thd; thd->client_param_count= stmt->param_count; thd->client_params= stmt->params; - if (emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE,0,0, - header, sizeof(header), 1, stmt) || - emb_read_query_result(stmt->mysql)) + + res= test(emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE, 0, 0, + header, sizeof(header), 1, stmt) || + emb_read_query_result(stmt->mysql)); + stmt->affected_rows= stmt->mysql->affected_rows; + stmt->insert_id= stmt->mysql->insert_id; + stmt->server_status= stmt->mysql->server_status; + if (res) { NET *net= &stmt->mysql->net; set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); DBUG_RETURN(1); } - stmt->affected_rows= stmt->mysql->affected_rows; - stmt->insert_id= stmt->mysql->insert_id; - stmt->server_status= stmt->mysql->server_status; - DBUG_RETURN(0); } diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index cb4fa104b4c..58a22686199 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -206,7 +206,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, } } - DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); + DBUG_PRINT("exit",("Mysql handler: 0x%lx", (long) mysql)); DBUG_RETURN(mysql); error: diff --git a/myisam/mi_close.c b/myisam/mi_close.c index 62f5617de1a..8a4f6ee7f5d 100644 --- a/myisam/mi_close.c +++ b/myisam/mi_close.c @@ -28,8 +28,9 @@ int mi_close(register MI_INFO *info) int error=0,flag; MYISAM_SHARE *share=info->s; DBUG_ENTER("mi_close"); - DBUG_PRINT("enter",("base: %lx reopen: %u locks: %u", - info,(uint) share->reopen, (uint) share->tot_locks)); + DBUG_PRINT("enter",("base: 0x%lx reopen: %u locks: %u", + (long) info, (uint) share->reopen, + (uint) share->tot_locks)); pthread_mutex_lock(&THR_LOCK_myisam); if (info->lock_type == F_EXTRA_LCK) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index c6e9da03adf..7515438f3a4 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -428,8 +428,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, key_segs) share.state.rec_per_key_part[key_segs-1]=1L; length+=key_length; - keydef->block_length= MI_BLOCK_SIZE(length-real_length_diff, - pointer,MI_MAX_KEYPTR_SIZE); + keydef->block_length= (uint16) MI_BLOCK_SIZE(length-real_length_diff, + pointer,MI_MAX_KEYPTR_SIZE); if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH || length >= MI_MAX_KEY_BUFF) { diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index 85cc60bdd9d..471420d99c0 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -165,7 +165,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo, DBUG_PRINT("error",("Couldn't allocate memory")); DBUG_RETURN(my_errno=ENOMEM); } - DBUG_PRINT("info",("root_page: %ld",old_root)); + DBUG_PRINT("info",("root_page: %ld", (long) old_root)); if (!_mi_fetch_keypage(info,keyinfo,old_root,DFLT_INIT_HITS,root_buff,0)) { error= -1; @@ -410,7 +410,7 @@ 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: 0x%lx", leaf_page, + DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx", (long) leaf_page, (ulong) keypos)); DBUG_DUMP("leaf_buff",(byte*) leaf_buff,mi_getint(leaf_buff)); @@ -597,7 +597,8 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo, else { /* Page is full */ endpos=anc_buff+anc_length; - DBUG_PRINT("test",("anc_buff: %lx endpos: %lx",anc_buff,endpos)); + DBUG_PRINT("test",("anc_buff: 0x%lx endpos: 0x%lx", + (long) anc_buff, (long) endpos)); if (keypos != anc_buff+2+key_reflength && !_mi_get_last_key(info,keyinfo,anc_buff,anc_key,keypos,&length)) goto err; @@ -775,7 +776,7 @@ static uint remove_key(MI_KEYDEF *keyinfo, uint nod_flag, int s_length; uchar *start; DBUG_ENTER("remove_key"); - DBUG_PRINT("enter",("keypos: %lx page_end: %lx",keypos,page_end)); + DBUG_PRINT("enter",("keypos: 0x%lx page_end: 0x%lx",(long) keypos, (long) page_end)); start=keypos; if (!(keyinfo->flag & diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index ef5ab73f1a9..6590e6bd92b 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -1066,8 +1066,8 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from, err: my_errno= HA_ERR_WRONG_IN_RECORD; - DBUG_PRINT("error",("to_end: %lx -> %lx from_end: %lx -> %lx", - to,to_end,from,from_end)); + DBUG_PRINT("error",("to_end: 0x%lx -> 0x%lx from_end: 0x%lx -> 0x%lx", + (long) to, (long) to_end, (long) from, (long) from_end)); DBUG_DUMP("from",(byte*) info->rec_buff,info->s->base.min_pack_length); DBUG_RETURN(MY_FILE_ERROR); } /* _mi_rec_unpack */ diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 01bd0c43119..c6f9799bd67 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -52,7 +52,7 @@ static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record); uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, const byte *record, my_off_t filepos) { - byte *pos,*end; + byte *pos; uchar *start; reg1 HA_KEYSEG *keyseg; my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT; @@ -107,18 +107,17 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, } if (keyseg->flag & HA_SPACE_PACK) { - end= pos + length; if (type != HA_KEYTYPE_NUM) { - while (end > pos && end[-1] == ' ') - end--; + length= cs->cset->lengthsp(cs, pos, length); } else { + byte *end= pos + length; while (pos < end && pos[0] == ' ') pos++; + length=(uint) (end-pos); } - length=(uint) (end-pos); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); memcpy((byte*) key,(byte*) pos,(size_t) char_length); @@ -403,8 +402,10 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr, pos= record+keyseg->start; if (keyseg->type != (int) HA_KEYTYPE_NUM) { - memcpy(pos,key,(size_t) length); - bfill(pos+length,keyseg->length-length,' '); + memcpy(pos,key,(size_t) length); + keyseg->charset->cset->fill(keyseg->charset, + pos + length, keyseg->length - length, + ' '); } else { diff --git a/myisam/mi_keycache.c b/myisam/mi_keycache.c index fb13f3703a2..d595be3a684 100644 --- a/myisam/mi_keycache.c +++ b/myisam/mi_keycache.c @@ -54,8 +54,8 @@ int mi_assign_to_key_cache(MI_INFO *info, int error= 0; MYISAM_SHARE* share= info->s; DBUG_ENTER("mi_assign_to_key_cache"); - DBUG_PRINT("enter",("old_key_cache_handle: %lx new_key_cache_handle: %lx", - share->key_cache, key_cache)); + DBUG_PRINT("enter",("old_key_cache_handle: 0x%lx new_key_cache_handle: 0x%lx", + (long) share->key_cache, (long) key_cache)); /* Skip operation if we didn't change key cache. This can happen if we diff --git a/myisam/mi_open.c b/myisam/mi_open.c index a52ab5aad1f..ab004ef8b5f 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -336,6 +336,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) goto err; } } + else if (pos->type == HA_KEYTYPE_BINARY) + pos->charset= &my_charset_bin; } if (share->keyinfo[i].flag & HA_SPATIAL) { @@ -1262,13 +1264,30 @@ int mi_enable_indexes(MI_INFO *info) RETURN 0 indexes are not disabled 1 all indexes are disabled - [2 non-unique indexes are disabled - NOT YET IMPLEMENTED] + 2 non-unique indexes are disabled */ int mi_indexes_are_disabled(MI_INFO *info) { MYISAM_SHARE *share= info->s; - return (! mi_is_any_key_active(share->state.key_map) && share->base.keys); + /* + No keys or all are enabled. keys is the number of keys. Left shifted + gives us only one bit set. When decreased by one, gives us all all bits + up to this one set and it gets unset. + */ + if (!share->base.keys || + (mi_is_all_keys_active(share->state.key_map, share->base.keys))) + return 0; + + /* All are disabled */ + if (mi_is_any_key_active(share->state.key_map)) + return 1; + + /* + We have keys. Some enabled, some disabled. + Don't check for any non-unique disabled but return directly 2 + */ + return 2; } diff --git a/myisam/mi_page.c b/myisam/mi_page.c index 5240c063fba..d18a10c3cde 100644 --- a/myisam/mi_page.c +++ b/myisam/mi_page.c @@ -27,7 +27,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo, uchar *tmp; uint page_size; DBUG_ENTER("_mi_fetch_keypage"); - DBUG_PRINT("enter",("page: %ld",page)); + DBUG_PRINT("enter",("page: %ld", (long) page)); tmp=(uchar*) key_cache_read(info->s->key_cache, info->s->kfile, page, level, (byte*) buff, @@ -80,7 +80,7 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, my_errno=EINVAL; DBUG_RETURN((-1)); } - DBUG_PRINT("page",("write page at: %lu",(long) page,buff)); + DBUG_PRINT("page",("write page at: %lu",(long) page)); DBUG_DUMP("buff",(byte*) buff,mi_getint(buff)); #endif diff --git a/myisam/mi_statrec.c b/myisam/mi_statrec.c index 42352f63c66..5e6ea939eca 100644 --- a/myisam/mi_statrec.c +++ b/myisam/mi_statrec.c @@ -255,8 +255,8 @@ int _mi_read_rnd_static_record(MI_INFO *info, byte *buf, if (filepos >= info->state->data_file_length) { DBUG_PRINT("test",("filepos: %ld (%ld) records: %ld del: %ld", - filepos/share->base.reclength,filepos, - info->state->records, info->state->del)); + (long) filepos/share->base.reclength, (long) filepos, + (long) info->state->records, (long) info->state->del)); fast_mi_writeinfo(info); DBUG_RETURN(my_errno=HA_ERR_END_OF_FILE); } diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c index 6a6dcb971a2..0959769992c 100644 --- a/myisam/mi_test2.c +++ b/myisam/mi_test2.c @@ -813,7 +813,7 @@ end: printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete); if (rec_pointer_size) printf("Record pointer size: %d\n",rec_pointer_size); - printf("myisam_block_size: %u\n", myisam_block_size); + printf("myisam_block_size: %lu\n", myisam_block_size); if (key_cacheing) { puts("Key cache used"); diff --git a/myisam/mi_write.c b/myisam/mi_write.c index 9ab8753f6d7..fb64ec2bb8b 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -339,7 +339,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, my_bool was_last_key; my_off_t next_page, dupp_key_pos; DBUG_ENTER("w_search"); - DBUG_PRINT("enter",("page: %ld",page)); + DBUG_PRINT("enter",("page: %ld", (long) page)); search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY; if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ @@ -462,7 +462,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *endpos, *prev_key; MI_KEY_PARAM s_temp; DBUG_ENTER("_mi_insert"); - DBUG_PRINT("enter",("key_pos: %lx",key_pos)); + DBUG_PRINT("enter",("key_pos: 0x%lx", (long) key_pos)); DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,USE_WHOLE_KEY);); nod_flag=mi_test_if_nod(anc_buff); @@ -483,8 +483,8 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo, { DBUG_PRINT("test",("t_length: %d ref_len: %d", t_length,s_temp.ref_length)); - DBUG_PRINT("test",("n_ref_len: %d n_length: %d key_pos: %lx", - s_temp.n_ref_length,s_temp.n_length,s_temp.key)); + DBUG_PRINT("test",("n_ref_len: %d n_length: %d key_pos: 0x%lx", + s_temp.n_ref_length,s_temp.n_length, (long) s_temp.key)); } #endif if (t_length > 0) @@ -677,7 +677,8 @@ uchar *_mi_find_half_pos(uint nod_flag, MI_KEYDEF *keyinfo, uchar *page, } while (page < end); *return_key_length=length; *after_key=page; - DBUG_PRINT("exit",("returns: %lx page: %lx half: %lx",lastpos,page,end)); + DBUG_PRINT("exit",("returns: 0x%lx page: 0x%lx half: 0x%lx", + (long) lastpos, (long) page, (long) end)); DBUG_RETURN(lastpos); } /* _mi_find_half_pos */ @@ -732,7 +733,8 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, } *return_key_length=last_length; *after_key=lastpos; - DBUG_PRINT("exit",("returns: %lx page: %lx end: %lx",prevpos,page,end)); + DBUG_PRINT("exit",("returns: 0x%lx page: 0x%lx end: 0x%lx", + (long) prevpos,(long) page,(long) end)); DBUG_RETURN(prevpos); } /* _mi_find_last_pos */ @@ -768,7 +770,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo, next_page= _mi_kpos(info->s->base.key_reflength, father_key_pos+father_keylength); buff=info->buff; - DBUG_PRINT("test",("use right page: %lu",next_page)); + DBUG_PRINT("test",("use right page: %lu", (ulong) next_page)); } else { @@ -777,7 +779,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo, next_page= _mi_kpos(info->s->base.key_reflength,father_key_pos); /* Fix that curr_buff is to left */ buff=curr_buff; curr_buff=info->buff; - DBUG_PRINT("test",("use left page: %lu",next_page)); + DBUG_PRINT("test",("use left page: %lu", (ulong) next_page)); } /* father_key_pos ptr to parting key */ if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff,0)) diff --git a/myisam/myisampack.c b/myisam/myisampack.c index e80a3ffacd9..c71fcce1d50 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -1105,18 +1105,18 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) my_off_t total_count; char llbuf[32]; - DBUG_PRINT("info", ("column: %3u", count - huff_counts + 1)); + DBUG_PRINT("info", ("column: %3u", (uint) (count - huff_counts + 1))); if (verbose >= 2) - VOID(printf("column: %3u\n", count - huff_counts + 1)); + VOID(printf("column: %3u\n", (uint) (count - huff_counts + 1))); if (count->tree_buff) { DBUG_PRINT("info", ("number of distinct values: %u", - (count->tree_pos - count->tree_buff) / - count->field_length)); + (uint) ((count->tree_pos - count->tree_buff) / + count->field_length))); if (verbose >= 2) VOID(printf("number of distinct values: %u\n", - (count->tree_pos - count->tree_buff) / - count->field_length)); + (uint) ((count->tree_pos - count->tree_buff) / + count->field_length))); } total_count= 0; for (idx= 0; idx < 256; idx++) @@ -1965,7 +1965,7 @@ static char *bindigits(ulonglong value, uint bits) DBUG_ASSERT(idx < sizeof(digits)); while (idx) - *(ptr++)= '0' + ((value >> (--idx)) & 1); + *(ptr++)= '0' + ((char) (value >> (--idx)) & (char) 1); *ptr= '\0'; return digits; } @@ -1995,7 +1995,7 @@ static char *hexdigits(ulonglong value) DBUG_ASSERT(idx < sizeof(digits)); while (idx) { - if ((*(ptr++)= '0' + ((value >> (4 * (--idx))) & 0xf)) > '9') + if ((*(ptr++)= '0' + ((char) (value >> (4 * (--idx))) & (char) 0xf)) > '9') *(ptr - 1)+= 'a' - '9' - 1; } *ptr= '\0'; @@ -2036,7 +2036,7 @@ static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees) uint huff_tree_bits; huff_tree_bits=max_bit(trees ? trees-1 : 0); - DBUG_PRINT("info", ("")); + DBUG_PRINT("info", (" ")); DBUG_PRINT("info", ("column types:")); DBUG_PRINT("info", ("FIELD_NORMAL 0")); DBUG_PRINT("info", ("FIELD_SKIP_ENDSPACE 1")); @@ -2048,12 +2048,12 @@ static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees) DBUG_PRINT("info", ("FIELD_ZERO 7")); DBUG_PRINT("info", ("FIELD_VARCHAR 8")); DBUG_PRINT("info", ("FIELD_CHECK 9")); - DBUG_PRINT("info", ("")); + DBUG_PRINT("info", (" ")); DBUG_PRINT("info", ("pack type as a set of flags:")); DBUG_PRINT("info", ("PACK_TYPE_SELECTED 1")); DBUG_PRINT("info", ("PACK_TYPE_SPACE_FIELDS 2")); DBUG_PRINT("info", ("PACK_TYPE_ZERO_FILL 4")); - DBUG_PRINT("info", ("")); + DBUG_PRINT("info", (" ")); if (verbose >= 2) { VOID(printf("\n")); @@ -2126,7 +2126,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) return 0; } - DBUG_PRINT("info", ("")); + DBUG_PRINT("info", (" ")); if (verbose >= 2) VOID(printf("\n")); tree_no= 0; @@ -2137,7 +2137,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) if (huff_tree->tree_number == 0) continue; /* Deleted tree */ tree_no++; - DBUG_PRINT("info", ("")); + DBUG_PRINT("info", (" ")); if (verbose >= 3) VOID(printf("\n")); /* Count the total number of elements (byte codes or column values). */ @@ -2280,11 +2280,11 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) { VOID(fflush(stdout)); VOID(fprintf(stderr, "error: Huffman code too long: %u/%u\n", - bits, 8 * sizeof(code))); + bits, (uint) (8 * sizeof(code)))); errors++; break; } - idx+= code & 1; + idx+= (uint) code & 1; if (idx >= length) { VOID(fflush(stdout)); @@ -2329,7 +2329,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) } flush_bits(); } - DBUG_PRINT("info", ("")); + DBUG_PRINT("info", (" ")); if (verbose >= 2) VOID(printf("\n")); my_afree((gptr) packed_tree); @@ -2507,7 +2507,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) end_pos-=count->max_zero_fill; field_length-=count->max_zero_fill; - switch(count->field_type) { + switch (count->field_type) { case FIELD_SKIP_ZERO: if (!memcmp((byte*) start_pos,zero_string,field_length)) { @@ -2726,6 +2726,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) break; } case FIELD_LAST: + case FIELD_enum_val_count: abort(); /* Impossible */ } start_pos+=count->max_zero_fill; @@ -2922,6 +2923,8 @@ static void flush_bits(void) bits-= 8; *file_buffer.pos++= (uchar) (bit_buffer >> bits); } + if (file_buffer.pos >= file_buffer.end) + VOID(flush_buffer(~ (ulong) 0)); file_buffer.bits= BITS_SAVED; file_buffer.bitbucket= 0; } diff --git a/myisammrg/myrg_extra.c b/myisammrg/myrg_extra.c index 62cf5f01aba..30bb46d27d4 100644 --- a/myisammrg/myrg_extra.c +++ b/myisammrg/myrg_extra.c @@ -28,7 +28,7 @@ int myrg_extra(MYRG_INFO *info,enum ha_extra_function function, int error,save_error=0; MYRG_TABLE *file; DBUG_ENTER("myrg_extra"); - DBUG_PRINT("info",("function: %d",(ulong) function)); + DBUG_PRINT("info",("function: %lu", (ulong) function)); if (function == HA_EXTRA_CACHE) { diff --git a/myisammrg/myrg_rkey.c b/myisammrg/myrg_rkey.c index f87b264081e..85464374d5d 100644 --- a/myisammrg/myrg_rkey.c +++ b/myisammrg/myrg_rkey.c @@ -88,7 +88,7 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key, mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; mi->once_flags|= RRND_PRESERVE_LASTINX; DBUG_PRINT("info", ("using table no: %d", - info->current_table - info->open_tables + 1)); + (int) (info->current_table - info->open_tables + 1))); DBUG_DUMP("result key", (byte*) mi->lastkey, mi->lastkey_length); DBUG_RETURN(_myrg_mi_read_record(mi,buf)); } diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 471ac9641d2..eff2ae740f5 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -59,12 +59,14 @@ dist-hook: $(INSTALL_DATA) $(srcdir)/t/*.opt $(srcdir)/t/*.slave-mi $(distdir)/t $(INSTALL_SCRIPT) $(srcdir)/t/*.sh $(distdir)/t $(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include + $(INSTALL_DATA) $(srcdir)/include/*.test $(distdir)/include $(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.frm $(distdir)/std_data + $(INSTALL_DATA) $(srcdir)/std_data/*.MY* $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(distdir)/lib $(INSTALL_DATA) $(srcdir)/lib/*.pl $(distdir)/lib @@ -88,6 +90,7 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/r/*.result $(DESTDIR)$(testdir)/r $(INSTALL_DATA) $(srcdir)/r/*.require $(DESTDIR)$(testdir)/r $(INSTALL_DATA) $(srcdir)/include/*.inc $(DESTDIR)$(testdir)/include + $(INSTALL_DATA) $(srcdir)/include/*.test $(DESTDIR)$(testdir)/include $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.*001 $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data @@ -95,6 +98,7 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.frm $(DESTDIR)$(testdir)/std_data + $(INSTALL_DATA) $(srcdir)/std_data/*.MY* $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(DESTDIR)$(testdir)/lib $(INSTALL_DATA) $(srcdir)/lib/*.pl $(DESTDIR)$(testdir)/lib diff --git a/mysql-test/include/federated.inc b/mysql-test/include/federated.inc index 1c53b9ed2c5..15230f47ed8 100644 --- a/mysql-test/include/federated.inc +++ b/mysql-test/include/federated.inc @@ -5,7 +5,7 @@ source ./include/master-slave.inc; # remote table creation connection slave; ---replicate-ignore-db=federated +#--replicate-ignore-db=federated stop slave; --disable_warnings diff --git a/mysql-test/include/sp-vars.inc b/mysql-test/include/sp-vars.inc index 4bac883ee0e..c241af2fb54 100644 --- a/mysql-test/include/sp-vars.inc +++ b/mysql-test/include/sp-vars.inc @@ -1,6 +1,6 @@ delimiter |; ---------------------------------------------------------------------------- +# -------------------------------------------------------------------------- CREATE PROCEDURE sp_vars_check_dflt() BEGIN @@ -40,7 +40,7 @@ BEGIN SELECT v17, v18, v19, v20; END| ---------------------------------------------------------------------------- +# -------------------------------------------------------------------------- CREATE PROCEDURE sp_vars_check_assignment() BEGIN @@ -89,35 +89,35 @@ BEGIN 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| ---------------------------------------------------------------------------- +# -------------------------------------------------------------------------- CREATE FUNCTION sp_vars_div_zero() RETURNS INTEGER BEGIN @@ -126,6 +126,6 @@ BEGIN RETURN div_zero; END| ---------------------------------------------------------------------------- +# -------------------------------------------------------------------------- delimiter ;| diff --git a/mysql-test/include/strict_autoinc.inc b/mysql-test/include/strict_autoinc.inc index 6960440f3a7..823efcc2040 100644 --- a/mysql-test/include/strict_autoinc.inc +++ b/mysql-test/include/strict_autoinc.inc @@ -2,6 +2,10 @@ # Test for strict-mode autoincrement # +--disable_warnings +drop table if exists t1; +--enable_warnings + set @org_mode=@@sql_mode; eval create table t1 ( diff --git a/mysql-test/install_test_db.sh b/mysql-test/install_test_db.sh index 4554b92857e..c30583503dc 100644 --- a/mysql-test/install_test_db.sh +++ b/mysql-test/install_test_db.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (C) 1997-2002 MySQL AB +# Copyright (C) 1997-2006 MySQL AB # For a more info consult the file COPYRIGHT distributed with this file # This scripts creates the privilege tables db, host, user, tables_priv, @@ -7,19 +7,26 @@ if [ x$1 = x"--bin" ]; then shift 1 + BINARY_DIST=1 + + bindir=../bin + scriptdir=../bin + libexecdir=../libexec # Check if it's a binary distribution or a 'make install' if test -x ../libexec/mysqld then execdir=../libexec + elif test -x ../../sbin/mysqld # RPM installation + then + execdir=../../sbin + bindir=../../bin + scriptdir=../../bin + libexecdir=../../libexec else execdir=../bin fi - bindir=../bin - BINARY_DIST=1 fix_bin=mysql-test - scriptdir=../bin - libexecdir=../libexec else execdir=../sql bindir=../client diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 9e943fec9ef..a00d06d2e60 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -288,6 +288,7 @@ sub collect_one_test_case($$$$$$$) { $tinfo->{'timezone'}= "GMT-3"; # for UNIX_TIMESTAMP tests to work $tinfo->{'slave_num'}= 0; # Default, no slave + $tinfo->{'master_num'}= 1; # Default, 1 master if ( defined mtr_match_prefix($tname,"rpl") ) { if ( $::opt_skip_rpl ) @@ -297,13 +298,8 @@ sub collect_one_test_case($$$$$$$) { return; } - $tinfo->{'slave_num'}= 1; # Default for rpl* tests, use one slave - if ( $tname eq 'rpl_failsafe' or $tname eq 'rpl_chain_temp_table' ) - { - # $tinfo->{'slave_num'}= 3; # Not 3 ? Check old code, strange - } } if ( defined mtr_match_prefix($tname,"federated") ) @@ -582,6 +578,7 @@ our @tags= ["include/have_debug.inc", "need_debug", 1], ["include/have_ndb.inc", "ndb_test", 1], ["include/have_ndb_extra.inc", "ndb_extra", 1], + ["include/have_multi_ndb.inc", "master_num", 2], ["require_manager", "require_manager", 1], ); diff --git a/mysql-test/lib/mtr_im.pl b/mysql-test/lib/mtr_im.pl index ca17516278e..967e92dfcdd 100644 --- a/mysql-test/lib/mtr_im.pl +++ b/mysql-test/lib/mtr_im.pl @@ -582,7 +582,7 @@ sub mtr_im_start($$) { mtr_add_arg($args, $opt); } - $im->{'pid'} = + $im->{'spawner_pid'} = mtr_spawn( $::exe_im, # path to the executable $args, # cmd-line args @@ -593,7 +593,7 @@ sub mtr_im_start($$) { { append_log_file => 1 } # append log files ); - unless ( $im->{'pid'} ) + unless ( $im->{'spawner_pid'} ) { mtr_error('Could not start Instance Manager.') } diff --git a/mysql-test/lib/mtr_io.pl b/mysql-test/lib/mtr_io.pl index 09749bc74e3..842dc09413d 100644 --- a/mysql-test/lib/mtr_io.pl +++ b/mysql-test/lib/mtr_io.pl @@ -41,6 +41,7 @@ sub mtr_get_pid_from_file ($) { # Read pid number from file my $pid= <FILE>; + chomp $pid; close FILE; return $pid if $pid=~ /^(\d+)/; diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl index 846ca25b725..f28e25e5966 100644 --- a/mysql-test/lib/mtr_misc.pl +++ b/mysql-test/lib/mtr_misc.pl @@ -134,6 +134,7 @@ sub mtr_exe_maybe_exists (@) { my @path= @_; map {$_.= ".exe"} @path if $::glob_win32; + map {$_.= ".nlm"} @path if $::glob_netware; foreach my $path ( @path ) { if($::glob_win32) diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index 9d0c1f601ba..cf0e4c214ed 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -220,7 +220,8 @@ sub spawn_parent_impl { my $ret_pid= waitpid($pid,0); if ( $ret_pid != $pid ) { - mtr_error("$path ($pid) got lost somehow"); + mtr_error("waitpid($pid, 0) returned $ret_pid " . + "when waiting for '$path'"); } return mtr_process_exit_status($?); @@ -708,7 +709,7 @@ sub mtr_wait_blocking($) { } } -# Start "mysqladmin shutdown" for a specific mysqld +# Start "mysqladmin <command>" for a specific mysqld sub mtr_mysqladmin_start($$$) { my $srv= shift; my $command= shift; @@ -738,9 +739,8 @@ sub mtr_mysqladmin_start($$$) { # Shutdown time must be high as slave may be in reconnect mtr_add_arg($args, "--shutdown_timeout=$adm_shutdown_tmo"); mtr_add_arg($args, "$command"); - my $path_mysqladmin_log= "$::opt_vardir/log/mysqladmin.log"; my $pid= mtr_spawn($::exe_mysqladmin, $args, - "", $path_mysqladmin_log, $path_mysqladmin_log, "", + "", "", "", "", { append_log_file => 1 }); mtr_verbose("mtr_mysqladmin_start, pid: $pid"); return $pid; @@ -937,6 +937,12 @@ sub check_expected_crash_and_restart($) } } } + + if ($::instance_manager->{'spawner_pid'} eq $ret_pid) + { + return; + } + mtr_warning("check_expected_crash_and_restart couldn't find an entry for pid: $ret_pid"); } @@ -1053,7 +1059,7 @@ sub sleep_until_file_created ($$$) { # Print extra message every 60 seconds my $seconds= ($loop * $sleeptime) / 1000; - if ( $seconds > 1 and int($seconds) % 60 == 0 ) + if ( $seconds > 1 and int($seconds * 10) % 600 == 0 ) { my $left= $timeout - $seconds; mtr_warning("Waited $seconds seconds for $pidfile to be created, " . diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index 758e98984b8..a2c16e1941a 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -94,10 +94,14 @@ sub mtr_report_test_skipped ($) { { print "[ disabled ] $tinfo->{'comment'}\n"; } - else + elsif ( $tinfo->{'comment'} ) { print "[ skipped ] $tinfo->{'comment'}\n"; } + else + { + print "[ skipped ]\n"; + } } sub mtr_report_tests_not_skipped_though_disabled ($) { diff --git a/mysql-test/lib/mtr_unique.pl b/mysql-test/lib/mtr_unique.pl new file mode 100644 index 00000000000..a8fb320c773 --- /dev/null +++ b/mysql-test/lib/mtr_unique.pl @@ -0,0 +1,156 @@ +# +# This file is used from mysql-test-run.pl when choosing +# port numbers and directories to use for running mysqld. +# + +use strict; +use Fcntl ':flock'; + +# +# Requested IDs are stored in a hash and released upon END. +# +my %mtr_unique_assigned_ids = (); +END { + while(my ($id,$file) = each(%mtr_unique_assigned_ids)) { + print "Autoreleasing $file:$id\n"; + mtr_release_unique_id($file, $id); + } +} + +# +# Require a unique, numerical ID, given a file name (where all +# requested IDs are stored), a minimum and a maximum value. +# +# We use flock to implement locking for the ID file and ignore +# possible problems arising from lack of support for it on +# some platforms (it should work on most, and the possible +# race condition would occur rarely). The proper solution for +# this is a daemon that manages IDs, of course. +# +# If no unique ID within the specified parameters can be +# obtained, return undef. +# +sub mtr_require_unique_id($$$) { + my $file = shift; + my $min = shift; + my $max = shift; + my $ret = undef; + my $changed = 0; + + my $can_use_ps = `ps -e | grep '^[ ]*$$ '`; + + if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { + die 'lock file is a symbolic link'; + } + + chmod 0777, "$file.sem"; + open SEM, ">", "$file.sem" or die "can't write to $file.sem"; + flock SEM, LOCK_EX or die "can't lock $file.sem"; + if(! -e $file) { + open FILE, ">", $file or die "can't create $file"; + close FILE; + } + + if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { + die 'lock file is a symbolic link'; + } + + chmod 0777, $file; + open FILE, "+<", $file or die "can't open $file"; + select undef,undef,undef,0.2; + seek FILE, 0, 0; + my %taken = (); + while(<FILE>) { + chomp; + my ($id, $pid) = split / /; + $taken{$id} = $pid; + if($can_use_ps) { + my $res = `ps -e | grep '^[ ]*$pid '`; + if(!$res) { + print "Ignoring slot $id used by missing process $pid.\n"; + delete $taken{$id}; + ++$changed; + } + } + } + for(my $i=$min; $i<=$max; ++$i) { + if(! exists $taken{$i}) { + $ret = $i; + $taken{$i} = $$; + ++$changed; + last; + } + } + if($changed) { + seek FILE, 0, 0; + truncate FILE, 0 or die "can't truncate $file"; + for my $k (keys %taken) { + print FILE $k . ' ' . $taken{$k} . "\n"; + } + } + close FILE; + flock SEM, LOCK_UN or warn "can't unlock $file.sem"; + close SEM; + $mtr_unique_assigned_ids{$ret} = $file if defined $ret; + return $ret; +} + +# +# Require a unique ID like above, but sleep if no ID can be +# obtained immediately. +# +sub mtr_require_unique_id_and_wait($$$) { + my $ret = mtr_require_unique_id($_[0],$_[1],$_[2]); + while(! defined $ret) { + sleep 30; + $ret = mtr_require_unique_id($_[0],$_[1],$_[2]); + print "Waiting for unique id to become available...\n" unless $ret; + } + return $ret; +} + +# +# Release a unique ID. +# +sub mtr_release_unique_id($$) { + my $file = shift; + my $myid = shift; + + if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { + die 'lock file is a symbolic link'; + } + + open SEM, ">", "$file.sem" or die "can't write to $file.sem"; + flock SEM, LOCK_EX or die "can't lock $file.sem"; + + if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { + die 'lock file is a symbolic link'; + } + + if(! -e $file) { + open FILE, ">", $file or die "can't create $file"; + close FILE; + } + open FILE, "+<", $file or die "can't open $file"; + select undef,undef,undef,0.2; + seek FILE, 0, 0; + my %taken = (); + while(<FILE>) { + chomp; + my ($id, $pid) = split / /; + $taken{$id} = $pid; + } + delete $taken{$myid}; + seek FILE, 0, 0; + truncate FILE, 0 or die "can't truncate $file"; + for my $k (keys %taken) { + print FILE $k . ' ' . $taken{$k} . "\n"; + } + close FILE; + flock SEM, LOCK_UN or warn "can't unlock $file.sem"; + close SEM; + delete $mtr_unique_assigned_ids{$myid}; +} + +1; + diff --git a/mysql-test/mysql-test-run-shell.sh b/mysql-test/mysql-test-run-shell.sh index 9e19a8cad7e..a81a3b8b607 100644 --- a/mysql-test/mysql-test-run-shell.sh +++ b/mysql-test/mysql-test-run-shell.sh @@ -123,7 +123,7 @@ find_valgrind() fi # >=2.1.2 requires the --tool option, some versions write to stdout, some to stderr valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && FIND_VALGRIND="$FIND_VALGRIND --tool=memcheck" - FIND_VALGRIND="$FIND_VALGRIND --alignment=8 --leak-check=yes --num-callers=16 --suppressions=$CWD/valgrind.supp" + FIND_VALGRIND="$FIND_VALGRIND --alignment=8 --leak-check=yes --num-callers=16 --suppressions=$MYSQL_TEST_DIR/valgrind.supp" } # No paths below as we can't be sure where the program is! @@ -174,18 +174,24 @@ fi # Misc. Definitions #-- -if [ -d ../sql ] ; then +# BASEDIR is always above mysql-test directory ... +MYSQL_TEST_DIR=`pwd` +cd .. + +if [ -d ./sql ] ; then SOURCE_DIST=1 else BINARY_DIST=1 -fi -#BASEDIR is always one above mysql-test directory -CWD=`pwd` -cd .. + # ... one level for tar.gz, two levels for a RPM installation + if [ ! -f ./bin/mysql_upgrade ] ; then + # Has to be RPM installation + cd .. + fi +fi BASEDIR=`pwd` -cd $CWD -MYSQL_TEST_DIR=$BASEDIR/mysql-test + +cd $MYSQL_TEST_DIR MYSQL_TEST_WINDIR=$MYSQL_TEST_DIR MYSQLTEST_VARDIR=$MYSQL_TEST_DIR/var export MYSQL_TEST_DIR MYSQL_TEST_WINDIR MYSQLTEST_VARDIR @@ -744,8 +750,15 @@ else if test -x "$BASEDIR/libexec/mysqld" then MYSQLD="$VALGRIND $BASEDIR/libexec/mysqld" - else + elif test -x "$BASEDIR/bin/mysqld" + then MYSQLD="$VALGRIND $BASEDIR/bin/mysqld" + elif test -x "$BASEDIR/sbin/mysqld" + then + MYSQLD="$VALGRIND $BASEDIR/sbin/mysqld" + else + $ECHO "Fatal error: Cannot find program mysqld in $BASEDIR/{libexec,bin,sbin}" 1>&2 + exit 1 fi CLIENT_BINDIR="$BASEDIR/bin" if test -d "$BASEDIR/tests" @@ -1390,7 +1403,7 @@ start_master() then $ECHO "set args $master_args" > $GDB_MASTER_INIT$1 $ECHO "To start gdb for the master , type in another window:" - $ECHO "cd $CWD ; gdb -x $GDB_MASTER_INIT$1 $MASTER_MYSQLD" + $ECHO "cd $MYSQL_TEST_DIR ; gdb -x $GDB_MASTER_INIT$1 $MASTER_MYSQLD" wait_for_master=1500 else ( $ECHO set args $master_args; @@ -1508,7 +1521,7 @@ start_slave() then $ECHO "set args $slave_args" > $GDB_SLAVE_INIT echo "To start gdb for the slave, type in another window:" - echo "cd $CWD ; gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD" + echo "cd $MYSQL_TEST_DIR ; gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD" wait_for_slave=1500 else ( $ECHO set args $slave_args; @@ -2074,12 +2087,15 @@ then # Remove files that can cause problems $RM -rf $MYSQL_TEST_DIR/var/ndbcluster - $RM -f $MYSQL_TEST_DIR/var/run/* $MYSQL_TEST_DIR/var/tmp/* + $RM -rf $MYSQL_TEST_DIR/var/run/* $MYSQL_TEST_DIR/var/tmp/* # Remove old berkeley db log files that can confuse the server $RM -f $MASTER_MYDDIR/log.* $RM -f $MASTER_MYDDIR"1"/log.* + # Remove old log and reject files + $RM -f r/*.reject r/*.progress r/*.log r/*.warnings + wait_for_master=$SLEEP_TIME_FOR_FIRST_MASTER wait_for_slave=$SLEEP_TIME_FOR_FIRST_SLAVE $ECHO "Installing Test Databases" diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 8a1d9b50f47..bf5915cfc1c 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -63,10 +63,8 @@ use Getopt::Long; use Sys::Hostname; use IO::Socket; use IO::Socket::INET; -use Data::Dumper; use strict; use warnings; -use diagnostics; select(STDOUT); $| = 1; # Automatically flush STDOUT @@ -88,6 +86,7 @@ require "lib/mtr_diff.pl"; require "lib/mtr_match.pl"; require "lib/mtr_misc.pl"; require "lib/mtr_stress.pl"; +require "lib/mtr_unique.pl"; $Devel::Trace::TRACE= 1; @@ -203,6 +202,7 @@ our $opt_client_ddd; our $opt_manual_gdb; our $opt_manual_ddd; our $opt_manual_debug; +our $opt_mtr_build_thread=0; our $opt_debugger; our $opt_client_debugger; @@ -217,18 +217,25 @@ our $clusters; our $instance_manager; +our $opt_master_myport; +our $opt_slave_myport; +our $im_port; +our $im_mysqld1_port; +our $im_mysqld2_port; our $opt_ndbcluster_port; our $opt_ndbconnectstring; our $opt_ndbcluster_port_slave; our $opt_ndbconnectstring_slave; our $opt_record; -our $opt_report_features; +my $opt_report_features; our $opt_check_testcases; +our $opt_mark_progress; our $opt_skip; our $opt_skip_rpl; our $max_slave_num= 0; +our $max_master_num= 1; our $use_innodb; our $opt_skip_test; our $opt_skip_im; @@ -240,8 +247,6 @@ our $opt_suite_timeout; my $default_testcase_timeout= 15; # 15 min max my $default_suite_timeout= 180; # 3 hours max -our $opt_source_dist; - our $opt_start_and_exit; our $opt_start_dirty; our $opt_start_from; @@ -301,6 +306,8 @@ our $glob_tot_real_time= 0; our %mysqld_variables; +my $source_dist= 0; + ###################################################################### # @@ -311,11 +318,13 @@ our %mysqld_variables; sub main (); sub initial_setup (); sub command_line_setup (); -sub datadir_setup (); +sub set_mtr_build_thread_ports($); +sub datadir_list_setup (); sub executable_setup (); sub environment_setup (); sub kill_running_servers (); -sub cleanup_stale_files (); +sub remove_stale_vardir (); +sub setup_vardir (); sub check_ssl_support ($); sub check_running_as_root(); sub check_ndbcluster_support ($); @@ -405,6 +414,15 @@ sub main () { $max_slave_num= $test->{slave_num}; mtr_error("Too many slaves") if $max_slave_num > 3; } + + # Count max number of masters used by a test case + if ( $test->{master_num} > $max_master_num) + { + $max_master_num= $test->{master_num}; + mtr_error("Too many masters") if $max_master_num > 2; + mtr_error("Too few masters") if $max_master_num < 1; + } + $use_innodb||= $test->{'innodb_test'}; } @@ -439,7 +457,6 @@ sub main () { mtr_exit(0); } - ############################################################################## # # Default settings @@ -453,45 +470,26 @@ sub command_line_setup () { $opt_suite= "main"; # Special default suite my $opt_comment; - my $opt_master_myport= 9306; - my $opt_slave_myport= 9308; + $opt_master_myport= 9306; + $opt_slave_myport= 9308; $opt_ndbcluster_port= 9310; $opt_ndbcluster_port_slave= 9311; - my $im_port= 9312; - my $im_mysqld1_port= 9313; - my $im_mysqld2_port= 9314; - - # - # 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. - # - # Note the MASTER_MYPORT has to be set the same in all 4.x and 5.x - # versions of this script, else a 4.0 test run might conflict with a - # 5.1 test run, even if different MTR_BUILD_THREAD is used. This means - # all port numbers might not be used in this version of the script. - # - # Also note the limiteation of ports we are allowed to hand out. This - # differs between operating systems and configuration, see - # http://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html - # But a fairly safe range seems to be 5001 - 32767 - if ( $ENV{'MTR_BUILD_THREAD'} ) - { - # Up to two masters, up to three slaves - $opt_master_myport= $ENV{'MTR_BUILD_THREAD'} * 10 + 10000; # and 1 - $opt_slave_myport= $opt_master_myport + 2; # and 3 4 - $opt_ndbcluster_port= $opt_master_myport + 5; - $opt_ndbcluster_port_slave= $opt_master_myport + 6; - $im_port= $opt_master_myport + 7; - $im_mysqld1_port= $opt_master_myport + 8; - $im_mysqld2_port= $opt_master_myport + 9; + $im_port= 9312; + $im_mysqld1_port= 9313; + $im_mysqld2_port= 9314; + + # If so requested, we try to avail ourselves of a unique build thread number. + if ( $ENV{'MTR_BUILD_THREAD'} ) { + if ( lc($ENV{'MTR_BUILD_THREAD'}) eq 'auto' ) { + print "Requesting build thread... "; + $ENV{'MTR_BUILD_THREAD'} = mtr_require_unique_id_and_wait("/tmp/mysql-test-ports", 200, 299); + print "got ".$ENV{'MTR_BUILD_THREAD'}."\n"; + } } - if ( $opt_master_myport < 5001 or $opt_master_myport + 10 >= 32767 ) + if ( $ENV{'MTR_BUILD_THREAD'} ) { - mtr_error("MTR_BUILD_THREAD number results in a port", - "outside 5001 - 32767", - "($opt_master_myport - $opt_master_myport + 10)"); + set_mtr_build_thread_ports($ENV{'MTR_BUILD_THREAD'}); } # This is needed for test log evaluation in "gen-build-status-page" @@ -543,10 +541,12 @@ sub command_line_setup () { 'im-port=i' => \$im_port, # Instance Manager port. 'im-mysqld1-port=i' => \$im_mysqld1_port, # Port of mysqld, controlled by IM 'im-mysqld2-port=i' => \$im_mysqld2_port, # Port of mysqld, controlled by IM + 'mtr-build-thread=i' => \$opt_mtr_build_thread, # Test case authoring 'record' => \$opt_record, 'check-testcases' => \$opt_check_testcases, + 'mark-progress' => \$opt_mark_progress, # Extra options used when starting mysqld 'mysqld=s' => \@opt_extra_mysqld_opt, @@ -623,6 +623,15 @@ sub command_line_setup () { $glob_scriptname= basename($0); + if ($opt_mtr_build_thread != 0) + { + set_mtr_build_thread_ports($opt_mtr_build_thread) + } + elsif ($ENV{'MTR_BUILD_THREAD'}) + { + $opt_mtr_build_thread= $ENV{'MTR_BUILD_THREAD'}; + } + # We require that we are in the "mysql-test" directory # to run mysql-test-run if (! -f $glob_scriptname) @@ -634,12 +643,12 @@ sub command_line_setup () { if ( -d "../sql" ) { - $opt_source_dist= 1; + $source_dist= 1; } $glob_hostname= mtr_short_hostname(); - # 'basedir' is always parent of "mysql-test" directory + # Find the absolute path to the test directory $glob_mysql_test_dir= cwd(); if ( $glob_cygwin_perl ) { @@ -647,14 +656,30 @@ sub command_line_setup () { $glob_mysql_test_dir= `cygpath -m "$glob_mysql_test_dir"`; chomp($glob_mysql_test_dir); } - $glob_basedir= dirname($glob_mysql_test_dir); + + # In most cases, the base directory we find everything relative to, + # is the parent directory of the "mysql-test" directory. For source + # distributions, TAR binary distributions and some other packages. + $glob_basedir= dirname($glob_mysql_test_dir); + + # In the RPM case, binaries and libraries are installed in the + # default system locations, instead of having our own private base + # directory. And we install "/usr/share/mysql-test". Moving up one + # more directory relative to "mysql-test" gives us a usable base + # directory for RPM installs. + if ( ! $source_dist and ! -d "$glob_basedir/bin" ) + { + $glob_basedir= dirname($glob_basedir); + } # Expect mysql-bench to be located adjacent to the source tree, by default $glob_mysql_bench_dir= "$glob_basedir/../mysql-bench" unless defined $glob_mysql_bench_dir; + $glob_mysql_bench_dir= undef + unless -d $glob_mysql_bench_dir; $path_my_basedir= - $opt_source_dist ? $glob_mysql_test_dir : $glob_basedir; + $source_dist ? $glob_mysql_test_dir : $glob_basedir; $glob_timers= mtr_init_timers(); @@ -663,7 +688,7 @@ sub command_line_setup () { # number as early as possible # - # Look for the client binaries + # Look for the client binaries directory $path_client_bindir= mtr_path_exists("$glob_basedir/client_release", "$glob_basedir/client_debug", vs_config_dirs('client', ''), @@ -679,7 +704,8 @@ sub command_line_setup () { "$path_client_bindir/mysqld-debug", "$path_client_bindir/mysqld-max", "$glob_basedir/libexec/mysqld", - "$glob_basedir/bin/mysqld"); + "$glob_basedir/bin/mysqld", + "$glob_basedir/sbin/mysqld"); # Use the mysqld found above to find out what features are available collect_mysqld_features(); @@ -754,7 +780,7 @@ sub command_line_setup () { { mtr_report("Using tmpfs in $fs"); $opt_mem= "$fs/var"; - $opt_mem .= $ENV{'MTR_BUILD_THREAD'} if $ENV{'MTR_BUILD_THREAD'}; + $opt_mem .= $opt_mtr_build_thread if $opt_mtr_build_thread; last; } } @@ -909,7 +935,7 @@ sub command_line_setup () { # -------------------------------------------------------------------------- # Gcov flag # -------------------------------------------------------------------------- - if ( $opt_gcov and ! $opt_source_dist ) + if ( $opt_gcov and ! $source_dist ) { mtr_error("Coverage test needs the source - please use source dist"); } @@ -1177,6 +1203,7 @@ sub command_line_setup () { # Setup master->[0] with the settings for the extern server $master->[0]->{'path_sock'}= $opt_socket if $opt_socket; + mtr_report("Using extern server at '$master->[0]->{path_sock}'"); } else { @@ -1190,14 +1217,71 @@ sub command_line_setup () { $path_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log"; $path_snapshot= "$opt_tmpdir/snapshot_$opt_master_myport/"; + + if ( $opt_valgrind and $opt_debug ) + { + # When both --valgrind and --debug is selected, send + # all output to the trace file, making it possible to + # see the exact location where valgrind complains + foreach my $mysqld (@{$master}, @{$slave}) + { + my $sidx= $mysqld->{idx} ? "$mysqld->{idx}" : ""; + $mysqld->{path_myerr}= + "$opt_vardir/log/" . $mysqld->{type} . "$sidx.trace"; + } + } +} + +# +# 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. +# +# Note the MASTER_MYPORT has to be set the same in all 4.x and 5.x +# versions of this script, else a 4.0 test run might conflict with a +# 5.1 test run, even if different MTR_BUILD_THREAD is used. This means +# all port numbers might not be used in this version of the script. +# +# Also note the limitation of ports we are allowed to hand out. This +# differs between operating systems and configuration, see +# http://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html +# But a fairly safe range seems to be 5001 - 32767 +# + +sub set_mtr_build_thread_ports($) { + my $mtr_build_thread= shift; + + if ( lc($mtr_build_thread) eq 'auto' ) { + print "Requesting build thread... "; + $ENV{'MTR_BUILD_THREAD'} = $mtr_build_thread = mtr_require_unique_id_and_wait("/tmp/mysql-test-ports", 200, 299); + print "got ".$mtr_build_thread."\n"; + } + + # Up to two masters, up to three slaves + $opt_master_myport= $mtr_build_thread * 10 + 10000; # and 1 + $opt_slave_myport= $opt_master_myport + 2; # and 3 4 + $opt_ndbcluster_port= $opt_master_myport + 5; + $opt_ndbcluster_port_slave= $opt_master_myport + 6; + $im_port= $opt_master_myport + 7; + $im_mysqld1_port= $opt_master_myport + 8; + $im_mysqld2_port= $opt_master_myport + 9; + + if ( $opt_master_myport < 5001 or $opt_master_myport + 10 >= 32767 ) + { + mtr_error("MTR_BUILD_THREAD number results in a port", + "outside 5001 - 32767", + "($opt_master_myport - $opt_master_myport + 10)"); + } } -sub datadir_setup () { + +sub datadir_list_setup () { # Make a list of all data_dirs - @data_dir_lst = ( - $master->[0]->{'path_myddir'}, - $master->[1]->{'path_myddir'}); + for (my $idx= 0; $idx < $max_master_num; $idx++) + { + push(@data_dir_lst, $master->[$idx]->{'path_myddir'}); + } for (my $idx= 0; $idx < $max_slave_num; $idx++) { @@ -1222,26 +1306,15 @@ sub datadir_setup () { sub collect_mysqld_features () { - # - # Execute "mysqld --no-defaults --help --verbose", that will - # print out version and a list of all features and settings - # my $found_variable_list_start= 0; - my $spec_file= "$glob_mysql_test_dir/mysqld.spec.$$"; - if ( mtr_run($exe_mysqld, - ["--no-defaults", - "--verbose", - "--help"], - "", "$spec_file", "$spec_file", "") != 0 ) - { - mtr_error("Failed to get version and list of features from %s", - $exe_mysqld); - } - my $F= IO::File->new($spec_file) or - mtr_error("can't open file \"$spec_file\": $!"); + # + # Execute "mysqld --no-defaults --help --verbose" to get a + # of all features and settings + # + my $list= `$exe_mysqld --no-defaults --verbose --help`; - while ( my $line= <$F> ) + foreach my $line (split('\n', $list)) { # First look for version if ( !$mysql_version_id ) @@ -1294,7 +1367,7 @@ sub collect_mysqld_features () { } } } - unlink($spec_file); + mtr_error("Could not find version of MySQL") unless $mysql_version_id; mtr_error("Could not find variabes list") unless $found_variable_list_start; @@ -1308,7 +1381,8 @@ sub executable_setup_im () { mtr_exe_maybe_exists( "$glob_basedir/server-tools/instance-manager/mysqlmanager", "$glob_basedir/libexec/mysqlmanager", - "$glob_basedir/bin/mysqlmanager"); + "$glob_basedir/bin/mysqlmanager", + "$glob_basedir/sbin/mysqlmanager"); return ($exe_im eq ""); } @@ -1417,7 +1491,8 @@ sub executable_setup () { # Look for mysql_fix_privilege_tables.sql script $file_mysql_fix_privilege_tables= - mtr_file_exists("$glob_basedir/scripts/mysql_fix_privilege_tables.sql"); + mtr_file_exists("$glob_basedir/scripts/mysql_fix_privilege_tables.sql", + "$glob_basedir/share/mysql_fix_privilege_tables.sql"); if ( ! $opt_skip_ndbcluster and executable_setup_ndb()) { @@ -1572,10 +1647,11 @@ sub environment_setup () { # Setup LD_LIBRARY_PATH so the libraries from this distro/clone # are used in favor of the system installed ones # -------------------------------------------------------------------------- - if ( $opt_source_dist ) + if ( $source_dist ) { push(@ld_library_paths, "$glob_basedir/libmysql/.libs/", - "$glob_basedir/libmysql_r/.libs/"); + "$glob_basedir/libmysql_r/.libs/", + "$glob_basedir/zlib.libs/"); } else { @@ -1650,11 +1726,12 @@ sub environment_setup () { $ENV{'SLAVE_MYPORT1'}= $slave->[1]->{'port'}; $ENV{'SLAVE_MYPORT2'}= $slave->[2]->{'port'}; $ENV{'MYSQL_TCP_PORT'}= $mysqld_variables{'port'}; + $ENV{'DEFAULT_MASTER_PORT'}= $mysqld_variables{'master-port'}; $ENV{'IM_PATH_SOCK'}= $instance_manager->{path_sock}; $ENV{'IM_USERNAME'}= $instance_manager->{admin_login}; $ENV{'IM_PASSWORD'}= $instance_manager->{admin_password}; - $ENV{MTR_BUILD_THREAD}= 0 unless $ENV{MTR_BUILD_THREAD}; # Set if not set + $ENV{MTR_BUILD_THREAD}= $opt_mtr_build_thread; $ENV{'EXE_MYSQL'}= $exe_mysql; @@ -1855,6 +1932,10 @@ sub environment_setup () { # ---------------------------------------------------- $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= $exe_my_print_defaults; + # ---------------------------------------------------- + # Setup env so childs can execute mysqladmin + # ---------------------------------------------------- + $ENV{'MYSQLADMIN'}= $exe_mysqladmin; # ---------------------------------------------------- # Setup env so childs can execute perror @@ -1949,29 +2030,23 @@ sub kill_running_servers () { # This is different from terminating processes we have # started from this run of the script, this is terminating # leftovers from previous runs. - - if ( ! -d $opt_vardir ) - { - if ( -l $opt_vardir and ! -d readlink($opt_vardir) ) - { - mtr_report("Removing $opt_vardir symlink without destination"); - unlink($opt_vardir); - } - # The "var" dir does not exist already - # the processes that mtr_kill_leftovers start will write - # their log files to var/log so it should be created - mkpath("$opt_vardir/log"); - } mtr_kill_leftovers(); } } -sub cleanup_stale_files () { - - my $created_by_mem_file= "$glob_mysql_test_dir/var/created_by_mem"; +# +# Remove var and any directories in var/ created by previous +# tests +# +sub remove_stale_vardir () { mtr_report("Removing Stale Files"); + # Safety! + mtr_error("No, don't remove the vardir when running with --extern") + if $opt_extern; + + mtr_verbose("opt_vardir: $opt_vardir"); if ( $opt_vardir eq $default_vardir ) { # @@ -1980,29 +2055,47 @@ sub cleanup_stale_files () { if ( -l $opt_vardir) { # var is a symlink - if (-f $created_by_mem_file) + + if ( $opt_mem and readlink($opt_vardir) eq $opt_mem ) { # Remove the directory which the link points at + mtr_verbose("Removing " . readlink($opt_vardir)); rmtree(readlink($opt_vardir)); - # Remove the entire "var" dir - rmtree("$opt_vardir/"); + # Remove the "var" symlink + mtr_verbose("unlink($opt_vardir)"); + unlink($opt_vardir); + } + elsif ( $opt_mem ) + { + # Just remove the "var" symlink + mtr_report("WARNING: Removing '$opt_vardir' symlink it's wrong"); + + mtr_verbose("unlink($opt_vardir)"); unlink($opt_vardir); } else { # Some users creates a soft link in mysql-test/var to another area - # - allow it + # - allow it, but remove all files in it + mtr_report("WARNING: Using the 'mysql-test/var' symlink"); - rmtree("$opt_vardir/log"); - rmtree("$opt_vardir/ndbcluster-$opt_ndbcluster_port"); - rmtree("$opt_vardir/run"); - rmtree("$opt_vardir/tmp"); + + # Make sure the directory where it points exist + mtr_error("The destination for symlink $opt_vardir does not exist") + if ! -d readlink($opt_vardir); + + foreach my $bin ( glob("$opt_vardir/*") ) + { + mtr_verbose("Removing bin $bin"); + rmtree($bin); + } } } else { # Remove the entire "var" dir + mtr_verbose("Removing $opt_vardir/"); rmtree("$opt_vardir/"); } } @@ -2014,21 +2107,56 @@ sub cleanup_stale_files () { # Remove the var/ dir in mysql-test dir if any # this could be an old symlink that shouldn't be there + mtr_verbose("Removing $default_vardir"); rmtree($default_vardir); # Remove the "var" dir + mtr_verbose("Removing $opt_vardir/"); rmtree("$opt_vardir/"); } +} + +# +# Create var and the directories needed in var +# +sub setup_vardir() { + mtr_report("Creating Directories"); + + if ( $opt_vardir eq $default_vardir ) + { + # + # Running with "var" in mysql-test dir + # + if ( -l $opt_vardir ) + { + # it's a symlink + + # Make sure the directory where it points exist + mtr_error("The destination for symlink $opt_vardir does not exist") + if ! -d readlink($opt_vardir); + } + elsif ( $opt_mem ) + { + # Runinng with "var" as a link to some "memory" location, normally tmpfs + mtr_verbose("Creating $opt_mem"); + mkpath($opt_mem); + + mtr_report("Symlinking 'var' to '$opt_mem'"); + symlink($opt_mem, $opt_vardir); + } + } + + if ( ! -d $opt_vardir ) + { + mtr_verbose("Creating $opt_vardir"); + mkpath($opt_vardir); + } - if ( $opt_mem ) + # Ensure a proper error message if vardir couldn't be created + unless ( -d $opt_vardir and -w $opt_vardir ) { - # Runinng with var as a link to some "memory" location, normally tmpfs - rmtree($opt_mem); - mkpath($opt_mem); - mtr_report("Creating symlink from $opt_vardir to $opt_mem"); - symlink($opt_mem, $opt_vardir); - # Put a small file to recognize this dir was created by --mem - mtr_tofile($created_by_mem_file, $opt_mem); + mtr_error("Writable 'var' directory is needed, use the " . + "'--vardir=<path>' option"); } mkpath("$opt_vardir/log"); @@ -2036,10 +2164,9 @@ sub cleanup_stale_files () { mkpath("$opt_vardir/tmp"); mkpath($opt_tmpdir) if $opt_tmpdir ne "$opt_vardir/tmp"; - # Remove old and create new data dirs + # Create new data dirs foreach my $data_dir (@data_dir_lst) { - rmtree("$data_dir"); mkpath("$data_dir/mysql"); mkpath("$data_dir/test"); } @@ -2061,6 +2188,12 @@ sub cleanup_stale_files () { } closedir(DIR); } + + # Remove old log files + foreach my $name (glob("r/*.progress r/*.log r/*.warnings")) + { + unlink($name); + } } @@ -2441,8 +2574,8 @@ sub ndbcluster_start ($$) { sub rm_ndbcluster_tables ($) { my $dir= shift; - foreach my $bin ( glob("$dir/cluster/apply_status*"), - glob("$dir/cluster/schema*") ) + foreach my $bin ( glob("$dir/mysql/apply_status*"), + glob("$dir/mysql/schema*")) { unlink($bin); } @@ -2576,31 +2709,51 @@ sub run_suite () { sub initialize_servers () { - datadir_setup(); + datadir_list_setup(); - if ( ! $opt_extern ) + if ( $opt_extern ) + { + # Running against an already started server, if the specified + # vardir does not already exist it should be created + if ( ! -d $opt_vardir ) + { + mtr_report("Creating '$opt_vardir'"); + setup_vardir(); + } + else + { + mtr_report("No need to create '$opt_vardir' it already exists"); + } + } + else { kill_running_servers(); if ( ! $opt_start_dirty ) { - cleanup_stale_files(); + remove_stale_vardir(); + setup_vardir(); + mysql_install_db(); if ( $opt_force ) { + # Save a snapshot of the freshly installed db + # to make it possible to restore to a known point in time save_installed_db(); } } - check_running_as_root(); } + check_running_as_root(); } sub mysql_install_db () { install_db('master', $master->[0]->{'path_myddir'}); - # FIXME check if testcase really is using second master - copy_install_db('master', $master->[1]->{'path_myddir'}); + if ($max_master_num) + { + copy_install_db('master', $master->[1]->{'path_myddir'}); + } # Install the number of slave databses needed for (my $idx= 0; $idx < $max_slave_num; $idx++) @@ -2959,26 +3112,15 @@ sub do_before_run_mysqltest($) unlink("$result_dir/$tname.log"); unlink("$result_dir/$tname.warnings"); - mtr_tonewfile($path_current_test_log,"$tname\n"); # Always tell where we are - - # output current test to ndbcluster log file to enable diagnostics - mtr_tofile($path_ndb_testrun_log,"CURRENT TEST $tname\n"); - - mtr_tofile($master->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n"); - if ( $master->[1]->{'pid'} ) - { - mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n"); - } - if ( $mysql_version_id < 50000 ) { - # Set envirnoment variable NDB_STATUS_OK to 1 + # Set environment variable NDB_STATUS_OK to 1 # if script decided to run mysqltest cluster _is_ installed ok $ENV{'NDB_STATUS_OK'} = "1"; } elsif ( $mysql_version_id < 50100 ) { - # Set envirnoment variable NDB_STATUS_OK to YES + # Set environment variable NDB_STATUS_OK to YES # if script decided to run mysqltest cluster _is_ installed ok $ENV{'NDB_STATUS_OK'} = "YES"; } @@ -2989,9 +3131,9 @@ sub do_after_run_mysqltest($) my $tinfo= shift; my $tname= $tinfo->{'name'}; - mtr_tofile($path_mysqltest_log,"CURRENT TEST $tname\n"); - # Save info from this testcase run to mysqltest.log + mtr_appendfile_to_file($path_current_test_log, $path_mysqltest_log) + if -f $path_current_test_log; mtr_appendfile_to_file($path_timefile, $path_mysqltest_log) if -f $path_timefile; @@ -3001,18 +3143,38 @@ sub do_after_run_mysqltest($) } +sub run_testcase_mark_logs($) +{ + my ($log_msg)= @_; + + # Write a marker to all log files + + # The file indicating current test name + mtr_tonewfile($path_current_test_log, $log_msg); + + # each mysqld's .err file + foreach my $mysqld (@{$master}, @{$slave}) + { + mtr_tofile($mysqld->{path_myerr}, $log_msg); + } + + # ndbcluster log file + mtr_tofile($path_ndb_testrun_log, $log_msg); + +} + sub find_testcase_skipped_reason($) { my ($tinfo)= @_; - # Open mysqltest.log + # Open mysqltest-time my $F= IO::File->new($path_timefile) or mtr_error("can't open file \"$path_timefile\": $!"); my $reason; while ( my $line= <$F> ) { - # Look for "reason: <reason fo skiping test>" + # Look for "reason: <reason for skipping test>" if ( $line =~ /reason: (.*)/ ) { $reason= $1; @@ -3120,6 +3282,10 @@ sub run_testcase ($) { run_testcase_stop_servers($tinfo, $master_restart, $slave_restart); } + + # Write to all log files to indicate start of testcase + run_testcase_mark_logs("CURRENT_TEST: $tinfo->{name}\n"); + my $died= mtr_record_dead_children(); if ($died or $master_restart or $slave_restart) { @@ -3389,11 +3555,10 @@ sub mysqld_arguments ($$$$$) { if ( $glob_use_embedded_server ) { $prefix= "--server-arg="; - } else { - # We can't pass embedded server --no-defaults - mtr_add_arg($args, "--no-defaults"); } + mtr_add_arg($args, "%s--no-defaults", $prefix); + mtr_add_arg($args, "%s--console", $prefix); mtr_add_arg($args, "%s--basedir=%s", $prefix, $path_my_basedir); mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir); @@ -3461,6 +3626,17 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--ndb-extra-logging", $prefix); } } + + if ( $mysql_version_id <= 50106 ) + { + # Force mysqld to use log files up until 5.1.6 + mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'}); + } + else + { + # Turn on logging, will be sent to tables + mtr_add_arg($args, "%s--log=", $prefix); + } } if ( $type eq 'slave' ) @@ -3478,8 +3654,6 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--log-slave-updates", $prefix); } - mtr_add_arg($args, "%s--log=%s", $prefix, - $slave->[$idx]->{'path_mylog'}); mtr_add_arg($args, "%s--master-retry-count=10", $prefix); mtr_add_arg($args, "%s--pid-file=%s", $prefix, $slave->[$idx]->{'path_pid'}); @@ -3540,6 +3714,18 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--ndb-extra-logging", $prefix); } } + + if ( $mysql_version_id <= 50106 ) + { + # Force mysqld to use log files up until 5.1.6 + mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'}); + } + else + { + # Turn on logging, will be sent to tables + mtr_add_arg($args, "%s--log=", $prefix); + } + } # end slave if ( $opt_debug ) @@ -3616,7 +3802,6 @@ sub mysqld_arguments ($$$$$) { elsif ( $type eq 'master' ) { mtr_add_arg($args, "%s--open-files-limit=1024", $prefix); - mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'}); } return $args; @@ -4102,7 +4287,8 @@ sub run_testcase_start_servers($) { } - if ( $clusters->[0]->{'pid'} and ! $master->[1]->{'pid'} ) + if ( $clusters->[0]->{'pid'} and ! $master->[1]->{'pid'} and + $tinfo->{'master_num'} > 1 ) { # Test needs cluster, start an extra mysqld connected to cluster @@ -4112,17 +4298,15 @@ sub run_testcase_start_servers($) { # tables ok FIXME This is a workaround so that only one mysqld # create the tables if ( ! sleep_until_file_created( - "$master->[0]->{'path_myddir'}/cluster/apply_status.ndb", + "$master->[0]->{'path_myddir'}/mysql/apply_status.ndb", $master->[0]->{'start_timeout'}, $master->[0]->{'pid'})) { - $tinfo->{'comment'}= "Failed to create 'cluster/apply_status' table"; + $tinfo->{'comment'}= "Failed to create 'mysql/apply_status' table"; return 1; } } - mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n"); - mysqld_start($master->[1],$tinfo->{'master_opt'},[]); } @@ -4150,8 +4334,6 @@ sub run_testcase_start_servers($) { # ---------------------------------------------------------------------- if ( $tinfo->{'slave_num'} ) { - mtr_tofile($slave->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n"); - restore_slave_databases($tinfo->{'slave_num'}); do_before_start_slave($tinfo); @@ -4317,6 +4499,10 @@ sub run_mysqltest ($) { mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir); + # Log line number and time for each line in .test file + mtr_add_arg($args, "--mark-progress") + if $opt_mark_progress; + if ($tinfo->{'component_id'} eq 'im') { mtr_add_arg($args, "--socket=%s", $instance_manager->{'path_sock'}); @@ -4765,11 +4951,14 @@ Options that specify ports slave_port=PORT Specify the port number used by the first slave ndbcluster-port=PORT Specify the port number used by cluster ndbcluster-port-slave=PORT Specify the port number used by slave cluster + mtr-build-thread=# Specify unique collection of ports. Can also be set by + setting the environment variable MTR_BUILD_THREAD. Options for test case authoring record TESTNAME (Re)genereate the result file for TESTNAME check-testcases Check testcases for sideeffects + mark-progress Log line number and elapsed time to <testname>.progress Options that pass on options @@ -4777,7 +4966,7 @@ Options that pass on options Options to run test on running server - extern Use running server for tests FIXME DANGEROUS + extern Use running server for tests ndb-connectstring=STR Use running cluster, and connect using STR ndb-connectstring-slave=STR Use running slave cluster, and connect using STR user=USER User for connection to extern server diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index ba8c11efbe1..d376b277c8a 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -541,6 +541,127 @@ create table t1 ( a timestamp ); alter table t1 add unique ( a(1) ); ERROR HY000: Incorrect sub part key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique sub keys drop table t1; +drop table if exists t1; +create table t1 (a int, key(a)); +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 a 1 a A NULL NULL NULL YES BTREE +"this used not to disable the index" +alter table t1 modify a int, disable keys; +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 a 1 a A NULL NULL NULL YES BTREE disabled +alter table t1 enable keys; +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 a 1 a A NULL NULL NULL YES BTREE +alter table t1 modify a bigint, disable keys; +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 a 1 a A NULL NULL NULL YES BTREE disabled +alter table t1 enable keys; +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 a 1 a A NULL NULL NULL YES BTREE +alter table t1 add b char(10), disable keys; +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 a 1 a A NULL NULL NULL YES BTREE disabled +alter table t1 add c decimal(10,2), enable keys; +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 a 1 a A NULL NULL NULL YES BTREE +"this however did" +alter table t1 disable keys; +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 a 1 a A NULL NULL NULL YES BTREE disabled +desc t1; +Field Type Null Key Default Extra +a bigint(20) YES MUL NULL +b char(10) YES NULL +c decimal(10,2) YES NULL +alter table t1 add d decimal(15,5); +"The key should still be disabled" +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 a 1 a A NULL NULL NULL YES BTREE disabled +drop table t1; +"Now will test with one unique index" +create table t1(a int, b char(10), unique(a)); +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +alter table t1 disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +alter table t1 enable keys; +"If no copy on noop change, this won't touch the data file" +"Unique index, no change" +alter table t1 modify a int, disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +"Change the type implying data copy" +"Unique index, no change" +alter table t1 modify a bigint, disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +alter table t1 modify a bigint; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +alter table t1 modify a int; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +drop table t1; +"Now will test with one unique and one non-unique index" +create table t1(a int, b char(10), unique(a), key(b)); +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE +alter table t1 disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE disabled +alter table t1 enable keys; +"If no copy on noop change, this won't touch the data file" +"The non-unique index will be disabled" +alter table t1 modify a int, disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE disabled +alter table t1 enable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE +"Change the type implying data copy" +"The non-unique index will be disabled" +alter table t1 modify a bigint, disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE disabled +"Change again the type, but leave the indexes as_is" +alter table t1 modify a int; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE disabled +"Try the same. When data is no copied on similar tables, this is noop" +alter table t1 modify a int; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE disabled +drop table t1; create database mysqltest; create table t1 (c1 int); alter table t1 rename mysqltest.t1; diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index 3be1cdcf15a..f73a80dde65 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -11120,7 +11120,13 @@ auto fld1 companynr fld3 fld4 fld5 fld6 2 011401 37 breaking dreaded Steinberg W 3 011402 37 Romans scholastics jarring 4 011403 37 intercepted audiology tinily +SELECT COUNT(auto) FROM t2; +COUNT(auto) +1213 INSERT DELAYED INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily',''); +SELECT COUNT(auto) FROM t2; +COUNT(auto) +1214 ALTER TABLE t2 DROP COLUMN fld6; SHOW CREATE TABLE t2; Table Create Table diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result index da0ca8ddba1..c141b255716 100644 --- a/mysql-test/r/compare.result +++ b/mysql-test/r/compare.result @@ -46,6 +46,10 @@ create table t1 (a tinyint(1),b binary(1)); insert into t1 values (0x01,0x01); select * from t1 where a=b; a b +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '' select * from t1 where a=b and b=0x01; a b +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '' drop table if exists t1; diff --git a/mysql-test/r/ctype_cp1250_ch.result b/mysql-test/r/ctype_cp1250_ch.result index b55849e4e12..73f415732cd 100644 --- a/mysql-test/r/ctype_cp1250_ch.result +++ b/mysql-test/r/ctype_cp1250_ch.result @@ -1,3 +1,4 @@ +DROP TABLE IF EXISTS t1; SHOW COLLATION LIKE 'cp1250_czech_cs'; Collation Charset Id Default Compiled Sortlen cp1250_czech_cs cp1250 34 Yes 2 diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index 4e145346081..125e0edd1f9 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -171,8 +171,8 @@ create table t1 (a char(10) character set koi8r, b text character set koi8r); insert into t1 values ('test','test'); insert into t1 values ('ÊÃÕË','ÊÃÕË'); Warnings: -Warning 1265 Data truncated for column 'a' at row 1 -Warning 1265 Data truncated for column 'b' at row 1 +Warning 1366 Incorrect string value: '\xCA\xC3\xD5\xCB' for column 'a' at row 1 +Warning 1366 Incorrect string value: '\xCA\xC3\xD5\xCB' for column 'b' at row 1 drop table t1; set names koi8r; create table t1 (a char(10) character set cp1251); diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 76fcbbeb9f8..e32c1e8aae0 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -723,6 +723,28 @@ lily river drop table t1; deallocate prepare stmt; +create table t1 ( +a char(10) unicode not null, +index a (a) +) engine=myisam; +insert into t1 values (repeat(0x201f, 10)); +insert into t1 values (repeat(0x2020, 10)); +insert into t1 values (repeat(0x2021, 10)); +explain select hex(a) from t1 order by a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL a 20 NULL 3 Using index +select hex(a) from t1 order by a; +hex(a) +201F201F201F201F201F201F201F201F201F201F +2020202020202020202020202020202020202020 +2021202120212021202120212021202120212021 +alter table t1 drop index a; +select hex(a) from t1 order by a; +hex(a) +201F201F201F201F201F201F201F201F201F201F +2020202020202020202020202020202020202020 +2021202120212021202120212021202120212021 +drop table t1; CREATE TABLE t1 (id int, s char(5) CHARACTER SET ucs2 COLLATE ucs2_unicode_ci); INSERT INTO t1 VALUES (1, 'ZZZZZ'), (1, 'ZZZ'), (2, 'ZZZ'), (2, 'ZZZZZ'); SELECT id, MIN(s) FROM t1 GROUP BY id; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 00fd5a0c9aa..4eb74510c93 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -197,7 +197,7 @@ drop table t1; create table t1 (s1 char(10) character set utf8); insert into t1 values (0x41FF); Warnings: -Warning 1265 Data truncated for column 's1' at row 1 +Warning 1366 Incorrect string value: '\xFF' for column 's1' at row 1 select hex(s1) from t1; hex(s1) 41 @@ -205,7 +205,7 @@ drop table t1; create table t1 (s1 varchar(10) character set utf8); insert into t1 values (0x41FF); Warnings: -Warning 1265 Data truncated for column 's1' at row 1 +Warning 1366 Incorrect string value: '\xFF' for column 's1' at row 1 select hex(s1) from t1; hex(s1) 41 @@ -213,7 +213,7 @@ drop table t1; create table t1 (s1 text character set utf8); insert into t1 values (0x41FF); Warnings: -Warning 1265 Data truncated for column 's1' at row 1 +Warning 1366 Incorrect string value: '\xFF' for column 's1' at row 1 select hex(s1) from t1; hex(s1) 41 @@ -1536,6 +1536,32 @@ set @a:=null; execute my_stmt using @a; a b drop table if exists t1; +drop table if exists t1; +drop view if exists v1, v2; +set names utf8; +create table t1(col1 varchar(12) character set utf8 collate utf8_unicode_ci); +insert into t1 values('t1_val'); +create view v1 as select 'v1_val' as col1; +select coercibility(col1), collation(col1) from v1; +coercibility(col1) collation(col1) +4 utf8_general_ci +create view v2 as select col1 from v1 union select col1 from t1; +select coercibility(col1), collation(col1)from v2; +coercibility(col1) collation(col1) +2 utf8_unicode_ci +2 utf8_unicode_ci +drop view v1, v2; +create view v1 as select 'v1_val' collate utf8_swedish_ci as col1; +select coercibility(col1), collation(col1) from v1; +coercibility(col1) collation(col1) +0 utf8_swedish_ci +create view v2 as select col1 from v1 union select col1 from t1; +select coercibility(col1), collation(col1) from v2; +coercibility(col1) collation(col1) +0 utf8_swedish_ci +0 utf8_swedish_ci +drop view v1, v2; +drop table t1; CREATE TABLE t1 ( colA int(11) NOT NULL, colB varchar(255) character set utf8 NOT NULL, diff --git a/mysql-test/r/fix_priv_tables.result b/mysql-test/r/fix_priv_tables.result new file mode 100644 index 00000000000..e54330a5520 --- /dev/null +++ b/mysql-test/r/fix_priv_tables.result @@ -0,0 +1,36 @@ +drop table if exists t1,t1aa,t2aa; +DROP DATABASE IF EXISTS testdb; +CREATE DATABASE testdb; +CREATE TABLE testdb.t1 ( +c1 INT, +c3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +CREATE VIEW testdb.v1 AS +SELECT * FROM testdb.t1; +GRANT CREATE VIEW, SHOW VIEW ON testdb.v1 TO 'show_view_tbl'@'localhost'; +SHOW GRANTS FOR 'show_view_tbl'@'localhost'; +Grants for show_view_tbl@localhost +GRANT USAGE ON *.* TO 'show_view_tbl'@'localhost' +GRANT CREATE VIEW, SHOW VIEW ON `testdb`.`v1` TO 'show_view_tbl'@'localhost' + +GRANT SELECT(c1) on testdb.v1 to 'select_only_c1'@localhost; +SHOW GRANTS FOR 'select_only_c1'@'localhost'; +Grants for select_only_c1@localhost +GRANT USAGE ON *.* TO 'select_only_c1'@'localhost' +GRANT SELECT (c1) ON `testdb`.`v1` TO 'select_only_c1'@'localhost' + +"after fix privs" +SHOW GRANTS FOR 'show_view_tbl'@'localhost'; +Grants for show_view_tbl@localhost +GRANT USAGE ON *.* TO 'show_view_tbl'@'localhost' +GRANT CREATE VIEW, SHOW VIEW ON `testdb`.`v1` TO 'show_view_tbl'@'localhost' + +SHOW GRANTS FOR 'select_only_c1'@'localhost'; +Grants for select_only_c1@localhost +GRANT USAGE ON *.* TO 'select_only_c1'@'localhost' +GRANT SELECT (c1) ON `testdb`.`v1` TO 'select_only_c1'@'localhost' + +DROP USER 'show_view_tbl'@'localhost'; +DROP USER 'select_only_c1'@'localhost'; +DROP VIEW testdb.v1; +DROP TABLE testdb.t1; +DROP DATABASE testdb; diff --git a/mysql-test/r/fix_priv_tabs.result b/mysql-test/r/fix_priv_tabs.result new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/mysql-test/r/fix_priv_tabs.result diff --git a/mysql-test/r/flush2.result b/mysql-test/r/flush2.result new file mode 100644 index 00000000000..7c94219fd71 --- /dev/null +++ b/mysql-test/r/flush2.result @@ -0,0 +1,24 @@ +flush logs; +set global expire_logs_days = 3; +show variables like 'log%'; +Variable_name Value +log ON +log_bin OFF +log_bin_trust_function_creators ON +log_error +log_queries_not_using_indexes OFF +log_slave_updates OFF +log_slow_queries OFF +log_warnings 1 +flush logs; +show variables like 'log%'; +Variable_name Value +log ON +log_bin OFF +log_bin_trust_function_creators ON +log_error +log_queries_not_using_indexes OFF +log_slave_updates OFF +log_slow_queries OFF +log_warnings 1 +set global expire_logs_days = 0; diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 85894d5cb0e..7c9069791fa 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -372,10 +372,10 @@ t collation(t) FORMAT(MATCH t AGAINST ('Osnabruck'),6) aus Osnabrück utf8_general_ci 1.591140 alter table t1 modify t varchar(200) collate latin1_german2_ci not null; Warnings: -Warning 1265 Data truncated for column 't' at row 3 -Warning 1265 Data truncated for column 't' at row 4 -Warning 1265 Data truncated for column 't' at row 5 -Warning 1265 Data truncated for column 't' at row 6 +Warning 1366 Incorrect string value: '\xD0\xAD\xD1\x82\xD0\xBE...' for column 't' at row 3 +Warning 1366 Incorrect string value: '\xD0\x9E\xD1\x82\xD0\xBB...' for column 't' at row 4 +Warning 1366 Incorrect string value: '\xD0\x9D\xD0\xB5 \xD0...' for column 't' at row 5 +Warning 1366 Incorrect string value: '\xD0\xB8 \xD0\xB1\xD1...' for column 't' at row 6 SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück'); t collation(t) aus Osnabrück latin1_german2_ci diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 5dbbd891427..6989b89833b 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -658,3 +658,73 @@ GROUP_CONCAT(a) x 2 1,2 1 2,3 DROP TABLE t1; +set names utf8; +create table t1 +( +x text character set utf8 not null, +y integer not null +); +insert into t1 values (repeat('a', 1022), 0), (repeat(_utf8 0xc3b7, 4), 0); +set group_concat_max_len= 1022 + 10; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1032 1031 1027 aaaaaaa,÷÷÷÷ C3B7C3B7C3B7 +set group_concat_max_len= 1022 + 9; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1031 1031 1027 aaaaaaa,÷÷÷÷ C3B7C3B7C3B7 +set group_concat_max_len= 1022 + 8; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1030 1029 1026 aaaaaaaa,÷÷÷ C3B7C3B7C3B7 +set group_concat_max_len= 1022 + 7; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1029 1029 1026 aaaaaaaa,÷÷÷ C3B7C3B7C3B7 +set group_concat_max_len= 1022 + 6; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1028 1027 1025 aaaaaaaaa,÷÷ 612CC3B7C3B7 +set group_concat_max_len= 1022 + 5; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1027 1027 1025 aaaaaaaaa,÷÷ 612CC3B7C3B7 +set group_concat_max_len= 1022 + 4; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1026 1025 1024 aaaaaaaaaa,÷ 6161612CC3B7 +set group_concat_max_len= 1022 + 3; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1025 1025 1024 aaaaaaaaaa,÷ 6161612CC3B7 +set group_concat_max_len= 1022 + 2; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1024 1023 1023 aaaaaaaaaaa, 61616161612C +set group_concat_max_len= 1022 + 1; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1023 1023 1023 aaaaaaaaaaa, 61616161612C +drop table t1; +set group_concat_max_len=1024; +set names latin1; +create table t1 (f1 int unsigned, f2 varchar(255)); +insert into t1 values (1,repeat('a',255)),(2,repeat('b',255)); +select f2,group_concat(f1) from t1 group by f2; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 t1 f2 f2 253 255 255 Y 0 0 8 +def group_concat(f1) 252 1024 1 Y 128 0 63 +f2 group_concat(f1) +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1 +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 2 +drop table t1; diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index c6117053a60..23517f7b603 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -1029,3 +1029,29 @@ t1 CREATE TABLE `t1` ( `stddev(0)` double(8,4) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8); +INSERT INTO t1 SELECT a, b+8 FROM t1; +INSERT INTO t1 SELECT a, b+16 FROM t1; +INSERT INTO t1 SELECT a, b+32 FROM t1; +INSERT INTO t1 SELECT a, b+64 FROM t1; +INSERT INTO t1 SELECT a, b+128 FROM t1; +INSERT INTO t1 SELECT a, b+256 FROM t1; +INSERT INTO t1 SELECT a, b+512 FROM t1; +INSERT INTO t1 SELECT a, b+1024 FROM t1; +INSERT INTO t1 SELECT a, b+2048 FROM t1; +INSERT INTO t1 SELECT a, b+4096 FROM t1; +INSERT INTO t1 SELECT a, b+8192 FROM t1; +INSERT INTO t1 SELECT a, b+16384 FROM t1; +INSERT INTO t1 SELECT a, b+32768 FROM t1; +SELECT a,COUNT(DISTINCT b) AS cnt FROM t1 GROUP BY a HAVING cnt > 50; +a cnt +1 65536 +SELECT a,SUM(DISTINCT b) AS sumation FROM t1 GROUP BY a HAVING sumation > 50; +a sumation +1 2147516416 +SELECT a,AVG(DISTINCT b) AS average FROM t1 GROUP BY a HAVING average > 50; +a average +1 32768.5000 +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index e38e2624e19..38250173dd1 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -202,6 +202,14 @@ select count(*) from t1 where id not in (1,2); count(*) 1 drop table t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 SELECT 1 IN (2, NULL); +SELECT should return NULL. +SELECT * FROM t1; +1 IN (2, NULL) +NULL +DROP TABLE t1; +End of 4.1 tests CREATE TABLE t1 (a int PRIMARY KEY); INSERT INTO t1 VALUES (44), (45), (46); SELECT * FROM t1 WHERE a IN (45); @@ -342,4 +350,9 @@ select some_id from t1 where some_id not in(-4,-1,3423534,2342342); some_id 1 2 +select some_id from t1 where some_id not in('-1', '0'); +some_id +1 +2 drop table t1; +End of 5.0 tests diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index c1ac3e191d3..5c6162b7c28 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -134,4 +134,11 @@ timediff(b, a) >= '00:00:03' drop table t2; drop table t1; set global query_cache_size=default; +create table t1 select INET_ATON('255.255.0.1') as `a`; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(21) unsigned default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index e5342eec54f..14c61a2dd93 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1903,4 +1903,17 @@ Warnings: Error 1292 Truncated incorrect DECIMAL value: '' Error 1292 Truncated incorrect DECIMAL value: '' Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated +SET @orig_sql_mode = @@SQL_MODE; +SET SQL_MODE=traditional; +SELECT CHAR(0xff,0x8f USING utf8); +CHAR(0xff,0x8f USING utf8) +NULL +Warnings: +Error 1300 Invalid utf8 character string: 'FF8F' +SELECT CHAR(0xff,0x8f USING utf8) IS NULL; +CHAR(0xff,0x8f USING utf8) IS NULL +1 +Warnings: +Error 1300 Invalid utf8 character string: 'FF8F' +SET SQL_MODE=@orig_sql_mode; End of 5.0 tests diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 1e5c01be288..45c05f0b5b5 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -1204,3 +1204,6 @@ fmtddate field2 Sep-4 12:00AM abcd DROP TABLE testBug8868; SET NAMES DEFAULT; +select str_to_date('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE; +str_to_date('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE +NULL diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result index e017a31f24b..e8134a50496 100644 --- a/mysql-test/r/gis-rtree.result +++ b/mysql-test/r/gis-rtree.result @@ -873,3 +873,11 @@ SELECT 1 FROM t1 WHERE foo != PointFromWKB(POINT(0,0)); 1 1 DROP TABLE t1; +CREATE TABLE t1(foo GEOMETRY NOT NULL, SPATIAL INDEX(foo) ); +INSERT INTO t1(foo) VALUES (NULL); +ERROR 23000: Column 'foo' cannot be null +INSERT INTO t1() VALUES (); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +INSERT INTO t1(foo) VALUES (''); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +DROP TABLE t1; diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 0304919baf6..7583aa14db8 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2162,3 +2162,127 @@ SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a; MIN(c) 2 DROP TABLE t1,t2; +CREATE TABLE t1 (a INT, b INT, INDEX (a,b)); +INSERT INTO t1 (a, b) VALUES (1,1), (1,2), (1,3), (1,4), (1,5), +(2,2), (2,3), (2,1), (3,1), (4,1), (4,2), (4,3), (4,4), (4,5), (4,6); +EXPLAIN SELECT max(b), a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL a 5 NULL 8 Using index for group-by +FLUSH STATUS; +SELECT max(b), a FROM t1 GROUP BY a; +max(b) a +5 1 +3 2 +1 3 +6 4 +SHOW STATUS LIKE 'handler_read__e%'; +Variable_name Value +Handler_read_key 8 +Handler_read_next 0 +EXPLAIN SELECT max(b), a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL a 5 NULL 8 Using index for group-by +FLUSH STATUS; +CREATE TABLE t2 SELECT max(b), a FROM t1 GROUP BY a; +SHOW STATUS LIKE 'handler_read__e%'; +Variable_name Value +Handler_read_key 8 +Handler_read_next 0 +FLUSH STATUS; +SELECT * FROM (SELECT max(b), a FROM t1 GROUP BY a) b; +max(b) a +5 1 +3 2 +1 3 +6 4 +SHOW STATUS LIKE 'handler_read__e%'; +Variable_name Value +Handler_read_key 8 +Handler_read_next 0 +FLUSH STATUS; +(SELECT max(b), a FROM t1 GROUP BY a) UNION +(SELECT max(b), a FROM t1 GROUP BY a); +max(b) a +5 1 +3 2 +1 3 +6 4 +SHOW STATUS LIKE 'handler_read__e%'; +Variable_name Value +Handler_read_key 16 +Handler_read_next 0 +EXPLAIN (SELECT max(b), a FROM t1 GROUP BY a) UNION +(SELECT max(b), a FROM t1 GROUP BY a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range NULL a 5 NULL 8 Using index for group-by +2 UNION t1 range NULL a 5 NULL 8 Using index for group-by +NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL +EXPLAIN SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x +FROM t1 AS t1_outer; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index +2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by +EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE EXISTS +(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index +2 SUBQUERY t1 index NULL a 10 NULL 8 Using index +EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE +(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by +EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE +a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1_outer index NULL a 10 NULL 15 Using where; Using index +2 DEPENDENT SUBQUERY t1 index NULL a 10 NULL 8 Using index +EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING +a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1_outer range NULL a 5 NULL 8 Using index for group-by +2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by +EXPLAIN SELECT 1 FROM t1 AS t1_outer1 JOIN t1 AS t1_outer2 +ON t1_outer1.a = (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) +AND t1_outer1.b = t1_outer2.b; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1_outer1 ref a a 5 const 1 Using where; Using index +1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using where; Using index +2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by +EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x +FROM t1 AS t1_outer) x2 FROM t1 AS t1_outer2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using index +2 SUBQUERY t1_outer index NULL a 10 NULL 15 Using index +3 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by +CREATE TABLE t3 LIKE t1; +FLUSH STATUS; +INSERT INTO t3 SELECT a,MAX(b) FROM t1 GROUP BY a; +SHOW STATUS LIKE 'handler_read__e%'; +Variable_name Value +Handler_read_key 8 +Handler_read_next 0 +DELETE FROM t3; +FLUSH STATUS; +INSERT INTO t3 SELECT 1, (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) +FROM t1 LIMIT 1; +SHOW STATUS LIKE 'handler_read__e%'; +Variable_name Value +Handler_read_key 8 +Handler_read_next 0 +FLUSH STATUS; +DELETE FROM t3 WHERE (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) > 10000; +SHOW STATUS LIKE 'handler_read__e%'; +Variable_name Value +Handler_read_key 8 +Handler_read_next 0 +FLUSH STATUS; +DELETE FROM t3 WHERE (SELECT (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) x +FROM t1) > 10000; +Warnings: +Error 1242 Subquery returns more than 1 row +SHOW STATUS LIKE 'handler_read__e%'; +Variable_name Value +Handler_read_key 8 +Handler_read_next 1 +DROP TABLE t1,t2,t3; diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result index b842a5f3bf9..d80a34f8427 100644 --- a/mysql-test/r/im_daemon_life_cycle.result +++ b/mysql-test/r/im_daemon_life_cycle.result @@ -6,7 +6,7 @@ instance_name status mysqld1 online mysqld2 offline Killing the process... -Sleeping... +Waiting... Success: the process was restarted. Success: server is ready to accept connection on socket. @@ -16,7 +16,7 @@ Success: server is ready to accept connection on socket. START INSTANCE mysqld2; Success: the process has been started. Killing the process... -Sleeping... +Waiting... Success: the process was restarted. Success: server is ready to accept connection on socket. SHOW INSTANCE STATUS mysqld1; diff --git a/mysql-test/r/im_life_cycle.result b/mysql-test/r/im_life_cycle.result index 69f6bb5a490..a9ad85d5947 100644 --- a/mysql-test/r/im_life_cycle.result +++ b/mysql-test/r/im_life_cycle.result @@ -39,7 +39,7 @@ ERROR HY000: Bad instance name. Check that the instance with such a name exists -- 1.1.6. -------------------------------------------------------------------- Killing the process... -Sleeping... +Waiting... Success: the process was restarted. SHOW INSTANCES; instance_name status @@ -52,7 +52,7 @@ mysqld2 offline START INSTANCE mysqld2; Success: the process has been started. Killing the process... -Sleeping... +Waiting... Success: the process was killed. -------------------------------------------------------------------- diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 3fffce73aa9..21d7bfb1b21 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1027,7 +1027,7 @@ CREATE PROCEDURE p1 () BEGIN SELECT 'foo' FROM DUAL; END | -ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' +ERROR 42000: Unknown database 'information_schema' select ROUTINE_NAME from routines; ROUTINE_NAME grant all on information_schema.* to 'user1'@'localhost'; @@ -1254,3 +1254,18 @@ COLUMN_NAME MD5(COLUMN_DEFAULT) LENGTH(COLUMN_DEFAULT) COLUMN_DEFAULT=get_value( fld1 7cf7a6782be951a1f2464a350da926a5 65532 1 DROP TABLE bug23037; DROP FUNCTION get_value; +create view v1 as +select table_schema as object_schema, +table_name as object_name, +table_type as object_type +from information_schema.tables +order by object_schema; +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found +2 DERIVED tables ALL NULL NULL NULL NULL 2 Using filesort +explain select * from (select table_name from information_schema.tables) as a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found +2 DERIVED tables ALL NULL NULL NULL NULL 2 +drop view v1; diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result index 7705961d08d..6df3cf61ddb 100644 --- a/mysql-test/r/lowercase_table.result +++ b/mysql-test/r/lowercase_table.result @@ -84,3 +84,27 @@ create table t2 like T1; drop table t1, t2; show tables; Tables_in_test +set names utf8; +drop table if exists Ä°,Ä°Ä°; +create table Ä° (s1 int); +show create table Ä°; +Table Create Table +Ä° CREATE TABLE `i` ( + `s1` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +show tables; +Tables_in_test +i +drop table Ä°; +create table Ä°Ä° (s1 int); +show create table Ä°Ä°; +Table Create Table +Ä°Ä° CREATE TABLE `ii` ( + `s1` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +show tables; +Tables_in_test +ii +drop table Ä°Ä°; +set names latin1; +End of 5.0 tests diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result index 50b0b6ae294..34e961395c4 100644 --- a/mysql-test/r/metadata.result +++ b/mysql-test/r/metadata.result @@ -96,3 +96,37 @@ i 2 affected rows: 1 affected rows: 0 +create table t1 (id int(10)); +insert into t1 values (1); +CREATE VIEW v1 AS select t1.id as id from t1; +CREATE VIEW v2 AS select t1.id as renamed from t1; +CREATE VIEW v3 AS select t1.id + 12 as renamed from t1; +select * from v1 group by id limit 1; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 v1 id id 3 10 1 Y 32768 0 63 +id +1 +select * from v1 group by id limit 0; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 v1 id id 3 10 0 Y 32768 0 63 +id +select * from v1 where id=1000 group by id; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 v1 id id 3 10 0 Y 32768 0 63 +id +select * from v1 where id=1 group by id; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 v1 id id 3 10 1 Y 32768 0 63 +id +1 +select * from v2 where renamed=1 group by renamed; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 v2 id renamed 3 10 1 Y 32768 0 63 +renamed +1 +select * from v3 where renamed=1 group by renamed; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def v3 renamed 8 12 0 Y 32896 0 63 +renamed +drop table t1; +drop view v1,v2,v3; diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 2ea317754ec..3ed2d10c9c9 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -922,6 +922,7 @@ SET @@myisam_repair_threads=1; SHOW VARIABLES LIKE 'myisam_repair%'; Variable_name Value myisam_repair_threads 1 +End of 4.1 tests set storage_engine=MyISAM; drop table if exists t1,t2,t3; --- Testing varchar --- @@ -1608,16 +1609,4 @@ create table t3 (c1 int) engine=myisam pack_keys=default; create table t4 (c1 int) engine=myisam pack_keys=2; 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 '2' at line 1 drop table t1, t2, t3; -show create table t1; -show create table t1; -create table t1 (a int) engine=myisam select 42 a; -select * from t1; -a -9 -select * from t1; -a -99 -select * from t1; -a -42 -drop table t1; +End of 5.0 tests diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index 7fd55351880..3bba1944c52 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -180,4 +180,8 @@ Too long dbname ERROR 1049 (42000) at line 1: Unknown database 'test_really_long_dbnamexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' Too long hostname ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'cyrils_superlonghostnameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' (errno) +1 +1 +ERROR at line 1: DELIMITER cannot contain a backslash character +ERROR at line 1: DELIMITER cannot contain a backslash character End of 5.0 tests diff --git a/mysql-test/r/mysqladmin.result b/mysql-test/r/mysqladmin.result new file mode 100644 index 00000000000..57927f8aa67 --- /dev/null +++ b/mysql-test/r/mysqladmin.result @@ -0,0 +1,4 @@ +mysqld is alive +mysqladmin: unknown variable 'database=db1' +Warning: mysqladmin: unknown variable 'loose-database=db2' +mysqld is alive diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 1cfc482416e..12a35fcf48b 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -512,6 +512,12 @@ mysqltest: At line 1: End of line junk detected: "write_file filename "; mysqltest: At line 1: Missing required argument 'filename' to command 'file_exists' mysqltest: At line 1: Missing required argument 'from_file' to command 'copy_file' mysqltest: At line 1: Missing required argument 'to_file' to command 'copy_file' +mysqltest: At line 1: Missing required argument 'mode' to command 'chmod' +mysqltest: At line 1: You must write a 4 digit octal number for mode +mysqltest: At line 1: You must write a 4 digit octal number for mode +mysqltest: At line 1: Missing required argument 'file' to command 'chmod' +mysqltest: At line 1: You must write a 4 digit octal number for mode +mysqltest: At line 1: You must write a 4 digit octal number for mode hello hello hello diff --git a/mysql-test/r/ndb_index_unique.result b/mysql-test/r/ndb_index_unique.result index ce4759ad553..12ffc8437db 100644 --- a/mysql-test/r/ndb_index_unique.result +++ b/mysql-test/r/ndb_index_unique.result @@ -140,7 +140,40 @@ b int unsigned not null, c int unsigned, UNIQUE USING HASH (b, c) ) engine=ndbcluster; -ERROR 42000: Column 'c' is used with UNIQUE or INDEX but is not defined as NOT NULL +Warnings: +Warning 1121 Ndb does not support unique index on NULL valued attributes, index access with NULL value will become full table scan +insert t2 values(1,1,NULL),(2,2,2),(3,3,NULL),(4,4,4),(5,5,NULL),(6,6,6),(7,7,NULL),(8,3,NULL),(9,3,NULL); +select * from t2 where c IS NULL order by a; +a b c +1 1 NULL +3 3 NULL +5 5 NULL +7 7 NULL +8 3 NULL +9 3 NULL +select * from t2 where b = 3 AND c IS NULL order by a; +a b c +3 3 NULL +8 3 NULL +9 3 NULL +select * from t2 where (b = 3 OR b = 5) AND c IS NULL order by a; +a b c +3 3 NULL +5 5 NULL +8 3 NULL +9 3 NULL +set @old_ecpd = @@session.engine_condition_pushdown; +set engine_condition_pushdown = true; +explain select * from t2 where (b = 3 OR b = 5) AND c IS NULL AND a < 9 order by a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range PRIMARY,b PRIMARY 4 NULL 1 Using where with pushed condition +select * from t2 where (b = 3 OR b = 5) AND c IS NULL AND a < 9 order by a; +a b c +3 3 NULL +5 5 NULL +8 3 NULL +set engine_condition_pushdown = @old_ecpd; +drop table t2; CREATE TABLE t3 ( a int unsigned NOT NULL, b int unsigned not null, diff --git a/mysql-test/r/ndb_update.result b/mysql-test/r/ndb_update.result index 164d1bd700c..d75f82172ae 100644 --- a/mysql-test/r/ndb_update.result +++ b/mysql-test/r/ndb_update.result @@ -17,8 +17,17 @@ pk1 b c 0 0 0 2 2 2 4 1 1 +UPDATE t1 set pk1 = 4 where pk1 = 2; +ERROR 23000: Duplicate entry '4' for key 1 +UPDATE IGNORE t1 set pk1 = 4 where pk1 = 2; +select * from t1 order by pk1; +pk1 b c +0 0 0 +2 2 2 +4 1 1 UPDATE t1 set pk1 = 1, c = 2 where pk1 = 4; ERROR 23000: Duplicate entry '' for key 0 +UPDATE IGNORE t1 set pk1 = 1, c = 2 where pk1 = 4; select * from t1 order by pk1; pk1 b c 0 0 0 diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 64653de5e9c..7b04c1acdc0 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -760,13 +760,6 @@ xxxxxxxxxxxxxxxxxxxaa xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxz drop table t1; -create table t1 (a int not null, b int not null, c int not null); -insert t1 values (1,1,1),(1,1,2),(1,2,1); -select a, b from t1 group by a, b order by sum(c); -a b -1 2 -1 1 -drop table t1; create table t1 ( `sid` decimal(8,0) default null, `wnid` varchar(11) not null default '', @@ -854,6 +847,40 @@ b a 20 1 10 2 DROP TABLE t1; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +SELECT a + 1 AS num FROM t1 ORDER BY 30 - num; +num +3 +2 +SELECT CONCAT('test', a) AS str FROM t1 ORDER BY UPPER(str); +str +test1 +test2 +SELECT a + 1 AS num FROM t1 GROUP BY 30 - num; +num +3 +2 +SELECT a + 1 AS num FROM t1 HAVING 30 - num; +num +2 +3 +SELECT a + 1 AS num, num + 1 FROM t1; +ERROR 42S22: Unknown column 'num' in 'field list' +SELECT a + 1 AS num, (select num + 2 FROM t1 LIMIT 1) FROM t1; +num (select num + 2 FROM t1 LIMIT 1) +2 4 +3 5 +SELECT a.a + 1 AS num FROM t1 a JOIN t1 b ON num = b.a; +ERROR 42S22: Unknown column 'num' in 'on clause' +DROP TABLE t1; +create table t1 (a int not null, b int not null, c int not null); +insert t1 values (1,1,1),(1,1,2),(1,2,1); +select a, b from t1 group by a, b order by sum(c); +a b +1 2 +1 1 +drop table t1; CREATE TABLE t1 (a int, b int, PRIMARY KEY (a)); INSERT INTO t1 VALUES (1,1), (2,2), (3,3); explain SELECT t1.b as a, t2.b as c FROM diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 003e57edb8e..234c12955d9 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -795,12 +795,12 @@ set @old_max_prepared_stmt_count= @@max_prepared_stmt_count; show variables like 'max_prepared_stmt_count'; Variable_name Value max_prepared_stmt_count 16382 -show variables like 'prepared_stmt_count'; +show status like 'prepared_stmt_count'; Variable_name Value -prepared_stmt_count 0 -select @@max_prepared_stmt_count, @@prepared_stmt_count; -@@max_prepared_stmt_count @@prepared_stmt_count -16382 0 +Prepared_stmt_count 0 +select @@max_prepared_stmt_count; +@@max_prepared_stmt_count +16382 set global max_prepared_stmt_count=-1; select @@max_prepared_stmt_count; @@max_prepared_stmt_count @@ -819,67 +819,70 @@ set max_prepared_stmt_count=1; ERROR HY000: Variable 'max_prepared_stmt_count' is a GLOBAL variable and should be set with SET GLOBAL set local max_prepared_stmt_count=1; ERROR HY000: Variable 'max_prepared_stmt_count' is a GLOBAL variable and should be set with SET GLOBAL -set local prepared_stmt_count=0; -ERROR HY000: Variable 'prepared_stmt_count' is a read only variable -set @@prepared_stmt_count=0; -ERROR HY000: Variable 'prepared_stmt_count' is a read only variable -set global prepared_stmt_count=1; -ERROR HY000: Variable 'prepared_stmt_count' is a read only variable set global max_prepared_stmt_count=1; select @@max_prepared_stmt_count; @@max_prepared_stmt_count 1 set global max_prepared_stmt_count=0; -select @@max_prepared_stmt_count, @@prepared_stmt_count; -@@max_prepared_stmt_count @@prepared_stmt_count -0 0 +select @@max_prepared_stmt_count; +@@max_prepared_stmt_count +0 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 0 prepare stmt from "select 1"; ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 0) -select @@prepared_stmt_count; -@@prepared_stmt_count -0 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 0 set global max_prepared_stmt_count=1; prepare stmt from "select 1"; -select @@prepared_stmt_count; -@@prepared_stmt_count -1 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 1 prepare stmt1 from "select 1"; ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 1) -select @@prepared_stmt_count; -@@prepared_stmt_count -1 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 1 deallocate prepare stmt; -select @@prepared_stmt_count; -@@prepared_stmt_count -0 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 0 prepare stmt from "select 1"; -select @@prepared_stmt_count; -@@prepared_stmt_count -1 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 1 prepare stmt from "select 2"; -select @@prepared_stmt_count; -@@prepared_stmt_count +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 1 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 1 +select @@max_prepared_stmt_count; +@@max_prepared_stmt_count 1 -select @@prepared_stmt_count, @@max_prepared_stmt_count; -@@prepared_stmt_count @@max_prepared_stmt_count -1 1 set global max_prepared_stmt_count=0; prepare stmt from "select 1"; ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 0) execute stmt; ERROR HY000: Unknown prepared statement handler (stmt) given to EXECUTE -select @@prepared_stmt_count; -@@prepared_stmt_count -0 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 0 prepare stmt from "select 1"; ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 0) -select @@prepared_stmt_count; -@@prepared_stmt_count -0 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 0 set global max_prepared_stmt_count=3; -select @@max_prepared_stmt_count, @@prepared_stmt_count; -@@max_prepared_stmt_count @@prepared_stmt_count -3 0 +select @@max_prepared_stmt_count; +@@max_prepared_stmt_count +3 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 0 prepare stmt from "select 1"; prepare stmt from "select 2"; prepare stmt1 from "select 3"; @@ -887,13 +890,13 @@ prepare stmt2 from "select 4"; ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 3) prepare stmt2 from "select 4"; ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 3) -select @@max_prepared_stmt_count, @@prepared_stmt_count; -@@max_prepared_stmt_count @@prepared_stmt_count -3 3 +select @@max_prepared_stmt_count; +@@max_prepared_stmt_count +3 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 3 deallocate prepare stmt; -select @@max_prepared_stmt_count, @@prepared_stmt_count; -@@max_prepared_stmt_count @@prepared_stmt_count -3 0 set global max_prepared_stmt_count= @old_max_prepared_stmt_count; drop table if exists t1; create temporary table if not exists t1 (a1 int); @@ -1475,6 +1478,24 @@ i 1 DEALLOCATE PREPARE stmt; DROP TABLE t1, t2; +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1), (2); +SELECT t1.i FROM t1 JOIN v1 ON t1.i = v1.i +WHERE EXISTS (SELECT * FROM t1 WHERE v1.i = 1); +i +1 +PREPARE stmt FROM "SELECT t1.i FROM t1 JOIN v1 ON t1.i = v1.i +WHERE EXISTS (SELECT * FROM t1 WHERE v1.i = 1)"; +EXECUTE stmt; +i +1 +EXECUTE stmt; +i +1 +DEALLOCATE PREPARE stmt; +DROP VIEW v1; +DROP TABLE t1; DROP PROCEDURE IF EXISTS p1; flush status; prepare sq from 'show status like "slow_queries"'; diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 846c687967d..d2b022a93fb 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -1273,3 +1273,51 @@ Variable_name Value Last_query_cost 0.000000 drop table t1; SET GLOBAL query_cache_size=0; +set global query_cache_size=1024*1024; +flush status; +create table t1 (a int); +insert into t1 (a) values (1), (2), (3); +select * from t1; +a +1 +2 +3 +show status like 'Qcache_hits'; +Variable_name Value +Qcache_hits 0 +select * from t1; +a +1 +2 +3 +show status like 'Qcache_hits'; +Variable_name Value +Qcache_hits 1 +create table t2 like t1; +select * from t1; +a +1 +2 +3 +show status like 'Qcache_hits'; +Variable_name Value +Qcache_hits 2 +insert into t2 select * from t1; +select * from t1; +a +1 +2 +3 +show status like 'Qcache_hits'; +Variable_name Value +Qcache_hits 3 +drop table t1, t2; +create table t1(c1 int); +create table t2(c1 int); +create table t3(c1 int); +create view v1 as select t3.c1 as c1 from t3,t2 where t3.c1 = t2.c1; +start transaction; +insert into t1(c1) select c1 from v1; +drop table t1, t2, t3; +drop view v1; +set global query_cache_size=0; diff --git a/mysql-test/r/read_only.result b/mysql-test/r/read_only.result index 1a1991a6255..69d25fbef6f 100644 --- a/mysql-test/r/read_only.result +++ b/mysql-test/r/read_only.result @@ -39,6 +39,11 @@ 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 temporary table ttt; +ERROR 42S02: Unknown table 'ttt' +drop temporary table if exists ttt; +Warnings: +Note 1051 Unknown table 'ttt' drop table t1,t2; drop user test@localhost; set global read_only=0; diff --git a/mysql-test/r/rpl000015.result b/mysql-test/r/rpl000015.result index e33201ced93..080ef436a2e 100644 --- a/mysql-test/r/rpl000015.result +++ b/mysql-test/r/rpl000015.result @@ -8,7 +8,7 @@ Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File change master to master_host='127.0.0.1'; 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 test MASTER_PORT 7 4 # # No No 0 0 0 # None 0 No # +# 127.0.0.1 test DEFAULT_MASTER_PORT 7 4 # # No No 0 0 0 # None 0 No # change master to master_host='127.0.0.1',master_user='root', master_password='',master_port=MASTER_PORT; show slave status; diff --git a/mysql-test/r/rpl_deadlock.result b/mysql-test/r/rpl_deadlock.result index 63b15bc1a1f..116c34a4d96 100644 --- a/mysql-test/r/rpl_deadlock.result +++ b/mysql-test/r/rpl_deadlock.result @@ -6,7 +6,7 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; create table t1 (a int not null, key(a)) engine=innodb; create table t2 (a int not null, key(a)) engine=innodb; -create table t3 (a int) engine=innodb; +create table t3 (a int unique) engine=innodb; create table t4 (a int) engine=innodb; show variables like 'slave_transaction_retries'; Variable_name Value @@ -35,14 +35,14 @@ begin; select * from t1 for update; a start slave; -insert into t2 values(22); +insert into t2 values(201); commit; select * from t1; a 1 select * from t2; a -22 +201 show slave status; Slave_IO_State # Master_Host 127.0.0.1 @@ -50,7 +50,7 @@ Master_User root Master_Port MASTER_MYPORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 18911 +Read_Master_Log_Pos 18918 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -65,7 +65,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 18911 +Exec_Master_Log_Pos 18918 Relay_Log_Space # Until_Condition None Until_Log_File @@ -78,12 +78,16 @@ Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master # stop slave; -change master to master_log_pos=532; +delete from t3; +change master to master_log_pos=539; begin; select * from t2 for update; a -22 +201 start slave; +select count(*) from t3 /* must be zero */; +count(*) +0 commit; select * from t1; a @@ -91,7 +95,7 @@ a 1 select * from t2; a -22 +201 show slave status; Slave_IO_State # Master_Host 127.0.0.1 @@ -99,7 +103,7 @@ Master_User root Master_Port MASTER_MYPORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 18911 +Read_Master_Log_Pos 18918 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -114,7 +118,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 18911 +Exec_Master_Log_Pos 18918 Relay_Log_Space # Until_Condition None Until_Log_File @@ -129,12 +133,16 @@ Seconds_Behind_Master # set @my_max_relay_log_size= @@global.max_relay_log_size; set global max_relay_log_size=0; stop slave; -change master to master_log_pos=532; +delete from t3; +change master to master_log_pos=539; begin; select * from t2 for update; a -22 +201 start slave; +select count(*) from t3 /* must be zero */; +count(*) +0 commit; select * from t1; a @@ -143,7 +151,7 @@ a 1 select * from t2; a -22 +201 show slave status; Slave_IO_State # Master_Host 127.0.0.1 @@ -151,7 +159,7 @@ Master_User root Master_Port MASTER_MYPORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 18911 +Read_Master_Log_Pos 18918 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -166,7 +174,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 18911 +Exec_Master_Log_Pos 18918 Relay_Log_Space # Until_Condition None Until_Log_File diff --git a/mysql-test/r/rpl_ignore_table.result b/mysql-test/r/rpl_ignore_table.result index 356a9dcb2f8..136cf5cc5eb 100644 --- a/mysql-test/r/rpl_ignore_table.result +++ b/mysql-test/r/rpl_ignore_table.result @@ -14,3 +14,19 @@ SELECT * FROM t4; a DROP TABLE t1; DROP TABLE t4; +DROP TABLE IF EXISTS t5; +CREATE TABLE t5 ( +word varchar(50) collate utf8_unicode_ci NOT NULL default '' +) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +SET @@session.character_set_client=33,@@session.collation_connection=192; +CREATE TEMPORARY TABLE tmptbl504451f4258$1 (id INT NOT NULL) ENGINE=MEMORY; +INSERT INTO t5 (word) VALUES ('TEST’'); +SELECT HEX(word) FROM t5; +HEX(word) +54455354E28099 +SELECT HEX(word) FROM t5; +HEX(word) +54455354E28099 +SELECT * FROM tmptbl504451f4258$1; +ERROR 42S02: Table 'test.tmptbl504451f4258$1' doesn't exist +DROP TABLE t5; diff --git a/mysql-test/r/rpl_packet.result b/mysql-test/r/rpl_packet.result new file mode 100644 index 00000000000..a5c9b43cabb --- /dev/null +++ b/mysql-test/r/rpl_packet.result @@ -0,0 +1,17 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +drop database if exists DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; +create database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; +select @@net_buffer_length, @@max_allowed_packet; +@@net_buffer_length @@max_allowed_packet +1024 1024 +create table `t1` (`f1` LONGTEXT) ENGINE=MyISAM; +INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1023'); +select count(*) from `DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________`.`t1` /* must be 1 */; +count(*) +1 +drop database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result index 7f152862373..a0464e97e28 100644 --- a/mysql-test/r/rpl_sp.result +++ b/mysql-test/r/rpl_sp.result @@ -467,3 +467,25 @@ DROP FUNCTION f1; drop table t1; set global log_bin_trust_function_creators=0; set global log_bin_trust_function_creators=0; +reset master; +drop database if exists mysqltest; +drop database if exists mysqltest2; +create database mysqltest; +create database mysqltest2; +use mysqltest2; +create table t ( t integer ); +create procedure mysqltest.test() begin end; +insert into t values ( 1 ); +show binlog events in 'master-bin.000001' from 98; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 98 Query 1 199 drop database if exists mysqltest +master-bin.000001 199 Query 1 302 drop database if exists mysqltest2 +master-bin.000001 302 Query 1 395 create database mysqltest +master-bin.000001 395 Query 1 490 create database mysqltest2 +master-bin.000001 490 Query 1 587 use `mysqltest2`; create table t ( t integer ) +master-bin.000001 587 Query 1 726 use `mysqltest2`; CREATE DEFINER=`root`@`localhost` procedure mysqltest.test() begin end +master-bin.000001 726 Query 1 821 use `mysqltest2`; insert into t values ( 1 ) +create procedure `\\`.test() begin end; +ERROR 42000: Incorrect database name '\\' +drop database mysqltest; +drop database mysqltest2; diff --git a/mysql-test/r/rpl_trigger.result b/mysql-test/r/rpl_trigger.result index 3c740bf8e64..f8573eec75f 100644 --- a/mysql-test/r/rpl_trigger.result +++ b/mysql-test/r/rpl_trigger.result @@ -941,3 +941,30 @@ c ---> Cleaning up... DROP TABLE t1; DROP TABLE t2; +drop table if exists t1; +create table t1(a int, b varchar(50)); +drop trigger not_a_trigger; +ERROR HY000: Trigger does not exist +drop trigger if exists not_a_trigger; +Warnings: +Note 1360 Trigger does not exist +create trigger t1_bi before insert on t1 +for each row set NEW.b := "In trigger t1_bi"; +insert into t1 values (1, "a"); +drop trigger if exists t1_bi; +insert into t1 values (2, "b"); +drop trigger if exists t1_bi; +Warnings: +Note 1360 Trigger does not exist +insert into t1 values (3, "c"); +select * from t1; +a b +1 In trigger t1_bi +2 b +3 c +select * from t1; +a b +1 In trigger t1_bi +2 b +3 c +drop table t1; diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 28cbdb16919..0dfb7c95f9a 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -296,7 +296,7 @@ SET sql_quote_show_create= @old_sql_quote_show_create; SET sql_mode= @old_sql_mode; select @@max_heap_table_size; @@max_heap_table_size -1047552 +1048576 CREATE TABLE t1 ( a int(11) default NULL, KEY a USING BTREE (a) diff --git a/mysql-test/r/strict_autoinc_1myisam.result b/mysql-test/r/strict_autoinc_1myisam.result index 5d3c2698cda..90a69bedc74 100644 --- a/mysql-test/r/strict_autoinc_1myisam.result +++ b/mysql-test/r/strict_autoinc_1myisam.result @@ -1,3 +1,4 @@ +drop table if exists t1; set @org_mode=@@sql_mode; create table t1 ( diff --git a/mysql-test/r/strict_autoinc_2innodb.result b/mysql-test/r/strict_autoinc_2innodb.result index f1936ff4de3..8a5243173e4 100644 --- a/mysql-test/r/strict_autoinc_2innodb.result +++ b/mysql-test/r/strict_autoinc_2innodb.result @@ -1,3 +1,4 @@ +drop table if exists t1; set @org_mode=@@sql_mode; create table t1 ( diff --git a/mysql-test/r/strict_autoinc_3heap.result b/mysql-test/r/strict_autoinc_3heap.result index aa0be270ac5..7dc48357c46 100644 --- a/mysql-test/r/strict_autoinc_3heap.result +++ b/mysql-test/r/strict_autoinc_3heap.result @@ -1,3 +1,4 @@ +drop table if exists t1; set @org_mode=@@sql_mode; create table t1 ( diff --git a/mysql-test/r/strict_autoinc_4bdb.result b/mysql-test/r/strict_autoinc_4bdb.result index 73683b645e2..89c4d2537f5 100644 --- a/mysql-test/r/strict_autoinc_4bdb.result +++ b/mysql-test/r/strict_autoinc_4bdb.result @@ -1,3 +1,4 @@ +drop table if exists t1; set @org_mode=@@sql_mode; create table t1 ( diff --git a/mysql-test/r/strict_autoinc_5ndb.result b/mysql-test/r/strict_autoinc_5ndb.result index d0d62d05b32..715f9a4b98b 100644 --- a/mysql-test/r/strict_autoinc_5ndb.result +++ b/mysql-test/r/strict_autoinc_5ndb.result @@ -1,3 +1,4 @@ +drop table if exists t1; set @org_mode=@@sql_mode; create table t1 ( diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index ec9fc2c307b..43247b56096 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -744,7 +744,7 @@ id select_type table type possible_keys key key_len ref rows Extra 3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL Warnings: -Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`id`,<exists>(select 1 AS `1` having (<cache>(`test`.`t2`.`id`) = <ref_null_helper>(1)) union select 3 AS `3` having (<cache>(`test`.`t2`.`id`) = <ref_null_helper>(3)))) +Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`id`,<exists>(select 1 AS `1` having trigcond((<cache>(`test`.`t2`.`id`) = <ref_null_helper>(1))) union select 3 AS `3` having trigcond((<cache>(`test`.`t2`.`id`) = <ref_null_helper>(3))))) SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3); id SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2); @@ -907,7 +907,7 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 Using where; Using index 2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1` +Note 1003 select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and trigcond(((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`)))) having trigcond(<is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1` drop table t1,t2,t3; create table t1 (a float); select 10.5 IN (SELECT * from t1 LIMIT 1); @@ -2816,19 +2816,19 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 Using where Warnings: -Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = _latin1'0') and ((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`)) and ((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`))) having (<is_not_null_test>(`test`.`t2`.`one`) and <is_not_null_test>(`test`.`t2`.`two`)))) AS `test` from `test`.`t1` +Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = _latin1'0') and trigcond((((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`)) and ((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`))))) having trigcond((<is_not_null_test>(`test`.`t2`.`one`) and <is_not_null_test>(`test`.`t2`.`two`))))) AS `test` from `test`.`t1` explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N'); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 Using where Warnings: -Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = _latin1'N') and (<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) and (<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`)))) +Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = _latin1'N') and trigcond(((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) and (<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`)))))) explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 Using where; Using temporary; Using filesort Warnings: -Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where (`test`.`t2`.`flag` = _latin1'0') group by `test`.`t2`.`one`,`test`.`t2`.`two` having (((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`)) and ((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)) and <is_not_null_test>(`test`.`t2`.`one`) and <is_not_null_test>(`test`.`t2`.`two`)))) AS `test` from `test`.`t1` +Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where (`test`.`t2`.`flag` = _latin1'0') group by `test`.`t2`.`one`,`test`.`t2`.`two` having trigcond((((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`)) and ((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)) and <is_not_null_test>(`test`.`t2`.`one`) and <is_not_null_test>(`test`.`t2`.`two`))))) AS `test` from `test`.`t1` DROP TABLE t1,t2; CREATE TABLE t1 (a char(5), b char(5)); INSERT INTO t1 VALUES (NULL,'aaa'), ('aaa','aaa'); @@ -3001,6 +3001,38 @@ field1 field2 1 1 1 3 DROP TABLE t1, t2; +CREATE TABLE t1(a int, INDEX (a)); +INSERT INTO t1 VALUES (1), (3), (5), (7); +INSERT INTO t1 VALUES (NULL); +CREATE TABLE t2(a int); +INSERT INTO t2 VALUES (1),(2),(3); +EXPLAIN SELECT a, a IN (SELECT a FROM t1) FROM t2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 3 +2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 Using index +SELECT a, a IN (SELECT a FROM t1) FROM t2; +a a IN (SELECT a FROM t1) +1 1 +2 NULL +3 1 +DROP TABLE t1,t2; +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('1998-09-23'), ('2003-03-25'); +CREATE TABLE t2 AS SELECT +(SELECT a FROM t1 WHERE a < '2000-01-01') AS sub_a +FROM t1 WHERE a > '2000-01-01'; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `sub_a` datetime default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +CREATE TABLE t3 AS (SELECT a FROM t1 WHERE a < '2000-01-01') UNION (SELECT a FROM t1 WHERE a > '2000-01-01'); +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `a` datetime default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1,t2,t3; create table t1 (df decimal(5,1)); insert into t1 values(1.1); insert into t1 values(2.2); @@ -3544,3 +3576,19 @@ FROM t1 GROUP BY t1.a LIMIT 1) 2 2 DROP TABLE t1,t2; +CREATE TABLE t1 (a int, b int auto_increment, PRIMARY KEY (b)); +CREATE TABLE t2 (x int auto_increment, y int, z int, +PRIMARY KEY (x), FOREIGN KEY (y) REFERENCES t1 (b)); +SET SESSION sort_buffer_size = 32 * 1024; +SELECT SQL_NO_CACHE COUNT(*) +FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c +FROM t1) t; +COUNT(*) +3000 +SET SESSION sort_buffer_size = 8 * 1024 * 1024; +SELECT SQL_NO_CACHE COUNT(*) +FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c +FROM t1) t; +COUNT(*) +3000 +DROP TABLE t1,t2; diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result new file mode 100644 index 00000000000..5ab8e448b39 --- /dev/null +++ b/mysql-test/r/subselect3.result @@ -0,0 +1,153 @@ +drop table if exists t0, t1, t2, t3, t4; +create table t1 (oref int, grp int, ie int) ; +insert into t1 (oref, grp, ie) values +(1, 1, 1), +(1, 1, 1), +(1, 2, NULL), +(2, 1, 3), +(3, 1, 4), +(3, 2, NULL); +create table t2 (oref int, a int); +insert into t2 values +(1, 1), +(2, 2), +(3, 3), +(4, NULL), +(2, NULL); +select a, oref, a in (select max(ie) +from t1 where oref=t2.oref group by grp) from t2; +a oref a in (select max(ie) +from t1 where oref=t2.oref group by grp) +1 1 1 +2 2 0 +3 3 NULL +NULL 4 0 +NULL 2 NULL +explain extended +select a, oref, a in (select max(ie) +from t1 where oref=t2.oref group by grp) from t2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 5 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 Using where; Using temporary; Using filesort +Warnings: +Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1 +Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref`,<in_optimizer>(`test`.`t2`.`a`,<exists>(select max(`test`.`t1`.`ie`) AS `max(ie)` from `test`.`t1` where (`test`.`t1`.`oref` = `test`.`t2`.`oref`) group by `test`.`t1`.`grp` having trigcond((<cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))) AS `a in (select max(ie) +from t1 where oref=t2.oref group by grp)` from `test`.`t2` +explain extended +select a, oref from t2 +where a in (select max(ie) from t1 where oref=t2.oref group by grp); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 Using where; Using temporary; Using filesort +Warnings: +Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1 +Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select max(`test`.`t1`.`ie`) AS `max(ie)` from `test`.`t1` where (`test`.`t1`.`oref` = `test`.`t2`.`oref`) group by `test`.`t1`.`grp` having (<cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`))))) +create table t3 (a int); +insert into t3 values (NULL), (NULL); +flush status; +select a in (select max(ie) from t1 where oref=4 group by grp) from t3; +a in (select max(ie) from t1 where oref=4 group by grp) +0 +0 +show status like 'Handler_read_rnd_next'; +Variable_name Value +Handler_read_rnd_next 11 +select ' ^ This must show 11' Z; +Z + ^ This must show 11 +explain extended select a in (select max(ie) from t1 where oref=4 group by grp) from t3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 Using where; Using temporary; Using filesort +Warnings: +Note 1003 select <in_optimizer>(`test`.`t3`.`a`,<exists>(select max(`test`.`t1`.`ie`) AS `max(ie)` from `test`.`t1` where (`test`.`t1`.`oref` = 4) group by `test`.`t1`.`grp` having trigcond((<cache>(`test`.`t3`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))) AS `a in (select max(ie) from t1 where oref=4 group by grp)` from `test`.`t3` +drop table t1, t2, t3; +create table t1 (a int, oref int, key(a)); +insert into t1 values +(1, 1), +(1, NULL), +(2, 3), +(2, NULL), +(3, NULL); +create table t2 (a int, oref int); +insert into t2 values (1, 1), (2,2), (NULL, 3), (NULL, 4); +select oref, a, a in (select a from t1 where oref=t2.oref) Z from t2; +oref a Z +1 1 1 +2 2 0 +3 NULL NULL +4 NULL 0 +explain extended +select oref, a, a in (select a from t1 where oref=t2.oref) Z from t2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 +2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 Using index; Using where +Warnings: +Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1 +Note 1003 select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a checking NULL where (`test`.`t1`.`oref` = `test`.`t2`.`oref`)))) AS `Z` from `test`.`t2` +flush status; +select oref, a from t2 where a in (select a from t1 where oref=t2.oref); +oref a +1 1 +show status like '%Handler_read_rnd_next'; +Variable_name Value +Handler_read_rnd_next 5 +delete from t2; +insert into t2 values (NULL, 0),(NULL, 0), (NULL, 0), (NULL, 0); +flush status; +select oref, a, a in (select a from t1 where oref=t2.oref) Z from t2; +oref a Z +0 NULL 0 +0 NULL 0 +0 NULL 0 +0 NULL 0 +show status like '%Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 29 +select 'No key lookups, seq reads: 29= 5 reads from t2 + 4 * 6 reads from t1.' Z; +Z +No key lookups, seq reads: 29= 5 reads from t2 + 4 * 6 reads from t1. +drop table t1, t2; +create table t1 (a int, b int, primary key (a)); +insert into t1 values (1,1), (3,1),(100,1); +create table t2 (a int, b int); +insert into t2 values (1,1),(2,1),(NULL,1),(NULL,0); +select a,b, a in (select a from t1 where t1.b = t2.b) Z from t2 ; +a b Z +1 1 1 +2 1 0 +NULL 1 NULL +NULL 0 0 +drop table t1, t2; +create table t1 (a int, b int, key(a)); +insert into t1 values +(0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9); +create table t2 like t1; +insert into t2 select * from t1; +update t2 set b=1; +create table t3 (a int, oref int); +insert into t3 values (1, 1), (NULL,1), (NULL,0); +select a, oref, +t3.a in (select t1.a from t1, t2 where t1.b=t2.a and t2.b=t3.oref) Z +from t3; +a oref Z +1 1 1 +NULL 1 NULL +NULL 0 0 +explain extended +select a, oref, +t3.a in (select t1.a from t1, t2 where t1.b=t2.a and t2.b=t3.oref) Z +from t3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 3 +2 DEPENDENT SUBQUERY t1 ref_or_null a a 5 func 4 Using where +2 DEPENDENT SUBQUERY t2 ref a a 5 test.t1.b 1 Using where +Warnings: +Note 1276 Field or reference 't3.oref' of SELECT #2 was resolved in SELECT #1 +Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<in_optimizer>(`test`.`t3`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t2`.`b` = `test`.`t3`.`oref`) and trigcond(((<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a`) or isnull(`test`.`t1`.`a`)))) having trigcond(<is_not_null_test>(`test`.`t1`.`a`)))) AS `Z` from `test`.`t3` +drop table t1, t2, t3; diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index 272836c450a..4725bcc0ac9 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -111,3 +111,26 @@ t1 CREATE TABLE `t1` ( `i` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +show create table t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/log/' +show create table t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/log/' +create table t1 (a int) engine=myisam select 42 a; +select * from t1; +a +9 +select * from t1; +a +99 +select * from t1; +a +42 +drop table t1; +End of 4.1 tests +End of 5.0 tests diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 5d643057666..9f34f60eb1a 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1241,4 +1241,41 @@ i j 2 2 13 13 drop table t1; +drop table if exists t1; +drop function if exists f1; +create table t1 (i int); +create function f1() returns int return 10; +create trigger t1_bi before insert on t1 for each row set @a:= f1() + 10; +insert into t1 values (); +select @a; +@a +20 +insert into t1 values (); +select @a; +@a +20 +drop table t1; +drop function f1; +drop table if exists t1; +create table t1(a int, b varchar(50)); +drop trigger not_a_trigger; +ERROR HY000: Trigger does not exist +drop trigger if exists not_a_trigger; +Warnings: +Note 1360 Trigger does not exist +create trigger t1_bi before insert on t1 +for each row set NEW.b := "In trigger t1_bi"; +insert into t1 values (1, "a"); +drop trigger if exists t1_bi; +insert into t1 values (2, "b"); +drop trigger if exists t1_bi; +Warnings: +Note 1360 Trigger does not exist +insert into t1 values (3, "c"); +select * from t1; +a b +1 In trigger t1_bi +2 b +3 c +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index bd58e83bb3f..f3883077919 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -610,4 +610,12 @@ select hex(a), b from t1; hex(a) b 1 2 drop table t1; +create table t1(bit_field bit(2), int_field int, key a(bit_field)); +insert into t1 values (1,2); +handler t1 open as t1; +handler t1 read a=(1); +bit_field int_field + 2 +handler t1 close; +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index 49e4827cb97..7fc1c4f398d 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -179,3 +179,15 @@ a 2006-06-06 15:55:55 DROP PREPARE s; DROP TABLE t1; +SELECT CAST(CAST('2006-08-10' AS DATE) AS DECIMAL(20,6)); +CAST(CAST('2006-08-10' AS DATE) AS DECIMAL(20,6)) +20060810.000000 +SELECT CAST(CAST('2006-08-10 10:11:12' AS DATETIME) AS DECIMAL(20,6)); +CAST(CAST('2006-08-10 10:11:12' AS DATETIME) AS DECIMAL(20,6)) +20060810101112.000000 +SELECT CAST(CAST('2006-08-10 10:11:12' AS DATETIME) + INTERVAL 14 MICROSECOND AS DECIMAL(20,6)); +CAST(CAST('2006-08-10 10:11:12' AS DATETIME) + INTERVAL 14 MICROSECOND AS DECIMAL(20,6)) +20060810101112.000014 +SELECT CAST(CAST('10:11:12.098700' AS TIME) AS DECIMAL(20,6)); +CAST(CAST('10:11:12.098700' AS TIME) AS DECIMAL(20,6)) +101112.098700 diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 84d2ea47298..e65e76ded3f 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1410,3 +1410,16 @@ i2 count(distinct j) 1.0 2 2.0 2 drop table t1; +create table t1(f1 decimal(20,6)); +insert into t1 values (CAST('10:11:12' AS date) + interval 14 microsecond); +insert into t1 values (CAST('10:11:12' AS time)); +select * from t1; +f1 +20101112000000.000014 +101112.000000 +drop table t1; +select cast(19999999999999999999 as unsigned); +cast(19999999999999999999 as unsigned) +18446744073709551615 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result index 1d707b83a4d..f6c2f4d01a6 100644 --- a/mysql-test/r/type_varchar.result +++ b/mysql-test/r/type_varchar.result @@ -453,3 +453,39 @@ id name_id id en cz 2 3 2 en string 2 cz string 2 3 3 3 en string 3 cz string 3 drop table t1, t2, t3; +CREATE TABLE t1 (a CHAR(2)); +INSERT INTO t1 VALUES (10), (50), (30), ('1a'), (60), ('t'); +SELECT a,(a + 0) FROM t1 ORDER BY a; +a (a + 0) +10 10 +1a 1 +30 30 +50 50 +60 60 +t 0 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '1a' +Warning 1292 Truncated incorrect DOUBLE value: 't ' +SELECT a,(a DIV 2) FROM t1 ORDER BY a; +a (a DIV 2) +10 5 +1a 0 +30 15 +50 25 +60 30 +t 0 +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '1a' +Warning 1292 Truncated incorrect INTEGER value: 't ' +SELECT a,CAST(a AS SIGNED) FROM t1 ORDER BY a; +a CAST(a AS SIGNED) +10 10 +1a 1 +30 30 +50 50 +60 60 +t 0 +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '1a' +Warning 1292 Truncated incorrect INTEGER value: 't' +DROP TABLE t1; diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index 8501b82fcdf..eb5d771bcfe 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -105,6 +105,85 @@ explain select myfunc_int(f1) from t1 order by 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort drop table t1; +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 values (1,1),(2,2); +CREATE FUNCTION fn(a int) RETURNS int DETERMINISTIC +BEGIN +RETURN a; +END +|| +CREATE VIEW v1 AS SELECT a, fn(MIN(b)) as c FROM t1 GROUP BY a; +SELECT myfunc_int(a AS attr_name) FROM t1; +myfunc_int(a AS attr_name) +1 +2 +EXPLAIN EXTENDED SELECT myfunc_int(a AS attr_name) FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 +Warnings: +Note 1003 select myfunc_int(`test`.`t1`.`a` AS `attr_name`) AS `myfunc_int(a AS attr_name)` from `test`.`t1` +EXPLAIN EXTENDED SELECT myfunc_int(a) FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 +Warnings: +Note 1003 select myfunc_int(`test`.`t1`.`a` AS `a`) AS `myfunc_int(a)` from `test`.`t1` +SELECT a,c FROM v1; +a c +1 1 +2 2 +SELECT a, fn(MIN(b) xx) as c FROM t1 GROUP BY a; +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 'xx) as c FROM t1 GROUP BY a' at line 1 +SELECT myfunc_int(fn(MIN(b) xx)) as c FROM t1 GROUP BY a; +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 'xx)) as c FROM t1 GROUP BY a' at line 1 +SELECT myfunc_int(test.fn(MIN(b) xx)) as c FROM t1 GROUP BY a; +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 'xx)) as c FROM t1 GROUP BY a' at line 1 +SELECT myfunc_int(fn(MIN(b)) xx) as c FROM t1 GROUP BY a; +c +1 +2 +SELECT myfunc_int(test.fn(MIN(b)) xx) as c FROM t1 GROUP BY a; +c +1 +2 +EXPLAIN EXTENDED SELECT myfunc_int(MIN(b) xx) as c FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +Warnings: +Note 1003 select myfunc_int(min(`test`.`t1`.`b`) AS `xx`) AS `c` from `test`.`t1` group by `test`.`t1`.`a` +EXPLAIN EXTENDED SELECT test.fn(MIN(b)) as c FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +Warnings: +Note 1003 select `test`.`fn`(min(`test`.`t1`.`b`)) AS `c` from `test`.`t1` group by `test`.`t1`.`a` +EXPLAIN EXTENDED SELECT myfunc_int(fn(MIN(b))) as c FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +Warnings: +Note 1003 select myfunc_int(`test`.`fn`(min(`test`.`t1`.`b`)) AS `fn(MIN(b))`) AS `c` from `test`.`t1` group by `test`.`t1`.`a` +EXPLAIN EXTENDED SELECT myfunc_int(test.fn(MIN(b))) as c FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +Warnings: +Note 1003 select myfunc_int(`test`.`fn`(min(`test`.`t1`.`b`)) AS `test.fn(MIN(b))`) AS `c` from `test`.`t1` group by `test`.`t1`.`a` +SELECT myfunc_int(MIN(b) xx) as c FROM t1 GROUP BY a; +c +1 +2 +SELECT test.fn(MIN(b)) as c FROM t1 GROUP BY a; +c +1 +2 +SELECT myfunc_int(fn(MIN(b))) as c FROM t1 GROUP BY a; +c +1 +2 +SELECT myfunc_int(test.fn(MIN(b))) as c FROM t1 GROUP BY a; +c +1 +2 +DROP VIEW v1; +DROP TABLE t1; +DROP FUNCTION fn; End of 5.0 tests. DROP FUNCTION metaphon; DROP FUNCTION myfunc_double; diff --git a/mysql-test/r/varbinary.result b/mysql-test/r/varbinary.result index e62051df5cd..2b8a9c625a5 100644 --- a/mysql-test/r/varbinary.result +++ b/mysql-test/r/varbinary.result @@ -26,3 +26,55 @@ select x,xx from t1; x xx 1 2 drop table t1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varbinary(255) default NULL, + `b` varchar(255) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select length(a), length(b) from t1; +length(a) length(b) +255 3 +255 3 +CHECK TABLE t1 FOR UPGRADE; +Table Op Msg_type Msg_text +test.t1 check error Table upgrade required. Please do "REPAIR TABLE `t1`" to fix it! +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varbinary(255) default NULL, + `b` varchar(255) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select length(a), length(b) from t1; +length(a) length(b) +3 3 +3 3 +insert into t1 values("ccc", "ddd"); +select length(a), length(b) from t1; +length(a) length(b) +3 3 +3 3 +3 3 +select hex(a), hex(b) from t1; +hex(a) hex(b) +616161 636363 +626262 646464 +636363 646464 +select concat("'", a, "'"), concat("'", b, "'") from t1; +concat("'", a, "'") concat("'", b, "'") +'aaa' 'ccc' +'bbb' 'ddd' +'ccc' 'ddd' +drop table t1; +create table t1(a varbinary(255)); +insert into t1 values("aaa "); +select length(a) from t1; +length(a) +6 +alter table t1 modify a varchar(255); +select length(a) from t1; +length(a) +6 diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index cf9ba1c604d..a802d83e9a2 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -712,3 +712,22 @@ DROP FUNCTION f1; DROP VIEW v2; DROP VIEW v1; DROP USER mysqltest_u1@localhost; +CREATE DATABASE db17254; +USE db17254; +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (10),(20); +CREATE USER def_17254@localhost; +GRANT SELECT ON db17254.* TO def_17254@localhost; +CREATE USER inv_17254@localhost; +GRANT SELECT ON db17254.t1 TO inv_17254@localhost; +GRANT CREATE VIEW ON db17254.* TO def_17254@localhost; +CREATE VIEW v1 AS SELECT * FROM t1; +DROP USER def_17254@localhost; +for a user +SELECT * FROM v1; +ERROR 42000: SELECT command denied to user 'inv_17254'@'localhost' for table 'v1' +for a superuser +SELECT * FROM v1; +ERROR HY000: There is no 'def_17254'@'localhost' registered +DROP USER inv_17254@localhost; +DROP DATABASE db17254; diff --git a/mysql-test/r/windows.result b/mysql-test/r/windows.result index 039c5b1476e..1702fd28c18 100644 --- a/mysql-test/r/windows.result +++ b/mysql-test/r/windows.result @@ -6,3 +6,9 @@ use prn; ERROR 42000: Unknown database 'prn' create table nu (a int); drop table nu; +drop table if exists t1; +CREATE TABLE t1 ( `ID` int(6) ) data directory 'c:/tmp/' index directory 'c:/tmp/' engine=MyISAM; +Warnings: +Warning 0 DATA DIRECTORY option ignored +Warning 0 INDEX DIRECTORY option ignored +drop table t1; diff --git a/mysql-test/std_data/bug19371.MYD b/mysql-test/std_data/bug19371.MYD Binary files differnew file mode 100644 index 00000000000..1b58a70832f --- /dev/null +++ b/mysql-test/std_data/bug19371.MYD diff --git a/mysql-test/std_data/bug19371.MYI b/mysql-test/std_data/bug19371.MYI Binary files differnew file mode 100644 index 00000000000..06ee5b2d766 --- /dev/null +++ b/mysql-test/std_data/bug19371.MYI diff --git a/mysql-test/std_data/bug19371.frm b/mysql-test/std_data/bug19371.frm Binary files differnew file mode 100644 index 00000000000..7be45d6f8da --- /dev/null +++ b/mysql-test/std_data/bug19371.frm diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 7c23a5ca410..233726ce923 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -372,6 +372,103 @@ alter table t1 add unique ( a(1) ); drop table t1; # +# Bug #24395: ALTER TABLE DISABLE KEYS doesn't work when modifying the table +# +# This problem happens if the data change is compatible. +# Changing to the same type is compatible for example. +# +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a int, key(a)); +show indexes from t1; +--echo "this used not to disable the index" +alter table t1 modify a int, disable keys; +show indexes from t1; + +alter table t1 enable keys; +show indexes from t1; + +alter table t1 modify a bigint, disable keys; +show indexes from t1; + +alter table t1 enable keys; +show indexes from t1; + +alter table t1 add b char(10), disable keys; +show indexes from t1; + +alter table t1 add c decimal(10,2), enable keys; +show indexes from t1; + +--echo "this however did" +alter table t1 disable keys; +show indexes from t1; + +desc t1; + +alter table t1 add d decimal(15,5); +--echo "The key should still be disabled" +show indexes from t1; + +drop table t1; + +--echo "Now will test with one unique index" +create table t1(a int, b char(10), unique(a)); +show indexes from t1; +alter table t1 disable keys; +show indexes from t1; +alter table t1 enable keys; + +--echo "If no copy on noop change, this won't touch the data file" +--echo "Unique index, no change" +alter table t1 modify a int, disable keys; +show indexes from t1; + +--echo "Change the type implying data copy" +--echo "Unique index, no change" +alter table t1 modify a bigint, disable keys; +show indexes from t1; + +alter table t1 modify a bigint; +show indexes from t1; + +alter table t1 modify a int; +show indexes from t1; + +drop table t1; + +--echo "Now will test with one unique and one non-unique index" +create table t1(a int, b char(10), unique(a), key(b)); +show indexes from t1; +alter table t1 disable keys; +show indexes from t1; +alter table t1 enable keys; + + +--echo "If no copy on noop change, this won't touch the data file" +--echo "The non-unique index will be disabled" +alter table t1 modify a int, disable keys; +show indexes from t1; +alter table t1 enable keys; +show indexes from t1; + +--echo "Change the type implying data copy" +--echo "The non-unique index will be disabled" +alter table t1 modify a bigint, disable keys; +show indexes from t1; + +--echo "Change again the type, but leave the indexes as_is" +alter table t1 modify a int; +show indexes from t1; +--echo "Try the same. When data is no copied on similar tables, this is noop" +alter table t1 modify a int; +show indexes from t1; + +drop table t1; + + +# # Bug#11493 - Alter table rename to default database does not work without # db name qualifying # diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index f712a770712..80533f21311 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -1345,10 +1345,14 @@ SELECT * FROM t2; CHECK TABLE t2; SELECT * FROM t2; - -# Just test syntax, we will never know if the output is right or wrong -# Must be the last test +# Test INSERT DELAYED and wait until the table has one more record +SELECT COUNT(auto) FROM t2; INSERT DELAYED INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily',''); +while (`SELECT COUNT(auto)!=1214 FROM t2`) +{ + sleep 0.1; +} +SELECT COUNT(auto) FROM t2; # Adding test for alter table ALTER TABLE t2 DROP COLUMN fld6; diff --git a/mysql-test/t/bdb-deadlock.test b/mysql-test/t/bdb-deadlock.test index 88243cfc860..b48648e0fd0 100644 --- a/mysql-test/t/bdb-deadlock.test +++ b/mysql-test/t/bdb-deadlock.test @@ -1,11 +1,3 @@ -# This test doesn't work with the embedded version as this code -# assumes that one query is running while we are doing queries on -# a second connection. -# This would work if mysqltest run would be threaded and handle each -# connection in a separate thread. -# - --- source include/not_embedded.inc -- source include/have_bdb.inc connect (con1,localhost,root,,); diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 91c22001b6c..eef6ec85bfa 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -550,7 +550,7 @@ create table t1 ( a varchar(112) charset utf8 collate utf8_bin not null, primary key (a) ) select 'test' as a ; ---warning 1364 +#--warning 1364 show create table t1; drop table t1; @@ -563,7 +563,7 @@ CREATE TABLE t2 ( ); insert into t2 values(111); ---warning 1364 +#--warning 1364 create table t1 ( a varchar(12) charset utf8 collate utf8_bin not null, b int not null, primary key (a) @@ -571,7 +571,7 @@ create table t1 ( show create table t1; drop table t1; ---warning 1364 +#--warning 1364 create table t1 ( a varchar(12) charset utf8 collate utf8_bin not null, b int not null, primary key (a) @@ -579,7 +579,7 @@ create table t1 ( show create table t1; drop table t1; ---warning 1364 +#--warning 1364 create table t1 ( a varchar(12) charset utf8 collate utf8_bin not null, b int null, primary key (a) @@ -587,7 +587,7 @@ create table t1 ( show create table t1; drop table t1; ---warning 1364 +#--warning 1364 create table t1 ( a varchar(12) charset utf8 collate utf8_bin not null, b int not null, primary key (a) @@ -595,7 +595,7 @@ create table t1 ( show create table t1; drop table t1; ---warning 1364 +#--warning 1364 create table t1 ( a varchar(12) charset utf8 collate utf8_bin, b int not null, primary key (a) @@ -609,7 +609,7 @@ create table t1 ( ); insert into t1 values (1,1,1, 1,1,1, 1,1,1); ---warning 1364 +#--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, @@ -617,20 +617,20 @@ create table t2 ( ) select a1,a2,a3,a4,a5,a6,a7,a8,a9 from t1 ; drop table t2; ---warning 1364 +#--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 +#--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 +#--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, diff --git a/mysql-test/t/csv.test b/mysql-test/t/csv.test index 65173cbf355..830bdaa3cf0 100644 --- a/mysql-test/t/csv.test +++ b/mysql-test/t/csv.test @@ -1360,27 +1360,27 @@ DROP TABLE bug14672; create table t1 (a int) engine=csv; insert t1 values (1); --enable_info -delete from t1; -- delete_row -delete from t1; -- delete_all_rows +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 +delete from t1; # delete_all_rows --disable_info insert t1 values (1),(2),(3); flush tables; --enable_info -delete from t1; -- delete_row +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 +delete from t1; # delete_all_rows --disable_info insert t1 values (1),(2),(3),(4),(5); --enable_info -truncate table t1; -- truncate +truncate table t1; # truncate --disable_info drop table t1; diff --git a/mysql-test/t/ctype_collate.test b/mysql-test/t/ctype_collate.test index e59693680bf..aca240b46bc 100644 --- a/mysql-test/t/ctype_collate.test +++ b/mysql-test/t/ctype_collate.test @@ -59,7 +59,7 @@ INSERT INTO t1 (latin1_f) VALUES (_latin1'Z'); INSERT INTO t1 (latin1_f) VALUES (_latin1'z'); --- ORDER BY +# ORDER BY SELECT latin1_f FROM t1 ORDER BY latin1_f; SELECT latin1_f FROM t1 ORDER BY latin1_f COLLATE latin1_swedish_ci; @@ -69,9 +69,9 @@ SELECT latin1_f FROM t1 ORDER BY latin1_f COLLATE latin1_bin; --error 1253 SELECT latin1_f FROM t1 ORDER BY latin1_f COLLATE koi8r_general_ci; ---SELECT latin1_f COLLATE koi8r FROM t1 ; +# SELECT latin1_f COLLATE koi8r FROM t1 ; --- AS + ORDER BY +# AS + ORDER BY SELECT latin1_f COLLATE latin1_swedish_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as; SELECT latin1_f COLLATE latin1_german2_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as; SELECT latin1_f COLLATE latin1_general_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as; @@ -80,7 +80,7 @@ SELECT latin1_f COLLATE latin1_bin AS latin1_f_as FROM t1 ORDER BY latin1 SELECT latin1_f COLLATE koi8r_general_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as; --- GROUP BY +# GROUP BY SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f; SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f COLLATE latin1_swedish_ci; @@ -91,7 +91,7 @@ SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f COLLATE latin1_bin; SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f COLLATE koi8r_general_ci; --- DISTINCT +# DISTINCT SELECT DISTINCT latin1_f FROM t1; SELECT DISTINCT latin1_f COLLATE latin1_swedish_ci FROM t1; @@ -102,21 +102,20 @@ SELECT DISTINCT latin1_f COLLATE latin1_bin FROM t1; SELECT DISTINCT latin1_f COLLATE koi8r FROM t1; --- Aggregates ---SELECT MAX(k COLLATE latin1_german2_ci) ---FROM t1 - - --- WHERE ---SELECT * ---FROM t1 ---WHERE (_latin1'Mu"ller' COLLATE latin1_german2_ci) = k - ---HAVING ---SELECT * ---FROM t1 ---HAVING (_latin1'Mu"ller' COLLATE latin1_german2_ci) = k - +# Aggregates + +--disable_parsing +SELECT MAX(k COLLATE latin1_german2_ci) +FROM t1 +WHERE +SELECT * +FROM t1 +WHERE (_latin1'Mu"ller' COLLATE latin1_german2_ci) = k +HAVING +SELECT * +FROM t1 +HAVING (_latin1'Mu"ller' COLLATE latin1_german2_ci) = k; +--enable_parsing # # Check that SHOW displays COLLATE clause diff --git a/mysql-test/t/ctype_cp1250_ch.test b/mysql-test/t/ctype_cp1250_ch.test index 65550e0c193..86eb8c31d99 100644 --- a/mysql-test/t/ctype_cp1250_ch.test +++ b/mysql-test/t/ctype_cp1250_ch.test @@ -1,5 +1,9 @@ -- source include/have_cp1250_ch.inc +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + SHOW COLLATION LIKE 'cp1250_czech_cs'; # diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 6c814368c88..5a3720dc431 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -298,7 +298,7 @@ INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA); SELECT HEX(a) FROM t1; DROP TABLE t1; --- the same should be also done with enum and set +# the same should be also done with enum and set # @@ -455,6 +455,23 @@ drop table t1; deallocate prepare stmt; # +# Bug#22052 Trailing spaces are not removed from UNICODE fields in an index +# +create table t1 ( + a char(10) unicode not null, + index a (a) +) engine=myisam; +insert into t1 values (repeat(0x201f, 10)); +insert into t1 values (repeat(0x2020, 10)); +insert into t1 values (repeat(0x2021, 10)); +# make sure "index read" is used +explain select hex(a) from t1 order by a; +select hex(a) from t1 order by a; +alter table t1 drop index a; +select hex(a) from t1 order by a; +drop table t1; + +# # Bug #20076: server crashes for a query with GROUP BY if MIN/MAX aggregation # over a 'ucs2' field uses a temporary table # diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 812965d648a..71259dab0c9 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1228,6 +1228,30 @@ set @a:=null; execute my_stmt using @a; drop table if exists t1; + +# +# Bug#21505 Create view - illegal mix of collation for operation 'UNION' +# +--disable_warnings +drop table if exists t1; +drop view if exists v1, v2; +--enable_warnings +set names utf8; +create table t1(col1 varchar(12) character set utf8 collate utf8_unicode_ci); +insert into t1 values('t1_val'); +create view v1 as select 'v1_val' as col1; +select coercibility(col1), collation(col1) from v1; +create view v2 as select col1 from v1 union select col1 from t1; +select coercibility(col1), collation(col1)from v2; +drop view v1, v2; +create view v1 as select 'v1_val' collate utf8_swedish_ci as col1; +select coercibility(col1), collation(col1) from v1; +create view v2 as select col1 from v1 union select col1 from t1; +select coercibility(col1), collation(col1) from v2; +drop view v1, v2; +drop table t1; + + # # Bug#19960: Inconsistent results when joining # InnoDB tables using partial UTF8 indexes diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index eaea7c710b0..53b73363c22 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -12,4 +12,5 @@ ndb_load : Bug#17233 user_limits : Bug#23921 random failure of user_limits.test +flush2 : Bug#24805 Pushbuild can't handle test with --disable-log-bin diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test index e517380ba9b..b2cc42cc0ff 100644 --- a/mysql-test/t/distinct.test +++ b/mysql-test/t/distinct.test @@ -437,3 +437,70 @@ EXPLAIN SELECT DISTINCT a,a FROM t1 WHERE b < 12 ORDER BY a; SELECT DISTINCT a,a FROM t1 WHERE b < 12 ORDER BY a; DROP TABLE t1; +# The test case for bug#20836 should be re-enabled when bug#16861 is resolved +# The results for the test should be the same as in 4.1. +# +#Bug #20836: Selecting into variables results in wrong results being returned +# +#--disable_warnings +#DROP TABLE IF EXISTS t1; +#--enable_warnings +# +#CREATE TABLE t1 (id INT NOT NULL, fruit_id INT NOT NULL, fruit_name varchar(20) +#default NULL); +# +#INSERT INTO t1 VALUES (1,1,'ORANGE'); +#INSERT INTO t1 VALUES (2,2,'APPLE'); +#INSERT INTO t1 VALUES (3,2,'APPLE'); +#INSERT INTO t1 VALUES (4,3,'PEAR'); +# +#SELECT DISTINCT fruit_id, fruit_name INTO @v1, @v2 FROM t1 WHERE fruit_name = +#'APPLE'; +#SELECT @v1, @v2; +# +#SELECT DISTINCT fruit_id, fruit_name INTO @v3, @v4 FROM t1 GROUP BY fruit_id, +#fruit_name HAVING fruit_name = 'APPLE'; +#SELECT @v3, @v4; +# +#SELECT DISTINCT @v5:= fruit_id, @v6:= fruit_name INTO @v7, @v8 FROM t1 WHERE +#fruit_name = 'APPLE'; +#SELECT @v5, @v6, @v7, @v8; +# +#SELECT DISTINCT @v5 + fruit_id, CONCAT(@v6, fruit_name) INTO @v9, @v10 FROM t1 +#WHERE fruit_name = 'APPLE'; +#SELECT @v5, @v6, @v7, @v8, @v9, @v10; +# +#SELECT DISTINCT @v11:= @v5 + fruit_id, @v12:= CONCAT(@v6, fruit_name) INTO +#@v13, @v14 FROM t1 WHERE fruit_name = 'APPLE'; +#SELECT @v11, @v12, @v13, @v14; +# +#SELECT DISTINCT @v13, @v14 INTO @v15, @v16 FROM t1 WHERE fruit_name = 'APPLE'; +#SELECT @v15, @v16; +# +#SELECT DISTINCT 2 + 2, 'Bob' INTO @v17, @v18 FROM t1 WHERE fruit_name = +#'APPLE'; +#SELECT @v17, @v18; +# +#--disable_warnings +#DROP TABLE IF EXISTS t2; +#--enable_warnings +# +#CREATE TABLE t2 (fruit_id INT NOT NULL, fruit_name varchar(20) +#default NULL); +# +#SELECT DISTINCT fruit_id, fruit_name INTO OUTFILE +#'../tmp/data1.tmp' FROM t1 WHERE fruit_name = 'APPLE'; +#LOAD DATA INFILE '../tmp/data1.tmp' INTO TABLE t2; +#--exec rm $MYSQL_TEST_DIR/var/tmp/data1.tmp +# +#SELECT DISTINCT @v19:= fruit_id, @v20:= fruit_name INTO OUTFILE +#'../tmp/data2.tmp' FROM t1 WHERE fruit_name = 'APPLE'; +#LOAD DATA INFILE '../tmp/data2.tmp' INTO TABLE t2; +#--exec rm $MYSQL_TEST_DIR/var/tmp/data2.tmp +# +#SELECT @v19, @v20; +#SELECT * FROM t2; +# +#DROP TABLE t1; +#DROP TABLE t2; + diff --git a/mysql-test/t/fix_priv_tables.test b/mysql-test/t/fix_priv_tables.test new file mode 100644 index 00000000000..3a91f41dfcc --- /dev/null +++ b/mysql-test/t/fix_priv_tables.test @@ -0,0 +1,66 @@ +# Embedded server doesn't support external clients +--source include/not_embedded.inc + +# +# This is the test for mysql_fix_privilege_tables +# It checks that a system tables from mysql 4.1.23 +# can be upgraded to current system table format +# +# Note: If this test fails, don't be confused about the errors reported +# by mysql-test-run This shows warnings generated by +# mysql_fix_system_tables which should be ignored. +# Instead, concentrate on the errors in r/system_mysql_db.reject + +--disable_warnings +drop table if exists t1,t1aa,t2aa; +--enable_warnings + +# +# Bug #20589 Missing some table level privileges after upgrade +# +# Add some grants that should survive the "upgrade" + +--disable_warnings +DROP DATABASE IF EXISTS testdb; +--enable_warnings +CREATE DATABASE testdb; +CREATE TABLE testdb.t1 ( + c1 INT, + c3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY); + +CREATE VIEW testdb.v1 AS + SELECT * FROM testdb.t1; + +GRANT CREATE VIEW, SHOW VIEW ON testdb.v1 TO 'show_view_tbl'@'localhost'; +SHOW GRANTS FOR 'show_view_tbl'@'localhost'; +echo; + +# Some extra GRANTS for more complete test +GRANT SELECT(c1) on testdb.v1 to 'select_only_c1'@localhost; +SHOW GRANTS FOR 'select_only_c1'@'localhost'; +echo; + +-- disable_result_log +-- disable_query_log + +# Run the mysql_fix_privilege_tables.sql using "mysql --force" +--exec $MYSQL --force mysql < $MYSQL_FIX_PRIVILEGE_TABLES > $MYSQLTEST_VARDIR/log/fix_priv_tables.log 2>&1 + +-- enable_query_log +-- enable_result_log + +echo "after fix privs"; + +SHOW GRANTS FOR 'show_view_tbl'@'localhost'; +echo; +SHOW GRANTS FOR 'select_only_c1'@'localhost'; +echo; + +DROP USER 'show_view_tbl'@'localhost'; +DROP USER 'select_only_c1'@'localhost'; + +DROP VIEW testdb.v1; +DROP TABLE testdb.t1; +DROP DATABASE testdb; + +# End of 4.1 tests diff --git a/mysql-test/t/flush.test b/mysql-test/t/flush.test index 95ba633fefd..3a4f2f2f5f2 100644 --- a/mysql-test/t/flush.test +++ b/mysql-test/t/flush.test @@ -1,11 +1,3 @@ -# This test doesn't work with the embedded version as this code -# assumes that one query is running while we are doing queries on -# a second connection. -# This would work if mysqltest run would be threaded and handle each -# connection in a separate thread. -# --- source include/not_embedded.inc - connect (con1,localhost,root,,); connect (con2,localhost,root,,); connection con1; diff --git a/mysql-test/t/flush2-master.opt b/mysql-test/t/flush2-master.opt new file mode 100644 index 00000000000..ccbd01c91d3 --- /dev/null +++ b/mysql-test/t/flush2-master.opt @@ -0,0 +1 @@ +--disable-log-bin diff --git a/mysql-test/t/flush2.test b/mysql-test/t/flush2.test new file mode 100644 index 00000000000..fc9e88e3141 --- /dev/null +++ b/mysql-test/t/flush2.test @@ -0,0 +1,9 @@ +# +# Bug#17733 Flushing logs causes daily server crash +# +flush logs; +set global expire_logs_days = 3; +show variables like 'log%'; +flush logs; +show variables like 'log%'; +set global expire_logs_days = 0; diff --git a/mysql-test/t/flush_block_commit.test b/mysql-test/t/flush_block_commit.test index ebb48242a4d..4412b2c357c 100644 --- a/mysql-test/t/flush_block_commit.test +++ b/mysql-test/t/flush_block_commit.test @@ -3,9 +3,6 @@ # We verify that we did not introduce a deadlock. # This is intended to mimick how mysqldump and innobackup work. -# This test doesn't work with the embedded server --- source include/not_embedded.inc - # And it requires InnoDB -- source include/have_innodb.inc diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 769f10277d4..3ff4b35873b 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -29,8 +29,10 @@ select grp,group_concat(c order by c) from t1 group by grp; select grp,group_concat(c order by c desc) from t1 group by grp; select grp,group_concat(d order by a) from t1 group by grp; select grp,group_concat(d order by a desc) from t1 group by grp; +--disable_warnings select grp,group_concat(a order by a,d+c-ascii(c)-a) from t1 group by grp; select grp,group_concat(a order by d+c-ascii(c),a) from t1 group by grp; +--enable_warnings select grp,group_concat(c order by 1) from t1 group by grp; select grp,group_concat(distinct c order by c) from t1 group by grp; select grp,group_concat(distinct c order by c desc) from t1 group by grp; @@ -461,3 +463,38 @@ SELECT GROUP_CONCAT(a), x GROUP BY x; DROP TABLE t1; +# +# Bug#23451 GROUP_CONCAT truncates a multibyte utf8 character +# +set names utf8; +create table t1 +( + x text character set utf8 not null, + y integer not null +); +insert into t1 values (repeat('a', 1022), 0), (repeat(_utf8 0xc3b7, 4), 0); +let $1= 10; +while ($1) +{ + eval set group_concat_max_len= 1022 + $1; + --disable_result_log + select @x:=group_concat(x) from t1 group by y; + --enable_result_log + select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); + dec $1; +} +drop table t1; +set group_concat_max_len=1024; +set names latin1; + +# +# Bug#14169 type of group_concat() result changed to blob if tmp_table was used +# +create table t1 (f1 int unsigned, f2 varchar(255)); +insert into t1 values (1,repeat('a',255)),(2,repeat('b',255)); +--enable_metadata +select f2,group_concat(f1) from t1 group by f2; +--disable_metadata +drop table t1; + +# End of 4.1 tests diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 079d107fad8..bccd4d9e762 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -29,7 +29,9 @@ select count(distinct a),count(distinct grp) from t1; select sum(all a),count(all a),avg(all a),std(all a),variance(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1; select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp; +--disable_warnings select grp, sum(a)+count(a)+avg(a)+std(a)+variance(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp; +--enable_warnings create table t2 (grp int, a bigint unsigned, c char(10)); insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp; @@ -700,3 +702,28 @@ create table t1 select stddev(0); show create table t1; drop table t1; +# +# Bug #23184: SELECT causes server crash +# +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8); +INSERT INTO t1 SELECT a, b+8 FROM t1; +INSERT INTO t1 SELECT a, b+16 FROM t1; +INSERT INTO t1 SELECT a, b+32 FROM t1; +INSERT INTO t1 SELECT a, b+64 FROM t1; +INSERT INTO t1 SELECT a, b+128 FROM t1; +INSERT INTO t1 SELECT a, b+256 FROM t1; +INSERT INTO t1 SELECT a, b+512 FROM t1; +INSERT INTO t1 SELECT a, b+1024 FROM t1; +INSERT INTO t1 SELECT a, b+2048 FROM t1; +INSERT INTO t1 SELECT a, b+4096 FROM t1; +INSERT INTO t1 SELECT a, b+8192 FROM t1; +INSERT INTO t1 SELECT a, b+16384 FROM t1; +INSERT INTO t1 SELECT a, b+32768 FROM t1; +SELECT a,COUNT(DISTINCT b) AS cnt FROM t1 GROUP BY a HAVING cnt > 50; +SELECT a,SUM(DISTINCT b) AS sumation FROM t1 GROUP BY a HAVING sumation > 50; +SELECT a,AVG(DISTINCT b) AS average FROM t1 GROUP BY a HAVING average > 50; + +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 8ddf1fbe314..86b0268f008 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -109,7 +109,28 @@ select count(*) from t1 where id not in (1); select count(*) from t1 where id not in (1,2); drop table t1; -# End of 4.1 tests + +# +# BUG#17047: CHAR() and IN() can return NULL without signaling NULL +# result +# +# The problem was in the IN() function that ignored maybe_null flags +# of all arguments except the first (the one _before_ the IN +# keyword, '1' in the test case below). +# +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 SELECT 1 IN (2, NULL); +--echo SELECT should return NULL. +SELECT * FROM t1; + +DROP TABLE t1; + + +--echo End of 4.1 tests + # # Bug #11885: WHERE condition with NOT IN (one element) @@ -231,4 +252,14 @@ insert into t1 values (1),(2); select some_id from t1 where some_id not in(2,-1); select some_id from t1 where some_id not in(-4,-1,-4); select some_id from t1 where some_id not in(-4,-1,3423534,2342342); + +# +# BUG#24261: crash when WHERE contains NOT IN ('<negative value>') for unsigned column type +# + +select some_id from t1 where some_id not in('-1', '0'); + drop table t1; + + +--echo End of 5.0 tests diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 52a5512d070..5cac6c45f65 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -125,4 +125,11 @@ drop table t2; drop table t1; set global query_cache_size=default; +# +# Bug #21466: INET_ATON() returns signed, not unsigned +# + +create table t1 select INET_ATON('255.255.0.1') as `a`; +show create table t1; +drop table t1; --echo End of 5.0 tests diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test index 97101fba615..77d7366afe6 100644 --- a/mysql-test/t/func_sapdb.test +++ b/mysql-test/t/func_sapdb.test @@ -35,7 +35,7 @@ SET @@SQL_MODE="ALLOW_INVALID_DATES"; select datediff("1997-11-31 23:59:59.000001","1997-12-31"); SET @@SQL_MODE=""; --- This will give a warning +# This will give a warning select datediff("1997-11-31 23:59:59.000001","1997-12-31"); select datediff("1997-11-30 23:59:59.000001",null); diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 9622de96143..af4f8b9a9d2 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -300,18 +300,26 @@ select POSITION(_latin1'B' COLLATE latin1_general_ci IN _latin1'abcd' COLLATE la select POSITION(_latin1'B' IN _latin2'abcd'); select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d'); ---fix this: ---select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d' COLLATE latin1_bin); ---select FIND_IN_SET(_latin1'B' COLLATE latin1_bin,_latin1'a,b,c,d'); + +# fix this: +--disable_parsing +select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d' COLLATE latin1_bin); +select FIND_IN_SET(_latin1'B' COLLATE latin1_bin,_latin1'a,b,c,d'); +--enable_parsing + --error 1267 select FIND_IN_SET(_latin1'B' COLLATE latin1_general_ci,_latin1'a,b,c,d' COLLATE latin1_bin); --error 1267 select FIND_IN_SET(_latin1'B',_latin2'a,b,c,d'); select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2); ---fix this: ---select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_bin,_latin1'd',2); ---select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd' COLLATE latin1_bin,2); + +# fix this: +--disable_parsing +select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_bin,_latin1'd',2); +select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd' COLLATE latin1_bin,2); +--enable_parsing + --error 1267 select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2); --error 1267 @@ -780,6 +788,7 @@ SELECT * FROM t1 INNER JOIN t2 ON code=id DROP TABLE t1,t2; + # # Bug #10963 # 4294967296 18446744073709551616 @@ -969,4 +978,18 @@ select lpad('hello', 18446744073709551616, '1'); select lpad('hello', -18446744073709551617, '1'); select lpad('hello', 18446744073709551617, '1'); + +# +# BUG#17047: CHAR() and IN() can return NULL without signaling NULL +# result +# +SET @orig_sql_mode = @@SQL_MODE; +SET SQL_MODE=traditional; + +SELECT CHAR(0xff,0x8f USING utf8); +SELECT CHAR(0xff,0x8f USING utf8) IS NULL; + +SET SQL_MODE=@orig_sql_mode; + + --echo End of 5.0 tests diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index b0c2c50d4d1..a69cbb67c5b 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -707,3 +707,9 @@ SELECT DATE_FORMAT(field1,'%b-%e %l:%i%p') as fmtddate, field2 FROM testBug8868; DROP TABLE testBug8868; SET NAMES DEFAULT; + +# +# Bug #22229: bug in DATE_ADD() +# + +select str_to_date('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE; diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test index 09cdcb2435e..e34dd14dbfc 100644 --- a/mysql-test/t/gis-rtree.test +++ b/mysql-test/t/gis-rtree.test @@ -242,3 +242,15 @@ INSERT INTO t1 (foo) VALUES (PointFromWKB(POINT(0,0))); SELECT 1 FROM t1 WHERE foo != PointFromWKB(POINT(0,0)); DROP TABLE t1; # End of 4.1 tests + +# +# bug #21790 (UNKNOWN ERROR on NULLs in RTree) +# +CREATE TABLE t1(foo GEOMETRY NOT NULL, SPATIAL INDEX(foo) ); +--error 1048 +INSERT INTO t1(foo) VALUES (NULL); +--error 1416 +INSERT INTO t1() VALUES (); +--error 1416 +INSERT INTO t1(foo) VALUES (''); +DROP TABLE t1; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index d3781d58780..2f5e3dced22 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -118,7 +118,7 @@ drop table t1; # --error 1221 GRANT FILE on mysqltest.* to mysqltest_1@localhost; -select 1; -- To test that the previous command didn't cause problems +select 1; # To test that the previous command didn't cause problems # # Bug #4898: User privileges depending on ORDER BY Settings of table db diff --git a/mysql-test/t/greedy_optimizer.test b/mysql-test/t/greedy_optimizer.test index e547d85b7f3..049d0ab09f7 100644 --- a/mysql-test/t/greedy_optimizer.test +++ b/mysql-test/t/greedy_optimizer.test @@ -140,18 +140,18 @@ insert into t7 values (21,2,3,4,5,6); select @@optimizer_search_depth; select @@optimizer_prune_level; --- This value swithes back to the old implementation of 'find_best()' --- set optimizer_search_depth=63; - old (independent of the optimizer_prune_level) --- --- These are the values for the parameters that control the greedy optimizer --- (total 6 combinations - 3 for optimizer_search_depth, 2 for optimizer_prune_level): +# This value swithes back to the old implementation of 'find_best()' +# set optimizer_search_depth=63; - old (independent of the optimizer_prune_level) +# +# These are the values for the parameters that control the greedy optimizer +# (total 6 combinations - 3 for optimizer_search_depth, 2 for optimizer_prune_level): -- --- set optimizer_search_depth=0; - automatic --- set optimizer_search_depth=1; - min --- set optimizer_search_depth=62; - max (default) +# set optimizer_search_depth=0; - automatic +# set optimizer_search_depth=1; - min +# set optimizer_search_depth=62; - max (default) -- --- set optimizer_prune_level=0 - exhaustive; --- set optimizer_prune_level=1 - heuristic; -- default +# set optimizer_prune_level=0 - exhaustive; +# set optimizer_prune_level=1 - heuristic; # default # @@ -170,17 +170,17 @@ select @@optimizer_prune_level; set optimizer_search_depth=63; select @@optimizer_search_depth; --- 6-table join, chain +# 6-table join, chain explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, star +# 6-table join, star explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, clique +# 6-table join, clique explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; @@ -195,17 +195,17 @@ select @@optimizer_prune_level; set optimizer_search_depth=0; select @@optimizer_search_depth; --- 6-table join, chain +# 6-table join, chain explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, star +# 6-table join, star explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, clique +# 6-table join, clique explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; @@ -214,17 +214,17 @@ show status like 'Last_query_cost'; set optimizer_search_depth=1; select @@optimizer_search_depth; --- 6-table join, chain +# 6-table join, chain explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, star +# 6-table join, star explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, clique +# 6-table join, clique explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; @@ -233,17 +233,17 @@ show status like 'Last_query_cost'; set optimizer_search_depth=62; select @@optimizer_search_depth; --- 6-table join, chain +# 6-table join, chain explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, star +# 6-table join, star explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, clique +# 6-table join, clique explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; @@ -256,17 +256,17 @@ select @@optimizer_prune_level; set optimizer_search_depth=0; select @@optimizer_search_depth; --- 6-table join, chain +# 6-table join, chain explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, star +# 6-table join, star explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, clique +# 6-table join, clique explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; @@ -275,17 +275,17 @@ show status like 'Last_query_cost'; set optimizer_search_depth=1; select @@optimizer_search_depth; --- 6-table join, chain +# 6-table join, chain explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, star +# 6-table join, star explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, clique +# 6-table join, clique explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; @@ -294,17 +294,17 @@ show status like 'Last_query_cost'; set optimizer_search_depth=62; select @@optimizer_search_depth; --- 6-table join, chain +# 6-table join, chain explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, star +# 6-table join, star explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; show status like 'Last_query_cost'; --- 6-table join, clique +# 6-table join, clique explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; show status like 'Last_query_cost'; explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 08f0f54df60..b3049498f90 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -57,8 +57,8 @@ create index idx_t1_1 on t1 (a1,a2,b,c); create index idx_t1_2 on t1 (a1,a2,b); analyze table t1; --- t2 is the same as t1, but with some NULLs in the MIN/MAX column, and one more --- nullable attribute +# t2 is the same as t1, but with some NULLs in the MIN/MAX column, and +# one more nullable attribute --disable_warnings drop table if exists t2; @@ -68,7 +68,7 @@ create table t2 ( a1 char(64), a2 char(64) not null, b char(16), c char(16), d char(16), dummy char(64) default ' ' ); insert into t2 select * from t1; --- add few rows with NULL's in the MIN/MAX column +# add few rows with NULL's in the MIN/MAX column insert into t2 (a1, a2, b, c, d) values ('a','a',NULL,'a777','xyz'),('a','a',NULL,'a888','xyz'),('a','a',NULL,'a999','xyz'), ('a','a','a',NULL,'xyz'), @@ -92,10 +92,10 @@ create index idx_t2_1 on t2 (a1,a2,b,c); create index idx_t2_2 on t2 (a1,a2,b); analyze table t2; --- Table t3 is the same as t1, but with smaller column lenghts. --- This allows to test different branches of the cost computation procedure --- when the number of keys per block are less than the number of keys in the --- sub-groups formed by predicates over non-group attributes. +# Table t3 is the same as t1, but with smaller column lenghts. +# This allows to test different branches of the cost computation procedure +# when the number of keys per block are less than the number of keys in the +# sub-groups formed by predicates over non-group attributes. --disable_warnings drop table if exists t3; @@ -164,11 +164,11 @@ create index idx_t3_2 on t3 (a1,a2,b); analyze table t3; --- --- Queries without a WHERE clause. These queries do not use ranges. --- +# +# Queries without a WHERE clause. These queries do not use ranges. +# --- plans +# plans explain select a1, min(a2) from t1 group by a1; explain select a1, max(a2) from t1 group by a1; explain select a1, min(a2), max(a2) from t1 group by a1; @@ -176,31 +176,31 @@ explain select a1, a2, b, min(c), max(c) from t1 group by a1,a2,b; explain select a1,a2,b,max(c),min(c) from t1 group by a1,a2,b; --replace_column 7 # 9 # explain select a1,a2,b,max(c),min(c) from t2 group by a1,a2,b; --- Select fields in different order +# Select fields in different order explain select min(a2), a1, max(a2), min(a2), a1 from t1 group by a1; explain select a1, b, min(c), a1, max(c), b, a2, max(c), max(c) from t1 group by a1, a2, b; explain select min(a2) from t1 group by a1; explain select a2, min(c), max(c) from t1 group by a1,a2,b; --- queries +# queries select a1, min(a2) from t1 group by a1; select a1, max(a2) from t1 group by a1; select a1, min(a2), max(a2) from t1 group by a1; select a1, a2, b, min(c), max(c) from t1 group by a1,a2,b; select a1,a2,b,max(c),min(c) from t1 group by a1,a2,b; select a1,a2,b,max(c),min(c) from t2 group by a1,a2,b; --- Select fields in different order +# Select fields in different order select min(a2), a1, max(a2), min(a2), a1 from t1 group by a1; select a1, b, min(c), a1, max(c), b, a2, max(c), max(c) from t1 group by a1, a2, b; select min(a2) from t1 group by a1; select a2, min(c), max(c) from t1 group by a1,a2,b; --- --- Queries with a where clause --- +# +# Queries with a where clause +# --- A) Preds only over the group 'A' attributes --- plans +# A) Preds only over the group 'A' attributes +# plans explain select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b; explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b; explain select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b; @@ -238,7 +238,7 @@ explain select a1,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b; --replace_column 9 # explain select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b; --- queries +# queries select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b; select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b; select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b; @@ -264,8 +264,8 @@ select a1,a2,b,min(c),max(c) from t2 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or select a1,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b; select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b; --- B) Equalities only over the non-group 'B' attributes --- plans +# B) Equalities only over the non-group 'B' attributes +# plans explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1; explain select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1; explain select a1,a2,b, max(c) from t1 where (b = 'b') group by a1,a2; @@ -278,11 +278,11 @@ explain select a1,a2,b, max(c) from t2 where (b = 'b') group by a1,a2; explain select a1,a2,b,min(c),max(c) from t2 where (b = 'b') group by a1,a2; explain select a1,a2, max(c) from t2 where (b = 'b') group by a1,a2; --- these queries test case 2) in TRP_GROUP_MIN_MAX::update_cost() +# these queries test case 2) in TRP_GROUP_MIN_MAX::update_cost() explain select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1; explain select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1; --- queries +# queries select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1; select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1; select a1,a2,b, max(c) from t1 where (b = 'b') group by a1,a2; @@ -295,20 +295,20 @@ select a1,a2,b, max(c) from t2 where (b = 'b') group by a1,a2; select a1,a2,b,min(c),max(c) from t2 where (b = 'b') group by a1,a2; select a1,a2, max(c) from t2 where (b = 'b') group by a1,a2; --- these queries test case 2) in TRP_GROUP_MIN_MAX::update_cost() +# these queries test case 2) in TRP_GROUP_MIN_MAX::update_cost() select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1; select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1; --- IS NULL (makes sense for t2 only) --- plans +# IS NULL (makes sense for t2 only) +# plans explain select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1; explain select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1; explain select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2; explain select a1,a2,b,max(c) from t2 where b is NULL group by a1,a2; explain select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2; explain select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2; --- queries +# queries select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1; select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1; select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2; @@ -316,8 +316,8 @@ select a1,a2,b,max(c) from t2 where b is NULL group by a1,a2; select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2; select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2; --- C) Range predicates for the MIN/MAX attribute --- plans +# C) Range predicates for the MIN/MAX attribute +# plans --replace_column 9 # explain select a1,a2,b, max(c) from t1 where (c > 'b1') group by a1,a2,b; explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') group by a1,a2,b; @@ -367,7 +367,7 @@ explain select a1,a2,b,min(c),max(c) from t2 where (c < 'c5') or (c = 'g412') or --replace_column 9 # explain select a1,a2,b,min(c),max(c) from t2 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b; --- queries +# queries select a1,a2,b, max(c) from t1 where (c > 'b1') group by a1,a2,b; select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') group by a1,a2,b; select a1,a2,b, max(c) from t1 where (c > 'f123') group by a1,a2,b; @@ -401,19 +401,19 @@ select a1,a2,b,min(c),max(c) from t2 where (c > 'b111') and (c <= 'g112') group select a1,a2,b,min(c),max(c) from t2 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b; select a1,a2,b,min(c),max(c) from t2 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b; --- analyze the sub-select +# analyze the sub-select explain select a1,a2,b,min(c),max(c) from t1 where exists ( select * from t2 where t2.c = t1.c ) group by a1,a2,b; --- the sub-select is unrelated to MIN/MAX +# the sub-select is unrelated to MIN/MAX explain select a1,a2,b,min(c),max(c) from t1 where exists ( select * from t2 where t2.c > 'b1' ) group by a1,a2,b; --- A,B,C) Predicates referencing mixed classes of attributes --- plans +# A,B,C) Predicates referencing mixed classes of attributes +# plans explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b; explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b; explain select a1,a2,b,min(c),max(c) from t1 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b; @@ -435,7 +435,7 @@ explain select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 --replace_column 9 # explain select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b; --- queries +# queries select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b; select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b; select a1,a2,b,min(c),max(c) from t1 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b; @@ -452,11 +452,11 @@ select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b; --- --- GROUP BY queries without MIN/MAX --- +# +# GROUP BY queries without MIN/MAX +# --- plans +# plans explain select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b; explain select a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b; explain select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b; @@ -471,7 +471,7 @@ explain select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121' --replace_column 9 # explain select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b; --- queries +# queries select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b; select a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b; select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b; @@ -482,11 +482,11 @@ select a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b; select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b; select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b; --- --- DISTINCT queries --- +# +# DISTINCT queries +# --- plans +# plans explain select distinct a1,a2,b from t1; explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a'); explain select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); @@ -502,7 +502,7 @@ explain select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c'); explain select distinct b from t2 where (a2 >= 'b') and (b = 'a'); --- queries +# queries select distinct a1,a2,b from t1; select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a'); select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); @@ -515,22 +515,22 @@ select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121 select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c'); select distinct b from t2 where (a2 >= 'b') and (b = 'a'); --- BUG #6303 +# BUG #6303 select distinct t_00.a1 from t1 t_00 where exists ( select * from t2 where a1 = t_00.a1 ); --- BUG #8532 - SELECT DISTINCT a, a causes server to crash +# BUG #8532 - SELECT DISTINCT a, a causes server to crash select distinct a1,a1 from t1; select distinct a2,a1,a2,a1 from t1; select distinct t1.a1,t2.a1 from t1,t2; --- --- DISTINCT queries with GROUP-BY --- +# +# DISTINCT queries with GROUP-BY +# --- plans +# plans explain select distinct a1,a2,b from t1; explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b; explain select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b; @@ -548,7 +548,7 @@ explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = --replace_column 9 # explain select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b; --- queries +# queries select distinct a1,a2,b from t1; select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b; select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b; @@ -562,9 +562,9 @@ select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') gr select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b; --- --- COUNT (DISTINCT cols) queries --- +# +# COUNT (DISTINCT cols) queries +# explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a'); explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); @@ -578,9 +578,9 @@ select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a'); select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a'); --- --- Queries with expressions in the select clause --- +# +# Queries with expressions in the select clause +# explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b; explain select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b; @@ -595,48 +595,48 @@ select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b; select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2; --- --- Negative examples: queries that should NOT be treated as optimizable by --- QUICK_GROUP_MIN_MAX_SELECT --- +# +# Negative examples: queries that should NOT be treated as optimizable by +# QUICK_GROUP_MIN_MAX_SELECT +# --- select a non-indexed attribute +# select a non-indexed attribute explain select a1,a2,b,d,min(c),max(c) from t1 group by a1,a2,b; explain select a1,a2,b,d from t1 group by a1,a2,b; --- predicate that references an attribute that is after the MIN/MAX argument --- in the index +# predicate that references an attribute that is after the MIN/MAX argument +# in the index explain select a1,a2,min(b),max(b) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2; --- predicate that references a non-indexed attribute +# predicate that references a non-indexed attribute explain select a1,a2,b,min(c),max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b; explain select a1,a2,b,c from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b,c; --- non-equality predicate for a non-group select attribute +# non-equality predicate for a non-group select attribute explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b < 'b') group by a1; explain select a1,a2,b from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2,b; --- non-group field with an equality predicate that references a keypart after the --- MIN/MAX argument +# non-group field with an equality predicate that references a keypart after the +# MIN/MAX argument explain select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1; select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1; --- disjunction for a non-group select attribute +# disjunction for a non-group select attribute explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b = 'a') group by a1; --- non-range predicate for the MIN/MAX attribute +# non-range predicate for the MIN/MAX attribute explain select a1,a2,b,min(c),max(c) from t2 where (c > 'a000') and (c <= 'd999') and (c like '_8__') group by a1,a2,b; --- not all attributes are indexed by one index +# not all attributes are indexed by one index explain select a1, a2, b, c, min(d), max(d) from t1 group by a1,a2,b,c; --- other aggregate functions than MIN/MAX +# other aggregate functions than MIN/MAX explain select a1,a2,count(a2) from t1 group by a1,a2,b; explain select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b; explain select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b; @@ -765,24 +765,24 @@ INSERT INTO t4 VALUES(1); INSERT INTO t5 VALUES(1,1); INSERT INTO t6 VALUES(1); --- original bug query +# original bug query SELECT * FROM t1 NATURAL JOIN (t2 JOIN (t3 NATURAL JOIN t4, t5 NATURAL JOIN t6) ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5)); --- inner join swapped +# inner join swapped SELECT * FROM t1 NATURAL JOIN (((t3 NATURAL JOIN t4) join (t5 NATURAL JOIN t6) on t3.id4 = t5.id5) JOIN t2 ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5)); --- one join less, no ON cond +# one join less, no ON cond SELECT * FROM t1 NATURAL JOIN ((t3 join (t5 NATURAL JOIN t6)) JOIN t2); --- wrong error message: 'id2' - ambiguous column +# wrong error message: 'id2' - ambiguous column SELECT * FROM (t2 JOIN (t3 NATURAL JOIN t4, t5 NATURAL JOIN t6) ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5)) @@ -810,3 +810,63 @@ explain SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a; SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a; DROP TABLE t1,t2; + +# +# Bug#24156: Loose index scan not used with CREATE TABLE ...SELECT and similar statements +# + +CREATE TABLE t1 (a INT, b INT, INDEX (a,b)); +INSERT INTO t1 (a, b) VALUES (1,1), (1,2), (1,3), (1,4), (1,5), + (2,2), (2,3), (2,1), (3,1), (4,1), (4,2), (4,3), (4,4), (4,5), (4,6); +EXPLAIN SELECT max(b), a FROM t1 GROUP BY a; +FLUSH STATUS; +SELECT max(b), a FROM t1 GROUP BY a; +SHOW STATUS LIKE 'handler_read__e%'; +EXPLAIN SELECT max(b), a FROM t1 GROUP BY a; +FLUSH STATUS; +CREATE TABLE t2 SELECT max(b), a FROM t1 GROUP BY a; +SHOW STATUS LIKE 'handler_read__e%'; +FLUSH STATUS; +SELECT * FROM (SELECT max(b), a FROM t1 GROUP BY a) b; +SHOW STATUS LIKE 'handler_read__e%'; +FLUSH STATUS; +(SELECT max(b), a FROM t1 GROUP BY a) UNION + (SELECT max(b), a FROM t1 GROUP BY a); +SHOW STATUS LIKE 'handler_read__e%'; +EXPLAIN (SELECT max(b), a FROM t1 GROUP BY a) UNION + (SELECT max(b), a FROM t1 GROUP BY a); + +EXPLAIN SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x + FROM t1 AS t1_outer; +EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE EXISTS + (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2); +EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE + (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12; +EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE + a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2); +EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING + a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2); +EXPLAIN SELECT 1 FROM t1 AS t1_outer1 JOIN t1 AS t1_outer2 + ON t1_outer1.a = (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) + AND t1_outer1.b = t1_outer2.b; +EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x + FROM t1 AS t1_outer) x2 FROM t1 AS t1_outer2; + +CREATE TABLE t3 LIKE t1; +FLUSH STATUS; +INSERT INTO t3 SELECT a,MAX(b) FROM t1 GROUP BY a; +SHOW STATUS LIKE 'handler_read__e%'; +DELETE FROM t3; +FLUSH STATUS; +INSERT INTO t3 SELECT 1, (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) + FROM t1 LIMIT 1; +SHOW STATUS LIKE 'handler_read__e%'; +FLUSH STATUS; +DELETE FROM t3 WHERE (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) > 10000; +SHOW STATUS LIKE 'handler_read__e%'; +FLUSH STATUS; +DELETE FROM t3 WHERE (SELECT (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) x + FROM t1) > 10000; +SHOW STATUS LIKE 'handler_read__e%'; + +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest index 65db9dee93f..acd615809f3 100644 --- a/mysql-test/t/im_daemon_life_cycle.imtest +++ b/mysql-test/t/im_daemon_life_cycle.imtest @@ -6,59 +6,73 @@ # ########################################################################### +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle im_daemon_life_cycle.imtest started. + +########################################################################### + --source include/im_check_env.inc -# Turn on reconnect, not on by default anymore +# Turn on reconnect, not on by default anymore. --enable_reconnect ########################################################################### +# +# The main daemon-life-cycle test case -- check that IM-angel will restart +# IM-main if it got killed: +# - kill IM-main and check that IM-angel will restart it; +# - wait for IM-main to start accepting connections before continue test +# case; +# +########################################################################### -# Kill the IM main process and check that the IM Angel will restart the main -# process. - ---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Main-test: starting... -########################################################################### +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Killing IM-main... +--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 im_daemon_life_cycle -# Wait for IM to start accepting connections. +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Waiting for IM-main to start accepting connections... +--exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 30 im_daemon_life_cycle ---exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 30 +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Main-test: done. ########################################################################### - # # BUG#12751: Instance Manager: client hangs +# - start nonguarded instance (mysqld2); +# - kill IM-main and get it restarted by IM-angel; +# - check that guarded instance (mysqld1) is accepting connections. +# - check that non-guarded instance (mysqld2) were not stopped. # +########################################################################### --echo --echo -------------------------------------------------------------------- --echo -- Test for BUG#12751 --echo -------------------------------------------------------------------- -# Give some time to begin accepting connections after restart. -# FIXME: race condition here. - ---sleep 3 +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle BUG12751: starting... # 1. Start mysqld; +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: starting... START INSTANCE mysqld2; -# FIXME: START INSTANCE should be synchronous. ---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started -# 2. Restart IM-main: kill it and IM-angel will restart it; wait for IM to -# start accepting connections again. +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: waiting to start... +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started im_daemon_life_cycle ---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: started. ---exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 30 +# 2. Restart IM-main; -# 3. Issue some statement -- connection should be re-established. +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Killing IM-main... +--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 im_daemon_life_cycle -# Give some time to begin accepting connections after restart. -# FIXME: race condition here. +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Waiting for IM-main to start accepting connections... +--exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 30 im_daemon_life_cycle + +# 3. Issue some statement -- connection should be re-established. ---sleep 3 +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Checking that IM-main processing commands... --replace_column 3 VERSION SHOW INSTANCE STATUS mysqld1; @@ -67,6 +81,13 @@ SHOW INSTANCE STATUS mysqld1; # So, if it we do not stop it, it will be stopped by mysql-test-run.pl with # warning. +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: stopping... STOP INSTANCE mysqld2; -# FIXME: STOP INSTANCE should be synchronous. ---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped + +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: waiting to stop... +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped im_daemon_life_cycle +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: stopped. + +########################################################################### + +--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle BUG12751: done. diff --git a/mysql-test/t/im_life_cycle.imtest b/mysql-test/t/im_life_cycle.imtest index ddfb62d312e..3721b92e2b7 100644 --- a/mysql-test/t/im_life_cycle.imtest +++ b/mysql-test/t/im_life_cycle.imtest @@ -25,7 +25,7 @@ START INSTANCE mysqld2; # FIXME: START INSTANCE should be synchronous. ---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started im_life_cycle # FIXME: Result of SHOW INSTANCES here is not deterministic unless START # INSTANCE is synchronous. Even waiting for mysqld to start by looking at @@ -58,7 +58,7 @@ SHOW VARIABLES LIKE 'port'; STOP INSTANCE mysqld2; # FIXME: STOP INSTANCE should be synchronous. ---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped im_life_cycle # FIXME: Result of SHOW INSTANCES here is not deterministic unless START # INSTANCE is synchronous. Even waiting for mysqld to start by looking at @@ -121,7 +121,7 @@ STOP INSTANCE mysqld3; --echo -- 1.1.6. --echo -------------------------------------------------------------------- ---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD1_PATH_PID restarted 30 +--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD1_PATH_PID restarted 30 im_life_cycle # Give some time to IM to detect that mysqld was restarted. It should be # longer than monitoring interval. @@ -143,7 +143,7 @@ SHOW INSTANCES; START INSTANCE mysqld2; # FIXME: START INSTANCE should be synchronous. ---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started im_life_cycle # FIXME: Result of SHOW INSTANCES here is not deterministic unless START # INSTANCE is synchronous. Even waiting for mysqld to start by looking at @@ -151,7 +151,7 @@ START INSTANCE mysqld2; # mysqld has started. # SHOW INSTANCES; ---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD2_PATH_PID killed 10 +--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD2_PATH_PID killed 10 im_life_cycle # FIXME: Result of SHOW INSTANCES here is not deterministic unless START # INSTANCE is synchronous. Even waiting for mysqld to start by looking at diff --git a/mysql-test/t/im_utils.imtest b/mysql-test/t/im_utils.imtest index 52878f6c2b5..0866b87204a 100644 --- a/mysql-test/t/im_utils.imtest +++ b/mysql-test/t/im_utils.imtest @@ -31,10 +31,10 @@ SHOW INSTANCE OPTIONS mysqld2; # START INSTANCE mysqld2; ---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started im_utils STOP INSTANCE mysqld2; ---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped im_utils # # Check 'SHOW LOG FILES' command: diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 27007bbe16a..623ccee49e4 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -715,7 +715,7 @@ create temporary table schemata(f1 char(10)); # Bug #10708 SP's can use INFORMATION_SCHEMA as ROUTINE_SCHEMA # delimiter |; ---error 1044 +--error ER_BAD_DB_ERROR CREATE PROCEDURE p1 () BEGIN SELECT 'foo' FROM DUAL; @@ -973,4 +973,18 @@ DROP FUNCTION get_value; + +# +# Bug#22413: EXPLAIN SELECT FROM view with ORDER BY yield server crash +# +create view v1 as +select table_schema as object_schema, + table_name as object_name, + table_type as object_type +from information_schema.tables +order by object_schema; +explain select * from v1; +explain select * from (select table_name from information_schema.tables) as a; +drop view v1; + # End of 5.0 tests. diff --git a/mysql-test/t/information_schema_chmod.test b/mysql-test/t/information_schema_chmod.test index c7ea2b03890..38586ab8b67 100644 --- a/mysql-test/t/information_schema_chmod.test +++ b/mysql-test/t/information_schema_chmod.test @@ -17,7 +17,7 @@ # create database mysqltest; create table mysqltest.t1(a int); ---exec chmod -r $MYSQLTEST_VARDIR/master-data/mysqltest +chmod 0000 $MYSQLTEST_VARDIR/master-data/mysqltest; select table_schema from information_schema.tables where table_schema='mysqltest'; ---exec chmod +r $MYSQLTEST_VARDIR/master-data/mysqltest +exec chmod 0777 $MYSQLTEST_VARDIR/master-data/mysqltest; drop database mysqltest; diff --git a/mysql-test/t/innodb-deadlock.test b/mysql-test/t/innodb-deadlock.test index 41741942963..81acfba5c93 100644 --- a/mysql-test/t/innodb-deadlock.test +++ b/mysql-test/t/innodb-deadlock.test @@ -1,6 +1,4 @@ -- source include/have_innodb.inc -# Can't test this with embedded server --- source include/not_embedded.inc connect (con1,localhost,root,,); connect (con2,localhost,root,,); diff --git a/mysql-test/t/innodb-lock.test b/mysql-test/t/innodb-lock.test index 55a712fef9b..eacf7e562be 100644 --- a/mysql-test/t/innodb-lock.test +++ b/mysql-test/t/innodb-lock.test @@ -1,6 +1,4 @@ -- source include/have_innodb.inc -# Can't test this with embedded server --- source include/not_embedded.inc # # Check and select innodb lock type diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 0c083ccdfd3..4a1efc9e566 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1482,7 +1482,7 @@ INSERT INTO t1 (id) VALUES (NULL); SELECT * FROM t1; DROP TABLE t2, t1; --- Test that foreign keys in temporary tables are not accepted (bug #12084) +# Test that foreign keys in temporary tables are not accepted (bug #12084) CREATE TABLE t1 ( id INT PRIMARY KEY diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 27558a31d68..4a07f495a55 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -362,38 +362,38 @@ insert into t4 values (2, 3); insert into t5 values (11,4); insert into t6 values (2, 3); --- Views with simple natural join. +# 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 +# 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 +# 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 +# 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 +# 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 +# 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 +# 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. +# 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); @@ -402,12 +402,12 @@ select * from (t4 natural right join t3) natural right join (t2 natural right jo 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; +# 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. +# MySQL extension - nested comma ',' operator instead of cross join. 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)); @@ -417,7 +417,7 @@ 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. +# 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) @@ -425,23 +425,23 @@ where b + 1 = y or b + 10 = y group by b,c,a,y having min(b) < max(y) order by a 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. +# 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 +# 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 +# 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 +# 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; @@ -449,11 +449,11 @@ 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 +# 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 +# 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; @@ -464,7 +464,7 @@ select * from (select * from t3 natural join t4) as t34 natural right join (select * from t1 natural join t2) as t12; --- Queries over views +# Queries over views select * from v1a; select * from v1b; select * from v1c; @@ -481,13 +481,13 @@ 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 +# TODO: add tests with correlated subqueries for natural join/join on. +# related to BUG#15269 ----------------------------------------------------------------------- --- Negative tests (tests for errors) ----------------------------------------------------------------------- +#-------------------------------------------------------------------- +# Negative tests (tests for errors) +#-------------------------------------------------------------------- -- error 1052 select * from t1 natural join (t3 cross join t4); -- works in Oracle - bug -- error 1052 @@ -504,7 +504,7 @@ select * from t6 natural join ((t1 natural join t2), (t3 natural join t4)); 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) +# 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 @@ -578,12 +578,12 @@ insert into t3 values (2,3); insert into t4 values (1,3); insert into t5 values (1,4); --- this fails +# this fails prepare stmt1 from "select * from ((t3 natural join (t1 natural join t2)) natural join t4) natural join t5"; execute stmt1; --- this works +# this works select * from ((t3 natural join (t1 natural join t2)) natural join t4) natural join t5; drop table t1, t2, t3, t4, t5; diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index f8ba649b3eb..1e99911a7e3 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -76,11 +76,14 @@ insert into t2 select id from t1; create table t3 (kill_id int); insert into t3 values(connection_id()); +connect (conn2, localhost, root,,); +connection conn2; + +connection conn1; -- disable_result_log send select id from t1 where id in (select distinct id from t2); -- enable_result_log -connect (conn2, localhost, root,,); connection conn2; select ((@id := kill_id) - kill_id) from t3; -- sleep 1 diff --git a/mysql-test/t/kill_n_check.sh b/mysql-test/t/kill_n_check.sh index a54fb6ef8bb..96c402a638c 100755 --- a/mysql-test/t/kill_n_check.sh +++ b/mysql-test/t/kill_n_check.sh @@ -2,74 +2,101 @@ ########################################################################### -# NOTE: this script returns 0 (success) even in case of failure. This is -# because this script is executed under mysql-test-run[.pl] and it's better to -# examine particular problem in log file, than just having said that the test -# case has failed. +# NOTE: this script returns 0 (success) even in case of failure (except for +# usage-error). This is because this script is executed under +# mysql-test-run[.pl] and it's better to examine particular problem in log +# file, than just having said that the test case has failed. + +########################################################################### + +basename=`basename "$0"` +dirname=`dirname "$0"` + +########################################################################### + +. "$dirname/utils.sh" ########################################################################### check_restart() { if [ ! -r "$pid_path" ]; then + log_debug "No '$pid_path' found." user_msg='the process was killed' return 1 fi new_pid=`cat "$pid_path" 2>/dev/null` + err_code=$? - if [ $? -eq 0 -a "$original_pid" = "$new_pid" ]; then + log_debug "err_code: $err_code; original_pid: $original_pid; new_pid: $new_pid." + + if [ $err_code -eq 0 -a "$original_pid" = "$new_pid" ]; then + log_debug "The process was not restarted." user_msg='the process was not restarted' return 1 fi + log_debug "The process was restarted." user_msg='the process was restarted' return 0 } ########################################################################### -if [ $# -ne 3 ]; then - echo "Usage: kill_n_check.sh <pid file path> killed|restarted <timeout>" - exit 0 +if [ $# -ne 4 ]; then + echo "Usage: $basename <pid file path> killed|restarted <timeout> <test id>" + exit 1 fi pid_path="$1" expected_result="$2" total_timeout="$3" +test_id="$4" +log_file="$MYSQLTEST_VARDIR/log/$test_id.log" + +log_debug "-- $basename: starting --" +log_debug "pid_path: '$pid_path'" +log_debug "expected_result: '$expected_result'" +log_debug "total_timeout: '$total_timeout'" +log_debug "test_id: '$test_id'" +log_debug "log_file: '$log_file'" + +########################################################################### if [ "$expected_result" != 'killed' -a \ "$expected_result" != 'restarted' ]; then - echo "Error: invalid second argument ('killed' or 'restarted' expected)." - exit 0 + log_error "Invalid second argument ($expected_result): 'killed' or 'restarted' expected." + quit 0 fi if [ -z "$pid_path" ]; then - echo "Error: invalid PID path ($pid_path)." - exit 0 + log_error "Invalid PID path ($pid_path)." + quit 0 fi if [ ! -r "$pid_path" ]; then - echo "Error: PID file ($pid_path) does not exist." - exit 0 + log_error "PID file ($pid_path) does not exist." + quit 0 fi if [ -z "$total_timeout" ]; then - echo "Error: timeout is not specified." - exit 0 + log_error "Timeout is not specified." + quit 0 fi ########################################################################### original_pid=`cat "$pid_path"` +log_debug "original_pid: $original_pid." -echo "Killing the process..." +log_info "Killing the process..." kill -9 $original_pid ########################################################################### -echo "Sleeping..." +log_info "Waiting..." if [ "$expected_result" = "restarted" ]; then @@ -79,37 +106,42 @@ if [ "$expected_result" = "restarted" ]; then while true; do + log_debug "cur_attempt: $cur_attempt." + if check_restart; then - echo "Success: $user_msg." - exit 0 + log_info "Success: $user_msg." + quit 0 fi [ $cur_attempt -ge $total_timeout ] && break + log_debug "Sleeping for 1 second..." sleep 1 cur_attempt=`expr $cur_attempt + 1` done - echo "Error: $user_msg." - exit 0 + log_error "$user_msg." + quit 0 else # $expected_result == killed # Here we have to sleep for some long time to ensure that the process will # not be restarted. + log_debug "Sleeping for $total_timeout seconds..." sleep $total_timeout new_pid=`cat "$pid_path" 2>/dev/null` + log_debug "new_pid: $new_pid." if [ "$new_pid" -a "$new_pid" -ne "$original_pid" ]; then - echo "Error: the process was restarted." + log_error "The process was restarted." else - echo "Success: the process was killed." + log_info "Success: the process was killed." fi - exit 0 + quit 0 fi diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test index 0c18a65bfd6..bc599b20d36 100644 --- a/mysql-test/t/limit.test +++ b/mysql-test/t/limit.test @@ -7,7 +7,7 @@ drop table if exists t1; --enable_warnings create table t1 (a int not null default 0 primary key, b int not null default 0); -insert into t1 () values (); -- Testing default values +insert into t1 () values (); # Testing default values insert into t1 values (1,1),(2,1),(3,1); update t1 set a=4 where b=1 limit 1; select * from t1; diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 33e268ccb11..d3eeee3b41c 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -1,11 +1,3 @@ -# This test doesn't work with the embedded version as this code -# assumes that one query is running while we are doing queries on -# a second connection. -# This would work if mysqltest run would be threaded and handle each -# connection in a separate thread. -# --- source include/not_embedded.inc - --disable_warnings drop table if exists t1,t2; --enable_warnings diff --git a/mysql-test/t/log.sh b/mysql-test/t/log.sh new file mode 100755 index 00000000000..20b265087cc --- /dev/null +++ b/mysql-test/t/log.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +########################################################################### + +basename=`basename "$0"` +dirname=`dirname "$0"` + +########################################################################### + +. "$dirname/utils.sh" + +########################################################################### + +if [ $# -lt 2 ]; then + echo "Usage: $basename <test id> log message ..." + exit 1 +fi + +test_id="$1" +log_file="$MYSQLTEST_VARDIR/log/$test_id.log" + +shift + +log_debug "$*" diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test index 96437bc7636..31513f1bd06 100644 --- a/mysql-test/t/lowercase_table.test +++ b/mysql-test/t/lowercase_table.test @@ -85,3 +85,23 @@ drop table t1, t2; show tables; # End of 4.1 tests + + +# +# Bug#20404: SHOW CREATE TABLE fails with Turkish I +# +set names utf8; +--disable_warnings +drop table if exists Ä°,Ä°Ä°; +--enable_warnings +create table Ä° (s1 int); +show create table Ä°; +show tables; +drop table Ä°; +create table Ä°Ä° (s1 int); +show create table Ä°Ä°; +show tables; +drop table Ä°Ä°; +set names latin1; + +--echo End of 5.0 tests diff --git a/mysql-test/t/metadata.test b/mysql-test/t/metadata.test index 65338448555..a6ebfdc14c1 100644 --- a/mysql-test/t/metadata.test +++ b/mysql-test/t/metadata.test @@ -61,4 +61,23 @@ drop table t1;// delimiter ;// --disable_info +# +# Bug #20191: getTableName gives wrong or inconsistent result when using VIEWs +# +--enable_metadata +create table t1 (id int(10)); +insert into t1 values (1); +CREATE VIEW v1 AS select t1.id as id from t1; +CREATE VIEW v2 AS select t1.id as renamed from t1; +CREATE VIEW v3 AS select t1.id + 12 as renamed from t1; +select * from v1 group by id limit 1; +select * from v1 group by id limit 0; +select * from v1 where id=1000 group by id; +select * from v1 where id=1 group by id; +select * from v2 where renamed=1 group by renamed; +select * from v3 where renamed=1 group by renamed; +drop table t1; +drop view v1,v2,v3; +--disable_metadata + # End of 4.1 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index d785002abdd..2b498704512 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -846,6 +846,10 @@ DROP TABLE t1; # SET @@myisam_repair_threads=1; SHOW VARIABLES LIKE 'myisam_repair%'; + +--echo End of 4.1 tests + + # Test varchar # @@ -969,39 +973,5 @@ create table t3 (c1 int) engine=myisam pack_keys=default; --error 1064 create table t4 (c1 int) engine=myisam pack_keys=2; drop table t1, t2, t3; -# -# Bug#8706 - temporary table with data directory option fails -# -connect (session1,localhost,root,,); -connect (session2,localhost,root,,); - -connection session1; -disable_query_log; -eval create temporary table t1 (a int) engine=myisam data directory="$MYSQLTEST_VARDIR/tmp" select 9 a; -enable_query_log; -disable_result_log; -show create table t1; -enable_result_log; - -connection session2; -disable_query_log; -eval create temporary table t1 (a int) engine=myisam data directory="$MYSQLTEST_VARDIR/tmp" select 99 a; -enable_query_log; -disable_result_log; -show create table t1; -enable_result_log; - -connection default; -create table t1 (a int) engine=myisam select 42 a; - -connection session1; -select * from t1; -disconnect session1; -connection session2; -select * from t1; -disconnect session2; -connection default; -select * from t1; -drop table t1; -# End of 4.1 tests +--echo End of 5.0 tests diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index c06e52e2d78..3d022eb27e4 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -143,6 +143,24 @@ drop table t1; --exec diff $MYSQLTEST_VARDIR/tmp/bug20328_1.result $MYSQLTEST_VARDIR/tmp/bug20328_2.result # +# Bug #19216: Client crashes on long SELECT +# +--exec echo "select" > $MYSQLTEST_VARDIR/tmp/b19216.tmp +# 3400 * 20 makes 68000 columns that is more than the max number that can fit +# in a 16 bit number. +let $i= 3400; +while ($i) +{ + --exec echo "'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'," >> $MYSQLTEST_VARDIR/tmp/b19216.tmp + dec $i; +} + +--exec echo "'b';" >> $MYSQLTEST_VARDIR/tmp/b19216.tmp +--disable_query_log +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/b19216.tmp >/dev/null +--enable_query_log + +# # Bug #20103: Escaping with backslash does not work # --exec echo "SET SQL_MODE = 'NO_BACKSLASH_ESCAPES';" > $MYSQLTEST_VARDIR/tmp/bug20103.sql @@ -223,4 +241,22 @@ drop table t17583; --error 1 --exec $MYSQL test -e "\r test cyrils_superlonghostnameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 2>&1 +# +# Bug #21412: mysql cmdline client allows backslash(es) +# as delimiter but can't recognize them +# + +# This should work just fine... +--exec echo "DELIMITER /" > $MYSQLTEST_VARDIR/tmp/bug21412.sql +--exec echo "SELECT 1/" >> $MYSQLTEST_VARDIR/tmp/bug21412.sql +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug21412.sql 2>&1 + +# This should give an error... +--exec echo "DELIMITER \\" > $MYSQLTEST_VARDIR/tmp/bug21412.sql +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug21412.sql 2>&1 + +# As should this... +--exec echo "DELIMITER \\\\" > $MYSQLTEST_VARDIR/tmp/bug21412.sql +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug21412.sql 2>&1 + --echo End of 5.0 tests diff --git a/mysql-test/t/mysqladmin.test b/mysql-test/t/mysqladmin.test new file mode 100644 index 00000000000..850abc1ee69 --- /dev/null +++ b/mysql-test/t/mysqladmin.test @@ -0,0 +1,32 @@ +# +# Test "mysqladmin ping" +# + +--exec $MYSQLADMIN --no-defaults -S $MASTER_MYSOCK -P $MASTER_MYPORT -u root --password= ping 2>&1 + + +# +# Bug#10608 mysqladmin breaks on "database" variable in my.cnf +# + +# When mysqladmin finds database in .cnf file it shall fail +--write_file $MYSQLTEST_VARDIR/tmp/bug10608.cnf +[client] +database=db1 +EOF + +--replace_regex /.*mysqladmin.*: unknown/mysqladmin: unknown/ +--error 7 +--exec $MYSQLADMIN --defaults-file=$MYSQLTEST_VARDIR/tmp/bug10608.cnf -S $MASTER_MYSOCK -P $MASTER_MYPORT -u root --password= ping 2>&1 + + +# When mysqladmin finds "loose-database" in .cnf file it shall print +# a warning and continue +--write_file $MYSQLTEST_VARDIR/tmp/bug10608.cnf +[client] +loose-database=db2 +EOF + +--replace_regex /Warning: .*mysqladmin.*: unknown/Warning: mysqladmin: unknown/ +--exec $MYSQLADMIN --defaults-file=$MYSQLTEST_VARDIR/tmp/bug10608.cnf -S $MASTER_MYSOCK -P $MASTER_MYPORT -u root --password= ping 2>&1 + diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 3c20b38722f..7da84543e6d 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -1,6 +1,9 @@ # This test should work in embedded server after mysqltest is fixed -- source include/not_embedded.inc +# This test uses chmod, can't be run with root permissions +-- source include/not_as_root.inc + # ============================================================================ # # Test of mysqltest itself @@ -1522,6 +1525,46 @@ remove_file $MYSQLTEST_VARDIR/tmp/file2.tmp; --exec echo "copy_file from_file;" | $MYSQL_TEST 2>&1 # ---------------------------------------------------------------------------- +# test for chmod +# ---------------------------------------------------------------------------- +--write_file $MYSQLTEST_VARDIR/tmp/file1.tmp +file1 +EOF + +chmod 0000 $MYSQLTEST_VARDIR/tmp/file1.tmp; +# The below write fails, but --error is not implemented +# for write_file +#--write_file $MYSQLTEST_VARDIR/tmp/file1.tmp +#test should fail +#EOF + +chmod 0777 $MYSQLTEST_VARDIR/tmp/file1.tmp; +--write_file $MYSQLTEST_VARDIR/tmp/file1.tmp +test2 +EOF + +remove_file $MYSQLTEST_VARDIR/tmp/file1.tmp; + +--error 1 +--exec echo "chmod ;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "chmod 0 from_file;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "chmod 08 from_file;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "chmod from_file;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "chmod ABZD from_file;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "chmod 06789 from_file;" | $MYSQL_TEST 2>&1 + + +# ---------------------------------------------------------------------------- # test for perl # ---------------------------------------------------------------------------- --perl diff --git a/mysql-test/t/ndb_index_unique.test b/mysql-test/t/ndb_index_unique.test index 8561b3794c4..e210491c9d0 100644 --- a/mysql-test/t/ndb_index_unique.test +++ b/mysql-test/t/ndb_index_unique.test @@ -85,7 +85,6 @@ select * from t2 order by a; drop table t2; --- error 1121 CREATE TABLE t2 ( a int unsigned NOT NULL PRIMARY KEY, b int unsigned not null, @@ -93,6 +92,20 @@ CREATE TABLE t2 ( UNIQUE USING HASH (b, c) ) engine=ndbcluster; + +insert t2 values(1,1,NULL),(2,2,2),(3,3,NULL),(4,4,4),(5,5,NULL),(6,6,6),(7,7,NULL),(8,3,NULL),(9,3,NULL); + +select * from t2 where c IS NULL order by a; +select * from t2 where b = 3 AND c IS NULL order by a; +select * from t2 where (b = 3 OR b = 5) AND c IS NULL order by a; +set @old_ecpd = @@session.engine_condition_pushdown; +set engine_condition_pushdown = true; +explain select * from t2 where (b = 3 OR b = 5) AND c IS NULL AND a < 9 order by a; +select * from t2 where (b = 3 OR b = 5) AND c IS NULL AND a < 9 order by a; +set engine_condition_pushdown = @old_ecpd; + +drop table t2; + # # Show use of PRIMARY KEY USING HASH indexes # diff --git a/mysql-test/t/ndb_update.test b/mysql-test/t/ndb_update.test index 45e3add4639..ebcc6995d74 100644 --- a/mysql-test/t/ndb_update.test +++ b/mysql-test/t/ndb_update.test @@ -23,8 +23,13 @@ UPDATE t1 set b = c; select * from t1 order by pk1; UPDATE t1 set pk1 = 4 where pk1 = 1; select * from t1 order by pk1; +--error 1062 +UPDATE t1 set pk1 = 4 where pk1 = 2; +UPDATE IGNORE t1 set pk1 = 4 where pk1 = 2; +select * from t1 order by pk1; -- error 1062 UPDATE t1 set pk1 = 1, c = 2 where pk1 = 4; +UPDATE IGNORE t1 set pk1 = 1, c = 2 where pk1 = 4; select * from t1 order by pk1; UPDATE t1 set pk1 = pk1 + 10; select * from t1 order by pk1; diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test index 4aec745f3f7..65e09b006ec 100644 --- a/mysql-test/t/null.test +++ b/mysql-test/t/null.test @@ -177,7 +177,7 @@ drop table t1; # non-null string collation, i.e. case insensitively, # rather than according to NULL's collation, i.e. case sensitively # --- in field +# in field select case 'str' when 'STR' then 'str' when null then 'null' end as c01, case 'str' when null then 'null' when 'STR' then 'str' end as c02, diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 1104c859ab8..d7cf0e2a375 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -514,11 +514,6 @@ set max_sort_length=20; select a from t1 order by a; drop table t1; -create table t1 (a int not null, b int not null, c int not null); -insert t1 values (1,1,1),(1,1,2),(1,2,1); -select a, b from t1 group by a, b order by sum(c); -drop table t1; - # # Bug #7331 # @@ -577,7 +572,27 @@ INSERT INTO t1 VALUES (1,30), (2,20), (1,10), (2,30), (1,20), (2,10); DROP TABLE t1; +# +# Bug #22457: Column alias in ORDER BY works, but not if in an expression +# + +CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2); +SELECT a + 1 AS num FROM t1 ORDER BY 30 - num; +SELECT CONCAT('test', a) AS str FROM t1 ORDER BY UPPER(str); +SELECT a + 1 AS num FROM t1 GROUP BY 30 - num; +SELECT a + 1 AS num FROM t1 HAVING 30 - num; +--error 1054 +SELECT a + 1 AS num, num + 1 FROM t1; +SELECT a + 1 AS num, (select num + 2 FROM t1 LIMIT 1) FROM t1; +--error 1054 +SELECT a.a + 1 AS num FROM t1 a JOIN t1 b ON num = b.a; +DROP TABLE t1; + # End of 4.1 tests +create table t1 (a int not null, b int not null, c int not null); +insert t1 values (1,1,1),(1,1,2),(1,2,1); +select a, b from t1 group by a, b order by sum(c); +drop table t1; # # Bug#21302: Result not properly sorted when using an ORDER BY on a second diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 8d01277b515..547f9a766d1 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -848,6 +848,9 @@ drop table t1; # Bug#16365 Prepared Statements: DoS with too many open statements # Check that the limit @@max_prpeared_stmt_count works. # +# This is also the test for bug#23159 prepared_stmt_count should be +# status variable. +# # Save the old value set @old_max_prepared_stmt_count= @@max_prepared_stmt_count; # @@ -857,17 +860,17 @@ set @old_max_prepared_stmt_count= @@max_prepared_stmt_count; # --disable_ps_protocol # -# A. Check that the new variables are present in SHOW VARIABLES list. +# A. Check that the new variables are present in SHOW VARIABLES and +# SHOW STATUS lists. # show variables like 'max_prepared_stmt_count'; -show variables like 'prepared_stmt_count'; +show status like 'prepared_stmt_count'; # -# B. Check that the new variables are selectable. +# B. Check that the new system variable is selectable. # -select @@max_prepared_stmt_count, @@prepared_stmt_count; +select @@max_prepared_stmt_count; # -# C. Check that max_prepared_stmt_count is settable (global only), -# whereas prepared_stmt_count is readonly. +# C. Check that max_prepared_stmt_count is settable (global only). # set global max_prepared_stmt_count=-1; select @@max_prepared_stmt_count; @@ -881,12 +884,6 @@ set @@max_prepared_stmt_count=1; set max_prepared_stmt_count=1; --error ER_GLOBAL_VARIABLE set local max_prepared_stmt_count=1; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set local prepared_stmt_count=0; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set @@prepared_stmt_count=0; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set global prepared_stmt_count=1; # set to a reasonable limit works set global max_prepared_stmt_count=1; select @@max_prepared_stmt_count; @@ -894,47 +891,50 @@ select @@max_prepared_stmt_count; # D. Check that the variables actually work. # set global max_prepared_stmt_count=0; -select @@max_prepared_stmt_count, @@prepared_stmt_count; +select @@max_prepared_stmt_count; +show status like 'prepared_stmt_count'; --error ER_MAX_PREPARED_STMT_COUNT_REACHED prepare stmt from "select 1"; -select @@prepared_stmt_count; +show status like 'prepared_stmt_count'; set global max_prepared_stmt_count=1; prepare stmt from "select 1"; -select @@prepared_stmt_count; +show status like 'prepared_stmt_count'; --error ER_MAX_PREPARED_STMT_COUNT_REACHED prepare stmt1 from "select 1"; -select @@prepared_stmt_count; +show status like 'prepared_stmt_count'; deallocate prepare stmt; -select @@prepared_stmt_count; +show status like 'prepared_stmt_count'; # # E. Check that we can prepare a statement with the same name # successfully, without hitting the limit. # prepare stmt from "select 1"; -select @@prepared_stmt_count; +show status like 'prepared_stmt_count'; prepare stmt from "select 2"; -select @@prepared_stmt_count; +show status like 'prepared_stmt_count'; # # F. We can set the max below the current count. In this case no new # statements should be allowed to prepare. # -select @@prepared_stmt_count, @@max_prepared_stmt_count; +show status like 'prepared_stmt_count'; +select @@max_prepared_stmt_count; set global max_prepared_stmt_count=0; --error ER_MAX_PREPARED_STMT_COUNT_REACHED prepare stmt from "select 1"; # Result: the old statement is deallocated, the new is not created. ---error 1243 # ER_UNKNOWN_STMT_HANDLER +--error ER_UNKNOWN_STMT_HANDLER execute stmt; -select @@prepared_stmt_count; +show status like 'prepared_stmt_count'; --error ER_MAX_PREPARED_STMT_COUNT_REACHED prepare stmt from "select 1"; -select @@prepared_stmt_count; +show status like 'prepared_stmt_count'; # # G. Show that the variables are up to date even after a connection with all # statements in it was terminated. # set global max_prepared_stmt_count=3; -select @@max_prepared_stmt_count, @@prepared_stmt_count; +select @@max_prepared_stmt_count; +show status like 'prepared_stmt_count'; prepare stmt from "select 1"; connect (con1,localhost,root,,); connection con1; @@ -943,26 +943,20 @@ prepare stmt1 from "select 3"; --error ER_MAX_PREPARED_STMT_COUNT_REACHED prepare stmt2 from "select 4"; connection default; ---error ER_MAX_PREPARED_STMT_COUNT_REACHED +--error ER_MAX_PREPARED_STMT_COUNT_REACHED prepare stmt2 from "select 4"; -select @@max_prepared_stmt_count, @@prepared_stmt_count; +select @@max_prepared_stmt_count; +show status like 'prepared_stmt_count'; disconnect con1; connection default; -# Wait for the connection to die: deal with a possible race deallocate prepare stmt; -let $count= `select @@prepared_stmt_count`; -if ($count) -{ ---sleep 2 - let $count= `select @@prepared_stmt_count`; -} -select @@max_prepared_stmt_count, @@prepared_stmt_count; # # Restore the old value. # set global max_prepared_stmt_count= @old_max_prepared_stmt_count; --enable_ps_protocol + # # Bug#19399 "Stored Procedures 'Lost Connection' when dropping/creating # tables" @@ -1514,6 +1508,29 @@ DROP TABLE t1, t2; # +# BUG#20327: Marking of a wrong field leads to a wrong result on select with +# view, prepared statement and subquery. +# +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT * FROM t1; + +INSERT INTO t1 VALUES (1), (2); + +let $query = SELECT t1.i FROM t1 JOIN v1 ON t1.i = v1.i + WHERE EXISTS (SELECT * FROM t1 WHERE v1.i = 1); +eval $query; +eval PREPARE stmt FROM "$query"; +# Statement execution should return '1'. +EXECUTE stmt; +# Check re-execution. +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; +DROP VIEW v1; +DROP TABLE t1; + + +# # BUG#21856: Prepared Statments: crash if bad create # --disable_warnings diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index d86f1a464b1..f6e480282ff 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -870,3 +870,32 @@ select * from t1 where a > 3; show status like 'last_query_cost'; drop table t1; SET GLOBAL query_cache_size=0; + +# +# Bug #20045: Server crash on INSERT ... SELECT ... FROM non-mergeable view +# +set global query_cache_size=1024*1024; +flush status; +create table t1 (a int); +insert into t1 (a) values (1), (2), (3); +select * from t1; +show status like 'Qcache_hits'; +select * from t1; +show status like 'Qcache_hits'; +create table t2 like t1; +select * from t1; +show status like 'Qcache_hits'; +insert into t2 select * from t1; +select * from t1; +show status like 'Qcache_hits'; +drop table t1, t2; + +create table t1(c1 int); +create table t2(c1 int); +create table t3(c1 int); +create view v1 as select t3.c1 as c1 from t3,t2 where t3.c1 = t2.c1; +start transaction; +insert into t1(c1) select c1 from v1; +drop table t1, t2, t3; +drop view v1; +set global query_cache_size=0; diff --git a/mysql-test/t/read_only.test b/mysql-test/t/read_only.test index 175a5bba6fa..8e14b310f4c 100644 --- a/mysql-test/t/read_only.test +++ b/mysql-test/t/read_only.test @@ -101,6 +101,18 @@ drop table t1; --error 1290 insert into t1 values(1); +# +# BUG #22077 "DROP TEMPORARY TABLE fails with wrong error if read_only is set" +# +# check if DROP TEMPORARY on a non-existing temporary table returns the right +# error + +--error ER_BAD_TABLE_ERROR +drop temporary table ttt; + +# check if DROP TEMPORARY TABLE IF EXISTS produces a warning with read_only set +drop temporary table if exists ttt; + connection default; drop table t1,t2; drop user test@localhost; diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test index 09a02344203..fce37d8466d 100644 --- a/mysql-test/t/rename.test +++ b/mysql-test/t/rename.test @@ -2,10 +2,6 @@ # Test of rename table # -# Test requires concurrent connections, which can't be tested on embedded -# server --- source include/not_embedded.inc - --disable_warnings drop table if exists t0,t1,t2,t3,t4; # Clear up from other tests (to ensure that SHOW TABLES below is right) diff --git a/mysql-test/t/rpl000015.test b/mysql-test/t/rpl000015.test index df4bf6f977b..d61b7120fa1 100644 --- a/mysql-test/t/rpl000015.test +++ b/mysql-test/t/rpl000015.test @@ -12,7 +12,7 @@ show slave status; change master to master_host='127.0.0.1'; # The following needs to be cleaned up when change master is fixed ---replace_result $MYSQL_TCP_PORT MASTER_PORT +--replace_result $DEFAULT_MASTER_PORT DEFAULT_MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # show slave status; --replace_result $MASTER_MYPORT MASTER_PORT diff --git a/mysql-test/t/rpl_deadlock.test b/mysql-test/t/rpl_deadlock.test index 1a48e4d417c..db2a7ec3a8d 100644 --- a/mysql-test/t/rpl_deadlock.test +++ b/mysql-test/t/rpl_deadlock.test @@ -16,7 +16,8 @@ source include/master-slave.inc; connection master; create table t1 (a int not null, key(a)) engine=innodb; create table t2 (a int not null, key(a)) engine=innodb; -create table t3 (a int) engine=innodb; +# requiring 'unique' for the timeout part of the test +create table t3 (a int unique) engine=innodb; create table t4 (a int) engine=innodb; show variables like 'slave_transaction_retries'; sync_slave_with_master; @@ -31,8 +32,7 @@ stop slave; connection master; begin; # Let's keep BEGIN and the locked statement in two different relay logs. -let $1=200; -disable_query_log; +let $1=200;disable_query_log; while ($1) { eval insert into t3 values( $1 ); @@ -59,7 +59,7 @@ enable_query_log; select * from t1 for update; start slave; --real_sleep 3 # hope that slave is blocked now -insert into t2 values(22); # provoke deadlock, slave should be victim +insert into t2 values(201); # provoke deadlock, slave should be victim commit; sync_with_master; select * from t1; # check that slave succeeded finally @@ -74,11 +74,13 @@ show slave status; # 2) Test lock wait timeout stop slave; -change master to master_log_pos=532; # the BEGIN log event +delete from t3; +change master to master_log_pos=539; # the BEGIN log event begin; select * from t2 for update; # hold lock start slave; --real_sleep 10 # slave should have blocked, and be retrying +select count(*) from t3 /* must be zero */; # replaying begins after rollback commit; sync_with_master; select * from t1; # check that slave succeeded finally @@ -97,11 +99,13 @@ set global max_relay_log_size=0; # This is really copy-paste of 2) of above stop slave; -change master to master_log_pos=532; +delete from t3; +change master to master_log_pos=539; begin; select * from t2 for update; start slave; --real_sleep 10 +select count(*) from t3 /* must be zero */; # replaying begins after rollback commit; sync_with_master; select * from t1; diff --git a/mysql-test/t/rpl_ignore_table-slave.opt b/mysql-test/t/rpl_ignore_table-slave.opt index cb49119bfcb..3aabbb2e0f5 100644 --- a/mysql-test/t/rpl_ignore_table-slave.opt +++ b/mysql-test/t/rpl_ignore_table-slave.opt @@ -1 +1 @@ ---replicate-ignore-table=test.t1 --replicate-ignore-table=test.t2 --replicate-ignore-table=test.t3 +--replicate-ignore-table=test.t1 --replicate-ignore-table=test.t2 --replicate-ignore-table=test.t3 --replicate-wild-ignore-table=%.tmptbl% diff --git a/mysql-test/t/rpl_ignore_table.test b/mysql-test/t/rpl_ignore_table.test index bc651779208..b875075f71c 100644 --- a/mysql-test/t/rpl_ignore_table.test +++ b/mysql-test/t/rpl_ignore_table.test @@ -26,3 +26,26 @@ SELECT * FROM t4; connection master; DROP TABLE t1; DROP TABLE t4; + + +# +# bug#22877 replication character sets get out of sync +# using replicate-wild-ignore-table +# +--disable_warnings +DROP TABLE IF EXISTS t5; +--enable_warnings +CREATE TABLE t5 ( + word varchar(50) collate utf8_unicode_ci NOT NULL default '' +) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +SET @@session.character_set_client=33,@@session.collation_connection=192; +CREATE TEMPORARY TABLE tmptbl504451f4258$1 (id INT NOT NULL) ENGINE=MEMORY; +INSERT INTO t5 (word) VALUES ('TEST’'); +SELECT HEX(word) FROM t5; +sync_slave_with_master; +connection slave; +SELECT HEX(word) FROM t5; +--error 1146 +SELECT * FROM tmptbl504451f4258$1; +connection master; +DROP TABLE t5; diff --git a/mysql-test/t/rpl_packet-master.opt b/mysql-test/t/rpl_packet-master.opt new file mode 100644 index 00000000000..42d4f94c999 --- /dev/null +++ b/mysql-test/t/rpl_packet-master.opt @@ -0,0 +1 @@ +-O max_allowed_packet=1024 -O net_buffer_length=1024 diff --git a/mysql-test/t/rpl_packet-slave.opt b/mysql-test/t/rpl_packet-slave.opt new file mode 100644 index 00000000000..42d4f94c999 --- /dev/null +++ b/mysql-test/t/rpl_packet-slave.opt @@ -0,0 +1 @@ +-O max_allowed_packet=1024 -O net_buffer_length=1024 diff --git a/mysql-test/t/rpl_packet.test b/mysql-test/t/rpl_packet.test new file mode 100644 index 00000000000..d01979a4731 --- /dev/null +++ b/mysql-test/t/rpl_packet.test @@ -0,0 +1,39 @@ +# +# Check replication protocol packet size handling +# Bug#19402 SQL close to the size of the max_allowed_packet fails on slave +# + +# max-out size db name +source include/master-slave.inc; + +let $db= DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; +disable_warnings; +eval drop database if exists $db; +enable_warnings; +eval create database $db; + +connection master; +select @@net_buffer_length, @@max_allowed_packet; +disconnect master; + +# alas, can't use eval here; if db name changed apply the change here +connect (master,localhost,root,,DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________); + +connection master; +create table `t1` (`f1` LONGTEXT) ENGINE=MyISAM; + +INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1023'); +save_master_pos; + +connection slave; +sync_with_master; +eval select count(*) from `$db`.`t1` /* must be 1 */; + +connection master; +eval drop database $db; +save_master_pos; + +connection slave; +sync_with_master; + +# End of tests diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index ee49f92910a..39a810aa021 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -17,8 +17,10 @@ connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); drop table if exists t1, t2, t3, t4; --enable_warnings connect (slave,localhost,root,,test,$SLAVE_MYPORT,slave.sock); -system cat /dev/null > $MYSQLTEST_VARDIR/slave-data/master.info; -system chmod 000 $MYSQLTEST_VARDIR/slave-data/master.info; +# Create empty file +write_file $MYSQLTEST_VARDIR/slave-data/master.info; +EOF +chmod 0000 $MYSQLTEST_VARDIR/slave-data/master.info; connection slave; --disable_warnings drop table if exists t1, t2, t3, t4; @@ -29,7 +31,7 @@ drop table if exists t1, t2, t3, t4; --replace_result $MYSQL_TEST_DIR TESTDIR --error 1105,1105,29 start slave; -system chmod 600 $MYSQLTEST_VARDIR/slave-data/master.info; +chmod 0600 $MYSQLTEST_VARDIR/slave-data/master.info; # It will fail again because the file is empty so the slave cannot get valuable # info about how to connect to the master from it (failure in # init_strvar_from_file() in init_master_info()). diff --git a/mysql-test/t/rpl_sp.test b/mysql-test/t/rpl_sp.test index b2a34a63735..373b895a7c1 100644 --- a/mysql-test/t/rpl_sp.test +++ b/mysql-test/t/rpl_sp.test @@ -524,4 +524,26 @@ sync_slave_with_master; set global log_bin_trust_function_creators=0; connection master; set global log_bin_trust_function_creators=0; +# +# Bug22043: MySQL don't add "USE <DATABASE>" before "DROP PROCEDURE IF EXISTS" +# +connection master; +reset master; +--disable_warnings +drop database if exists mysqltest; +drop database if exists mysqltest2; +--enable_warnings +create database mysqltest; +create database mysqltest2; +use mysqltest2; +create table t ( t integer ); +create procedure mysqltest.test() begin end; +insert into t values ( 1 ); +show binlog events in 'master-bin.000001' from 98; +--error ER_WRONG_DB_NAME +create procedure `\\`.test() begin end; +# Clean up +drop database mysqltest; +drop database mysqltest2; + diff --git a/mysql-test/t/rpl_trigger.test b/mysql-test/t/rpl_trigger.test index d6e9410b1d3..faba89e7a73 100644 --- a/mysql-test/t/rpl_trigger.test +++ b/mysql-test/t/rpl_trigger.test @@ -423,6 +423,43 @@ DROP TABLE t2; --sync_with_master --connection master +# +# BUG#23703: DROP TRIGGER needs an IF EXISTS +# + +connection master; + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1(a int, b varchar(50)); + +-- error ER_TRG_DOES_NOT_EXIST +drop trigger not_a_trigger; + +drop trigger if exists not_a_trigger; + +create trigger t1_bi before insert on t1 +for each row set NEW.b := "In trigger t1_bi"; + +insert into t1 values (1, "a"); +drop trigger if exists t1_bi; +insert into t1 values (2, "b"); +drop trigger if exists t1_bi; +insert into t1 values (3, "c"); + +select * from t1; + +save_master_pos; +connection slave; +sync_with_master; + +select * from t1; + +connection master; + +drop table t1; # # End of tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 0f096d97d25..0c82cef867f 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2700,7 +2700,7 @@ insert into t2 values ('58013'),('58014'),('58015'),('58016'); create table t3 (a_id int(11) not null, b_id char(16) character set utf8); insert into t3 values (123,null),(123,null),(123,null),(123,null),(123,null),(123,'58013'); --- both queries are equivalent +# both queries are equivalent select count(*) from t1 inner join (t3 left join t2 on t2.id = t3.b_id) on t1.id = t3.a_id; @@ -2940,7 +2940,7 @@ create table t2 ( insert into t1 (b,c) values (0,1), (0,1); insert into t2 (b,c) values (0,1); --- Row 1 should succeed. Row 2 should fail. Both fail. +# Row 1 should succeed. Row 2 should fail. Both fail. select t1.a, t1.b + 0, t1.c + 0, t2.a, t2.b + 0, t2.c, t2.d from t1 left outer join t2 on t1.a = t2.c and t2.b <> 1 where t1.b <> 1 order by t1.a; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 849be577893..369ae9bff65 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -1,5 +1,4 @@ -# Requires use of multiple simultaneous connections, not supported with -# embedded server testing +# Uses GRANT commands that usually disabled in embedded server -- source include/not_embedded.inc # diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test index b94de6236d3..cc3e3b93e06 100644 --- a/mysql-test/t/sp-prelocking.test +++ b/mysql-test/t/sp-prelocking.test @@ -209,7 +209,7 @@ select f3() // call sp1() // ---------------- +# --------------- drop procedure sp1// drop function f3// diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index 1a71425d2a7..9d5adf57f81 100644 --- a/mysql-test/t/status.test +++ b/mysql-test/t/status.test @@ -1,10 +1,3 @@ -# This test doesn't work with the embedded version as this code -# assumes that one query is running while we are doing queries on -# a second connection. -# This would work if mysqltest run would be threaded and handle each -# connection in a separate thread. -# ---source include/not_embedded.inc # PS causes different statistics --disable_ps_protocol diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test index 6ebbb53ed8e..224a7422de1 100644 --- a/mysql-test/t/strict.test +++ b/mysql-test/t/strict.test @@ -327,14 +327,14 @@ INSERT INTO t1 (col2) VALUES(CAST('0000-00-00' AS DATETIME)); # SQLSTATE 22007 <invalid datetime value> --error 1292 INSERT INTO t1 (col3) VALUES(CAST('0000-10-31 15:30' AS DATETIME)); --- should return OK --- We accept this to be a failure +# should return OK +# We accept this to be a failure --error 1292 INSERT INTO t1 (col3) VALUES(CAST('2004-10-0 15:30' AS DATETIME)); --error 1292 INSERT INTO t1 (col3) VALUES(CAST('2004-0-10 15:30' AS DATETIME)); --- should return SQLSTATE 22007 <invalid datetime value> +# should return SQLSTATE 22007 <invalid datetime value> # deactivated because of Bug#8294 # Bug#8294 Traditional: Misleading error message for invalid CAST to DATE @@ -422,8 +422,8 @@ INSERT INTO t1 (col2) VALUES(CONVERT('0000-00-00',DATETIME)); # SQLSTATE 22007 <invalid datetime value> --error 1292 INSERT INTO t1 (col3) VALUES(CONVERT('0000-10-31 15:30',DATETIME)); --- should return OK --- We accept this to be a failure +# should return OK +# We accept this to be a failure --error 1292 INSERT INTO t1 (col3) VALUES(CONVERT('2004-10-0 15:30',DATETIME)); @@ -729,11 +729,11 @@ DROP TABLE t1; CREATE TABLE t1 (col1 NUMERIC(4,2)); INSERT INTO t1 VALUES (10.55),(10.5555),(0),(-10.55),(-10.5555),(11),(1e+01); --- Note that the +/-10.5555 is inserted as +/-10.55, not +/-10.56 ! +# Note that the +/-10.5555 is inserted as +/-10.55, not +/-10.56 ! INSERT INTO t1 VALUES ('10.55'),('10.5555'),('-10.55'),('-10.5555'),('11'),('1e+01'); --- The 2 following inserts should generate a warning, but doesn't yet --- because NUMERIC works like DECIMAL +# The 2 following inserts should generate a warning, but doesn't yet +# because NUMERIC works like DECIMAL --error 1264 INSERT INTO t1 VALUES (101.55); --error 1264 @@ -744,8 +744,8 @@ INSERT INTO t1 VALUES (-101.55); INSERT INTO t1 VALUES (1010.55); --error 1264 INSERT INTO t1 VALUES (1010); --- The 2 following inserts should generate a warning, but doesn't yet --- because NUMERIC works like DECIMAL +# The 2 following inserts should generate a warning, but doesn't yet +# because NUMERIC works like DECIMAL --error 1264 INSERT INTO t1 VALUES ('101.55'); --error 1264 diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index dee5b1e4fb0..0bbbc5a793e 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -108,7 +108,7 @@ select * from t3 where a in (select a,b from t2); -- error 1241 select * from t3 where a in (select * from t2); insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9),(1,10); --- empty set +# empty set select b,max(a) as ma from t4 group by b having b < (select max(t2.a) from t2 where t2.b=t4.b); insert into t2 values (2,10); select b,max(a) as ma from t4 group by b having ma < (select max(t2.a) from t2 where t2.b=t4.b); @@ -1955,6 +1955,39 @@ SELECT field1, field2 DROP TABLE t1, t2; +# +# Bug #23478: not top-level IN subquery returning a non-empty result set +# with possible NULL values by index access from the outer query +# + +CREATE TABLE t1(a int, INDEX (a)); +INSERT INTO t1 VALUES (1), (3), (5), (7); +INSERT INTO t1 VALUES (NULL); + +CREATE TABLE t2(a int); +INSERT INTO t2 VALUES (1),(2),(3); + +EXPLAIN SELECT a, a IN (SELECT a FROM t1) FROM t2; +SELECT a, a IN (SELECT a FROM t1) FROM t2; + +DROP TABLE t1,t2; + +# +# Bug #11302: getObject() returns a String for a sub-query of type datetime +# +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('1998-09-23'), ('2003-03-25'); + +CREATE TABLE t2 AS SELECT + (SELECT a FROM t1 WHERE a < '2000-01-01') AS sub_a + FROM t1 WHERE a > '2000-01-01'; +SHOW CREATE TABLE t2; + +CREATE TABLE t3 AS (SELECT a FROM t1 WHERE a < '2000-01-01') UNION (SELECT a FROM t1 WHERE a > '2000-01-01'); +SHOW CREATE TABLE t3; + +DROP TABLE t1,t2,t3; + # End of 4.1 tests # @@ -2247,11 +2280,11 @@ drop table t1; # Bug#19700: subselect returning BIGINT always returned it as SIGNED # CREATE TABLE t1 (i BIGINT UNSIGNED); -INSERT INTO t1 VALUES (10000000000000000000); -- > MAX SIGNED BIGINT 9323372036854775807 +INSERT INTO t1 VALUES (10000000000000000000); # > MAX SIGNED BIGINT 9323372036854775807 INSERT INTO t1 VALUES (1); CREATE TABLE t2 (i BIGINT UNSIGNED); -INSERT INTO t2 VALUES (10000000000000000000); -- same as first table +INSERT INTO t2 VALUES (10000000000000000000); # same as first table INSERT INTO t2 VALUES (1); /* simple test */ @@ -2426,3 +2459,40 @@ SELECT ( FROM t1 t2 GROUP BY t2.a; DROP TABLE t1,t2; + +# +# Bug #21727: Correlated subquery that requires filesort: +# slow with big sort_buffer_size +# + +CREATE TABLE t1 (a int, b int auto_increment, PRIMARY KEY (b)); +CREATE TABLE t2 (x int auto_increment, y int, z int, + PRIMARY KEY (x), FOREIGN KEY (y) REFERENCES t1 (b)); + +disable_query_log; +let $1=3000; +while ($1) +{ + eval INSERT INTO t1(a) VALUES(RAND()*1000); + eval SELECT MAX(b) FROM t1 INTO @id; + let $2=10; + while ($2) + { + eval INSERT INTO t2(y,z) VALUES(@id,RAND()*1000); + dec $2; + } + dec $1; +} +enable_query_log; + +SET SESSION sort_buffer_size = 32 * 1024; +SELECT SQL_NO_CACHE COUNT(*) + FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c + FROM t1) t; + +SET SESSION sort_buffer_size = 8 * 1024 * 1024; +SELECT SQL_NO_CACHE COUNT(*) + FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c + FROM t1) t; + +DROP TABLE t1,t2; diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test new file mode 100644 index 00000000000..f7fbafdd17f --- /dev/null +++ b/mysql-test/t/subselect3.test @@ -0,0 +1,137 @@ +--disable_warnings +drop table if exists t0, t1, t2, t3, t4; +--enable_warnings + +# +# 1. Subquery with GROUP/HAVING +# +create table t1 (oref int, grp int, ie int) ; +insert into t1 (oref, grp, ie) values + (1, 1, 1), + (1, 1, 1), + (1, 2, NULL), + + (2, 1, 3), + + (3, 1, 4), + (3, 2, NULL); + +# Ok, for +# select max(ie) from t1 where oref=PARAM group by grp +# we'll have: +# 1 -> (1, NULL) matching + NULL +# 2 -> (3) non-matching +# 3 -> (3, NULL) non-matching + NULL +# 4 -> () nothing. + +create table t2 (oref int, a int); +insert into t2 values + (1, 1), + (2, 2), + (3, 3), + (4, NULL), + (2, NULL); + +# true, false, null, false, null +select a, oref, a in (select max(ie) + from t1 where oref=t2.oref group by grp) from t2; + +# This must have a trigcond +explain extended +select a, oref, a in (select max(ie) + from t1 where oref=t2.oref group by grp) from t2; + +# This must not have a trigcond: +explain extended +select a, oref from t2 +where a in (select max(ie) from t1 where oref=t2.oref group by grp); + + +# Non-correlated subquery, 2 NULL evaluations +create table t3 (a int); +insert into t3 values (NULL), (NULL); +flush status; +select a in (select max(ie) from t1 where oref=4 group by grp) from t3; +show status like 'Handler_read_rnd_next'; +select ' ^ This must show 11' Z; + +# This must show trigcond: +explain extended select a in (select max(ie) from t1 where oref=4 group by grp) from t3; + +drop table t1, t2, t3; + +# +# 2. Subquery handled with 'index_subquery': +# +create table t1 (a int, oref int, key(a)); +insert into t1 values + (1, 1), + (1, NULL), + (2, 3), + (2, NULL), + (3, NULL); + +create table t2 (a int, oref int); +insert into t2 values (1, 1), (2,2), (NULL, 3), (NULL, 4); + +select oref, a, a in (select a from t1 where oref=t2.oref) Z from t2; + +# The next explain shows "using index" but that is just incorrect display +# (there is a bug filed about this). +explain extended +select oref, a, a in (select a from t1 where oref=t2.oref) Z from t2; + +flush status; +select oref, a from t2 where a in (select a from t1 where oref=t2.oref); +# This will only show access to t2: +show status like '%Handler_read_rnd_next'; + +# Check that repeated NULL-scans are not cached (subq. is not correlated): +delete from t2; +insert into t2 values (NULL, 0),(NULL, 0), (NULL, 0), (NULL, 0); + +flush status; +select oref, a, a in (select a from t1 where oref=t2.oref) Z from t2; +show status like '%Handler_read%'; +select 'No key lookups, seq reads: 29= 5 reads from t2 + 4 * 6 reads from t1.' Z; + +drop table t1, t2; + +# +# 3. Subquery handled with 'unique_index_subquery': +# +create table t1 (a int, b int, primary key (a)); +insert into t1 values (1,1), (3,1),(100,1); + +create table t2 (a int, b int); +insert into t2 values (1,1),(2,1),(NULL,1),(NULL,0); + +select a,b, a in (select a from t1 where t1.b = t2.b) Z from t2 ; + +drop table t1, t2; + +# +# 4. Subquery that is a join, with ref access +# +create table t1 (a int, b int, key(a)); +insert into t1 values + (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9); + +create table t2 like t1; +insert into t2 select * from t1; +update t2 set b=1; + +create table t3 (a int, oref int); +insert into t3 values (1, 1), (NULL,1), (NULL,0); +select a, oref, + t3.a in (select t1.a from t1, t2 where t1.b=t2.a and t2.b=t3.oref) Z +from t3; + +# This must have trigcond in WHERE and HAVING: +explain extended +select a, oref, + t3.a in (select t1.a from t1, t2 where t1.b=t2.a and t2.b=t3.oref) Z +from t3; + +drop table t1, t2, t3; + diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 19a720a4fb8..d79b6905224 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -139,4 +139,43 @@ enable_query_log; show create table t1; drop table t1; -# End of 4.1 tests +# +# Bug#8706 - temporary table with data directory option fails +# +connect (session1,localhost,root,,); +connect (session2,localhost,root,,); + +connection session1; +disable_query_log; +eval create temporary table t1 (a int) engine=myisam data directory="$MYSQLTEST_VARDIR/log" select 9 a; +enable_query_log; +# If running test suite with a non standard tmp dir, the "show create table" +# will print "DATA_DIRECTORY=". Use replace_result to mask it out +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +show create table t1; + +connection session2; +disable_query_log; +eval create temporary table t1 (a int) engine=myisam data directory="$MYSQLTEST_VARDIR/log" select 99 a; +enable_query_log; +# If running test suite with a non standard tmp dir, the "show create table" +# will print "DATA_DIRECTORY=". Use replace_result to mask it out +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +show create table t1; + +connection default; +create table t1 (a int) engine=myisam select 42 a; + +connection session1; +select * from t1; +disconnect session1; +connection session2; +select * from t1; +disconnect session2; +connection default; +select * from t1; +drop table t1; + +--echo End of 4.1 tests + +--echo End of 5.0 tests diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 92320648033..2bb2292e5b8 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1,3 +1,7 @@ +# This test uses chmod, can't be run with root permissions +-- source include/not_as_root.inc + + # # Basic triggers test # @@ -1138,8 +1142,10 @@ select trigger_schema, trigger_name, event_object_schema, event_object_table, action_statement from information_schema.triggers where event_object_schema = 'test'; # Trick which makes update of second .TRN file impossible -system echo dummy >$MYSQLTEST_VARDIR/master-data/test/t1_ai.TRN~; -system chmod 000 $MYSQLTEST_VARDIR/master-data/test/t1_ai.TRN~; +write_file $MYSQLTEST_VARDIR/master-data/test/t1_ai.TRN~; +dummy +EOF +chmod 0000 $MYSQLTEST_VARDIR/master-data/test/t1_ai.TRN~; --error 1 rename table t1 to t2; # 't1' should be still there and triggers should work correctly @@ -1148,8 +1154,8 @@ select @a, @b; select trigger_schema, trigger_name, event_object_schema, event_object_table, action_statement from information_schema.triggers where event_object_schema = 'test'; -system chmod 600 $MYSQLTEST_VARDIR/master-data/test/t1_ai.TRN~; -system rm $MYSQLTEST_VARDIR/master-data/test/t1_ai.TRN~; +chmod 0600 $MYSQLTEST_VARDIR/master-data/test/t1_ai.TRN~; +remove_file $MYSQLTEST_VARDIR/master-data/test/t1_ai.TRN~; # Let us check that updates to .TRN files were rolled back too drop trigger t1_bi; drop trigger t1_ai; @@ -1499,4 +1505,52 @@ select * from t1; drop table t1; +# +# Bug #23651 "Server crashes when trigger which uses stored function +# invoked from different connections". +# +--disable_warnings +drop table if exists t1; +drop function if exists f1; +--enable_warnings +create table t1 (i int); +create function f1() returns int return 10; +create trigger t1_bi before insert on t1 for each row set @a:= f1() + 10; +insert into t1 values (); +select @a; +connection addconroot1; +insert into t1 values (); +select @a; +connection default; +drop table t1; +drop function f1; + +# +# Bug#23703: DROP TRIGGER needs an IF EXISTS +# + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1(a int, b varchar(50)); + +-- error ER_TRG_DOES_NOT_EXIST +drop trigger not_a_trigger; + +drop trigger if exists not_a_trigger; + +create trigger t1_bi before insert on t1 +for each row set NEW.b := "In trigger t1_bi"; + +insert into t1 values (1, "a"); +drop trigger if exists t1_bi; +insert into t1 values (2, "b"); +drop trigger if exists t1_bi; +insert into t1 values (3, "c"); + +select * from t1; + +drop table t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test index d46ba667665..48ad24ff6b7 100644 --- a/mysql-test/t/type_bit.test +++ b/mysql-test/t/type_bit.test @@ -261,4 +261,15 @@ insert into t1 (b, a) values ('2', '1'); select hex(a), b from t1; drop table t1; +# +# type was not properly initalized, which caused key_copy to fail +# + +create table t1(bit_field bit(2), int_field int, key a(bit_field)); +insert into t1 values (1,2); +handler t1 open as t1; +handler t1 read a=(1); +handler t1 close; +drop table t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index cdf73bf6c89..3ad6bdc53e4 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -125,3 +125,13 @@ PREPARE s FROM 'SELECT a FROM t1 WHERE a=(SELECT MAX(a) FROM t1) AND (a="2006060 EXECUTE s; DROP PREPARE s; DROP TABLE t1; + + +# +# Bug 19491 (CAST DATE AS DECIMAL returns incorrect result +# +SELECT CAST(CAST('2006-08-10' AS DATE) AS DECIMAL(20,6)); +SELECT CAST(CAST('2006-08-10 10:11:12' AS DATETIME) AS DECIMAL(20,6)); +SELECT CAST(CAST('2006-08-10 10:11:12' AS DATETIME) + INTERVAL 14 MICROSECOND AS DECIMAL(20,6)); +SELECT CAST(CAST('10:11:12.098700' AS TIME) AS DECIMAL(20,6)); + diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index e4843c3b83e..f315e88fd0e 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -613,7 +613,7 @@ select truncate(99.999999999999999999999999999999999999,31); #-- should return 99.9999999999999999999999999999999 # select truncate(99999999999999999999999999999999999999,-31); --- should return 90000000000000000000000000000000 +# should return 90000000000000000000000000000000 # #-- 6. Set functions (AVG, SUM, COUNT) should work. # @@ -810,7 +810,7 @@ select 1 / 0; #BUG#6048 Stored procedure causes operating system reboot #BUG#6053 DOUBLE PRECISION literal --- Tests from 'traditional' mode tests +# Tests from 'traditional' mode tests # set sql_mode='ansi,traditional'; # @@ -1108,3 +1108,15 @@ insert into t1 values (1,1), (1,2), (2,3), (2,4); select i, count(distinct j) from t1 group by i; select i+0.0 as i2, count(distinct j) from t1 group by i2; drop table t1; + +create table t1(f1 decimal(20,6)); +insert into t1 values (CAST('10:11:12' AS date) + interval 14 microsecond); +insert into t1 values (CAST('10:11:12' AS time)); +select * from t1; +drop table t1; + +# +# Bug #8663 (cant use bigint as input to CAST) +# +select cast(19999999999999999999 as unsigned); + diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test index 439e98471b2..7b87a388c56 100644 --- a/mysql-test/t/type_varchar.test +++ b/mysql-test/t/type_varchar.test @@ -187,3 +187,13 @@ left join t3 on t1.id=t3.id order by t3.id; --disable_metadata --enable_ps_protocol drop table t1, t2, t3; + +# +# Bug #11927: Warnings shown for CAST( chr as signed) but not (chr + 0) +# +CREATE TABLE t1 (a CHAR(2)); +INSERT INTO t1 VALUES (10), (50), (30), ('1a'), (60), ('t'); +SELECT a,(a + 0) FROM t1 ORDER BY a; +SELECT a,(a DIV 2) FROM t1 ORDER BY a; +SELECT a,CAST(a AS SIGNED) FROM t1 ORDER BY a; +DROP TABLE t1; diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test index c62d7829b05..52ae424e423 100644 --- a/mysql-test/t/udf.test +++ b/mysql-test/t/udf.test @@ -127,6 +127,50 @@ create table t1(f1 int); insert into t1 values(1),(2); explain select myfunc_int(f1) from t1 order by 1; drop table t1; + +# +# Bug #21809: Error 1356 while selecting from view with grouping though +# underlying select OK. +# +CREATE TABLE t1(a INT, b INT); INSERT INTO t1 values (1,1),(2,2); + +DELIMITER ||; +CREATE FUNCTION fn(a int) RETURNS int DETERMINISTIC +BEGIN + RETURN a; +END +|| +DELIMITER ;|| + +CREATE VIEW v1 AS SELECT a, fn(MIN(b)) as c FROM t1 GROUP BY a; + +SELECT myfunc_int(a AS attr_name) FROM t1; +EXPLAIN EXTENDED SELECT myfunc_int(a AS attr_name) FROM t1; +EXPLAIN EXTENDED SELECT myfunc_int(a) FROM t1; +SELECT a,c FROM v1; + +--error ER_PARSE_ERROR +SELECT a, fn(MIN(b) xx) as c FROM t1 GROUP BY a; +--error ER_PARSE_ERROR +SELECT myfunc_int(fn(MIN(b) xx)) as c FROM t1 GROUP BY a; +--error ER_PARSE_ERROR +SELECT myfunc_int(test.fn(MIN(b) xx)) as c FROM t1 GROUP BY a; + +SELECT myfunc_int(fn(MIN(b)) xx) as c FROM t1 GROUP BY a; +SELECT myfunc_int(test.fn(MIN(b)) xx) as c FROM t1 GROUP BY a; + +EXPLAIN EXTENDED SELECT myfunc_int(MIN(b) xx) as c FROM t1 GROUP BY a; +EXPLAIN EXTENDED SELECT test.fn(MIN(b)) as c FROM t1 GROUP BY a; +EXPLAIN EXTENDED SELECT myfunc_int(fn(MIN(b))) as c FROM t1 GROUP BY a; +EXPLAIN EXTENDED SELECT myfunc_int(test.fn(MIN(b))) as c FROM t1 GROUP BY a; +SELECT myfunc_int(MIN(b) xx) as c FROM t1 GROUP BY a; +SELECT test.fn(MIN(b)) as c FROM t1 GROUP BY a; +SELECT myfunc_int(fn(MIN(b))) as c FROM t1 GROUP BY a; +SELECT myfunc_int(test.fn(MIN(b))) as c FROM t1 GROUP BY a; +DROP VIEW v1; +DROP TABLE t1; +DROP FUNCTION fn; + --echo End of 5.0 tests. # diff --git a/mysql-test/t/utils.sh b/mysql-test/t/utils.sh new file mode 100644 index 00000000000..b3f4744947d --- /dev/null +++ b/mysql-test/t/utils.sh @@ -0,0 +1,55 @@ +########################################################################### +# +# This file provides utility functions and is included by other scripts. +# +# The following global variables must be set before calling functions from this +# file: +# - basename -- base name of the calling script (main application); +# - log_file -- where to store log records; +# +########################################################################### + +log() +{ + [ -z "$log_file" ] && return; + + log_level="$1" + log_msg="$2" + ts=`date` + + echo "[$ts] [$basename] [$log_level] $log_msg" >> "$log_file"; +} + +########################################################################### + +log_debug() +{ + log 'DEBUG' "$1" +} + +########################################################################### + +log_info() +{ + log 'INFO' "$1" + echo "$1" +} + +########################################################################### + +log_error() +{ + log 'ERROR' "$1" + echo "Error: $1" +} + +########################################################################### + +quit() +{ + exit_status="$1" + + log_debug "-- $basename: finished (exit_status: $exit_status) --" + + exit $exit_status +} diff --git a/mysql-test/t/varbinary.test b/mysql-test/t/varbinary.test index 5fbd116d7b8..2f0c1c83e84 100644 --- a/mysql-test/t/varbinary.test +++ b/mysql-test/t/varbinary.test @@ -1,3 +1,7 @@ +# This test uses chmod, can't be run with root permissions +-- source include/not_as_root.inc + + # Initialise --disable_warnings drop table if exists t1; @@ -37,3 +41,46 @@ select x,xx from t1; drop table t1; # End of 4.1 tests + +# +# Bug #19371 VARBINARY() have trailing zeros after upgrade from 4.1 +# + +# Test with a saved table from 4.1 +copy_file std_data/bug19371.frm $MYSQLTEST_VARDIR/master-data/test/t1.frm; +chmod 0777 $MYSQLTEST_VARDIR/master-data/test/t1.frm; +copy_file std_data/bug19371.MYD $MYSQLTEST_VARDIR/master-data/test/t1.MYD; +chmod 0777 $MYSQLTEST_VARDIR/master-data/test/t1.MYD; +copy_file std_data/bug19371.MYI $MYSQLTEST_VARDIR/master-data/test/t1.MYI; +chmod 0777 $MYSQLTEST_VARDIR/master-data/test/t1.MYI; + +# Everything _looks_ fine +show create table t1; + +# But the length of the varbinary columns are too long +select length(a), length(b) from t1; + +# Run CHECK TABLE, it should indicate table need a REPAIR TABLE +CHECK TABLE t1 FOR UPGRADE; + +# Run REPAIR TABLE to alter the table and repair +# the varbinary fields +REPAIR TABLE t1; + +# Now check it's back to normal +show create table t1; +select length(a), length(b) from t1; +insert into t1 values("ccc", "ddd"); +select length(a), length(b) from t1; +select hex(a), hex(b) from t1; +select concat("'", a, "'"), concat("'", b, "'") from t1; + +drop table t1; + +# Check that the fix does not affect table created with current version +create table t1(a varbinary(255)); +insert into t1 values("aaa "); +select length(a) from t1; +alter table t1 modify a varchar(255); +select length(a) from t1; + diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 9a4b75add13..67e0ab6bcbd 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -800,7 +800,7 @@ DROP DATABASE mysqltest1; CREATE TABLE t1 (a INT PRIMARY KEY); INSERT INTO t1 VALUES (1), (2), (3); CREATE DEFINER = 'no-such-user'@localhost VIEW v AS SELECT a from t1; ---warning 1448 +#--warning 1448 SHOW CREATE VIEW v; --error 1449 SELECT * FROM v; @@ -927,4 +927,41 @@ DROP VIEW v2; DROP VIEW v1; DROP USER mysqltest_u1@localhost; +# +# Bug#17254: Error for DEFINER security on VIEW provides too much info +# +connect (root,localhost,root,,); +connection root; +CREATE DATABASE db17254; +USE db17254; +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (10),(20); +CREATE USER def_17254@localhost; +GRANT SELECT ON db17254.* TO def_17254@localhost; +CREATE USER inv_17254@localhost; +GRANT SELECT ON db17254.t1 TO inv_17254@localhost; +GRANT CREATE VIEW ON db17254.* TO def_17254@localhost; + +connect (def,localhost,def_17254,,db17254); +connection def; +CREATE VIEW v1 AS SELECT * FROM t1; + +connection root; +DROP USER def_17254@localhost; + +connect (inv,localhost,inv_17254,,db17254); +connection inv; +--echo for a user +--error 1142 +SELECT * FROM v1; + +connection root; +--echo for a superuser +--error 1449 +SELECT * FROM v1; +DROP USER inv_17254@localhost; +DROP DATABASE db17254; +disconnect def; +disconnect inv; + # End of 5.0 tests. diff --git a/mysql-test/t/wait_for_process.sh b/mysql-test/t/wait_for_process.sh index df0f4a17e3a..4c2d89cfea6 100755 --- a/mysql-test/t/wait_for_process.sh +++ b/mysql-test/t/wait_for_process.sh @@ -2,34 +2,40 @@ ########################################################################### -pid_path="$1" -total_attempts="$2" -event="$3" +# NOTE: this script returns 0 (success) even in case of failure (except for +# usage-error). This is because this script is executed under +# mysql-test-run[.pl] and it's better to examine particular problem in log +# file, than just having said that the test case has failed. -case "$3" in - started) - check_fn='check_started'; - ;; +########################################################################### - stopped) - check_fn='check_stopped'; - ;; +basename=`basename "$0"` +dirname=`dirname "$0"` - *) - echo "Error: invalid third argument ('started' or 'stopped' expected)." - exit 0 -esac +########################################################################### + +. "$dirname/utils.sh" ########################################################################### check_started() { - [ ! -r "$pid_path" ] && return 1 + if [ ! -r "$pid_path" ]; then + log_debug "No PID-file ($pid_path) found -- not started." + return 1 + fi new_pid=`cat "$pid_path" 2>/dev/null` + err_code=$? + + log_debug "err_code: $err_code; new_pid: $new_pid." - [ $? -eq 0 -a "$original_pid" = "$new_pid" ] && return 1 + if [ $? -ne 0 -o -z "$new_pid" ]; then + log_debug "The process was not started." + return 1 + fi + log_debug "The process was started." return 0 } @@ -37,30 +43,72 @@ check_started() check_stopped() { - [ -r "$pid_path" ] && return 1 + if [ -r "$pid_path" ]; then + log_debug "PID-file '$pid_path' exists -- not stopped." + return 1 + fi + log_debug "No PID-file ($pid_path) found -- stopped." return 0 } ########################################################################### +if [ $# -ne 4 ]; then + echo "Usage: $basename <pid file path> <total attempts> started|stopped <test id>" + exit 1 +fi + +pid_path="$1" +total_attempts="$2" +event="$3" +test_id="$4" +log_file="$MYSQLTEST_VARDIR/log/$test_id.log" + +log_debug "-- $basename: starting --" +log_debug "pid_path: '$pid_path'" +log_debug "total_attempts: '$total_attempts'" +log_debug "event: '$event'" +log_debug "test_id: '$test_id'" +log_debug "log_file: '$log_file'" + +########################################################################### + +case "$event" in + started) + check_fn='check_started'; + ;; + + stopped) + check_fn='check_stopped'; + ;; + + *) + log_error "Invalid third argument ('started' or 'stopped' expected)." + quit 0 +esac + +########################################################################### + cur_attempt=1 while true; do + log_debug "cur_attempt: $cur_attempt." + if ( eval $check_fn ); then - echo "Success: the process has been $event." - exit 0 + log_info "Success: the process has been $event." + quit 0 fi [ $cur_attempt -ge $total_attempts ] && break + log_debug "Sleeping for 1 second..." sleep 1 cur_attempt=`expr $cur_attempt + 1` done -echo "Error: the process has not been $event in $total_attempts secs." -exit 0 - +log_error "The process has not been $event in $total_attempts secs." +quit 0 diff --git a/mysql-test/t/wait_for_socket.sh b/mysql-test/t/wait_for_socket.sh index 3b900fa2208..1bce74dfd3a 100755 --- a/mysql-test/t/wait_for_socket.sh +++ b/mysql-test/t/wait_for_socket.sh @@ -2,9 +2,25 @@ ########################################################################### -if [ $# -ne 6 ]; then - echo "Usage: wait_for_socket.sh <executable path> <socket path> <username> <password> <db> <timeout>" - exit 0 +# NOTE: this script returns 0 (success) even in case of failure (except for +# usage-error). This is because this script is executed under +# mysql-test-run[.pl] and it's better to examine particular problem in log +# file, than just having said that the test case has failed. + +########################################################################### + +basename=`basename "$0"` +dirname=`dirname "$0"` + +########################################################################### + +. "$dirname/utils.sh" + +########################################################################### + +if [ $# -ne 7 ]; then + echo "Usage: wait_for_socket.sh <executable path> <socket path> <username> <password> <db> <timeout> <test id>" + exit 1 fi client_exe="$1" @@ -13,41 +29,57 @@ username="$3" password="$4" db="$5" total_timeout="$6" +test_id="$7" +log_file="$MYSQLTEST_VARDIR/log/$test_id.log" + +log_debug "-- $basename: starting --" +log_debug "client_exe: '$client_exe'" +log_debug "socket_path: '$socket_path'" +log_debug "username: '$username'" +log_debug "password: '$password'" +log_debug "db: '$db'" +log_debug "total_timeout: '$total_timeout'" +log_debug "test_id: '$test_id'" +log_debug "log_file: '$log_file'" ########################################################################### if [ -z "$client_exe" ]; then - echo "Error: invalid path to client executable ($client_exe)." - exit 0; + log_error "Invalid path to client executable ($client_exe)." + quit 0; fi if [ ! -x "$client_exe" ]; then - echo "Error: client by path '$client_exe' is not available." - exit 0; + log_error "Client by path '$client_exe' is not available." + quit 0; fi if [ -z "$socket_path" ]; then - echo "Error: invalid socket patch." - exit 0 + log_error "Invalid socket patch ($socket_path)." + quit 0 fi ########################################################################### -client_args="--silent --socket=$socket_path " +client_args="--silent --socket=$socket_path --connect_timeout=1 " [ -n "$username" ] && client_args="$client_args --user=$username " [ -n "$password" ] && client_args="$client_args --password=$password " [ -n "$db" ] && client_args="$client_args $db" +log_debug "client_args: '$client_args'" + ########################################################################### cur_attempt=1 while true; do + log_debug "cur_attempt: $cur_attempt." + if ( echo 'quit' | "$client_exe" $client_args >/dev/null 2>&1 ); then - echo "Success: server is ready to accept connection on socket." - exit 0 + log_info "Success: server is ready to accept connection on socket." + quit 0 fi [ $cur_attempt -ge $total_timeout ] && break @@ -58,5 +90,5 @@ while true; do done -echo "Error: server does not accept connections after $total_timeout seconds." -exit 0 +log_error "Server does not accept connections after $total_timeout seconds." +quit 0 diff --git a/mysql-test/t/windows.test b/mysql-test/t/windows.test index d6bcfeb8cb3..b5377a9b9b0 100644 --- a/mysql-test/t/windows.test +++ b/mysql-test/t/windows.test @@ -17,4 +17,13 @@ use prn; create table nu (a int); drop table nu; +# +# Bug17489: ailed to put data file in custom directory use "data directory" option +# +--disable_warnings +drop table if exists t1; +--enable_warnings +CREATE TABLE t1 ( `ID` int(6) ) data directory 'c:/tmp/' index directory 'c:/tmp/' engine=MyISAM; +drop table t1; + # End of 4.1 tests diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 7926cb916c1..b1a3e7441fb 100755 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -26,4 +26,5 @@ ADD_LIBRARY(mysys array.c charset-def.c charset.c checksum.c default.c default_m my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c my_windac.c my_winsem.c my_winthread.c my_write.c ptr_cmp.c queues.c rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c - thr_rwlock.c tree.c typelib.c base64.c my_memmem.c) + thr_rwlock.c tree.c typelib.c base64.c my_memmem.c + my_getpagesize.c) diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 041130fdf5c..47480e8f363 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -29,7 +29,7 @@ noinst_HEADERS = mysys_priv.h my_static.h \ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_path.c mf_loadpath.c my_file.c \ my_open.c my_create.c my_dup.c my_seek.c my_read.c \ - my_pread.c my_write.c \ + my_pread.c my_write.c my_getpagesize.c \ mf_keycache.c mf_keycaches.c my_crc32.c \ mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \ mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \ diff --git a/mysys/base64.c b/mysys/base64.c index b29c8ff8360..2d1b7f2aeba 100644 --- a/mysys/base64.c +++ b/mysys/base64.c @@ -40,7 +40,7 @@ base64_needed_encoded_length(int length_of_data) int base64_needed_decoded_length(int length_of_encoded_data) { - return ceil(length_of_encoded_data * 3 / 4); + return (int) ceil(length_of_encoded_data * 3 / 4); } diff --git a/mysys/default.c b/mysys/default.c index 540968d4ba0..a147163e938 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -484,7 +484,7 @@ static int search_default_file(Process_option_func opt_handler, my_bool have_ext= fn_ext(config_file)[0] != 0; const char **exts_to_use= have_ext ? empty_list : f_extensions; - for (ext= (char**) exts_to_use; *ext; *ext++) + for (ext= (char**) exts_to_use; *ext; ext++) { int error; if ((error= search_default_file_with_ext(opt_handler, handler_ctx, @@ -672,7 +672,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, ext= fn_ext(search_file->name); /* check extension */ - for (tmp_ext= (char**) f_extensions; *tmp_ext; *tmp_ext++) + for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++) { if (!strcmp(ext, *tmp_ext)) break; @@ -861,7 +861,7 @@ void my_print_default_files(const char *conf_file) { for (dirs=default_directories ; *dirs; dirs++) { - for (ext= (char**) exts_to_use; *ext; *ext++) + for (ext= (char**) exts_to_use; *ext; ext++) { const char *pos; char *end; @@ -979,10 +979,11 @@ static uint my_get_system_windows_directory(char *buffer, uint size) Everywhere else, this is: 1. /etc/ - 2. getenv(DEFAULT_HOME_ENV) - 3. "" - 4. "~/" - 5. --sysconfdir=<path> + 2. /etc/mysql/ + 3. getenv(DEFAULT_HOME_ENV) + 4. "" + 5. "~/" + 6. --sysconfdir=<path> */ @@ -1008,6 +1009,7 @@ static void init_default_directories() *ptr++= env; #endif *ptr++= "/etc/"; + *ptr++= "/etc/mysql/"; #endif if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) *ptr++= env; diff --git a/mysys/hash.c b/mysys/hash.c index 99479ef6769..9a268a7e218 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -53,7 +53,7 @@ _hash_init(HASH *hash,CHARSET_INFO *charset, void (*free_element)(void*),uint flags CALLER_INFO_PROTO) { DBUG_ENTER("hash_init"); - DBUG_PRINT("enter",("hash: 0x%lx size: %d",hash,size)); + DBUG_PRINT("enter",("hash: 0x%lx size: %d", (long) hash, size)); hash->records=0; if (my_init_dynamic_array_ci(&hash->array,sizeof(HASH_LINK),size,0)) @@ -109,7 +109,7 @@ static inline void hash_free_elements(HASH *hash) void hash_free(HASH *hash) { DBUG_ENTER("hash_free"); - DBUG_PRINT("enter",("hash: 0x%lxd",hash)); + DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash)); hash_free_elements(hash); hash->free= 0; @@ -129,7 +129,7 @@ void hash_free(HASH *hash) void my_hash_reset(HASH *hash) { DBUG_ENTER("my_hash_reset"); - DBUG_PRINT("enter",("hash: 0x%lxd",hash)); + DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash)); hash_free_elements(hash); reset_dynamic(&hash->array); @@ -644,7 +644,8 @@ my_bool hash_check(HASH *hash) if ((rec_link=hash_rec_mask(hash,hash_info,blength,records)) != i) { DBUG_PRINT("error", - ("Record in wrong link at %d: Start %d Record: 0x%lx Record-link %d", idx,i,hash_info->data,rec_link)); + ("Record in wrong link at %d: Start %d Record: 0x%lx Record-link %d", + idx, i, (long) hash_info->data, rec_link)); error=1; } else @@ -655,12 +656,12 @@ my_bool hash_check(HASH *hash) } if (found != records) { - DBUG_PRINT("error",("Found %ld of %ld records")); + DBUG_PRINT("error",("Found %u of %u records", found, records)); error=1; } if (records) DBUG_PRINT("info", - ("records: %ld seeks: %d max links: %d hitrate: %.2f", + ("records: %u seeks: %d max links: %d hitrate: %.2f", records,seek,max_links,(float) seek / (float) records)); return error; } diff --git a/mysys/list.c b/mysys/list.c index 0e55c9399f5..c4ce5b5e36f 100644 --- a/mysys/list.c +++ b/mysys/list.c @@ -28,7 +28,7 @@ LIST *list_add(LIST *root, LIST *element) { DBUG_ENTER("list_add"); - DBUG_PRINT("enter",("root: 0x%lx element: 0x%lx", root, element)); + DBUG_PRINT("enter",("root: 0x%lx element: 0x%lx", (long) root, (long) element)); if (root) { if (root->prev) /* If add in mid of list */ diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 249eaf48ad2..e0962999015 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -594,7 +594,8 @@ void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare, DBUG_ENTER("init_io_cache_share"); DBUG_PRINT("io_cache_share", ("read_cache: 0x%lx share: 0x%lx " "write_cache: 0x%lx threads: %u", - read_cache, cshare, write_cache, num_threads)); + (long) read_cache, (long) cshare, + (long) write_cache, num_threads)); DBUG_ASSERT(num_threads > 1); DBUG_ASSERT(read_cache->type == READ_CACHE); @@ -656,7 +657,7 @@ void remove_io_thread(IO_CACHE *cache) pthread_mutex_lock(&cshare->mutex); DBUG_PRINT("io_cache_share", ("%s: 0x%lx", (cache == cshare->source_cache) ? - "writer" : "reader", cache)); + "writer" : "reader", (long) cache)); /* Remove from share. */ total= --cshare->total_threads; @@ -732,7 +733,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) cshare->running_threads--; DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u", (cache == cshare->source_cache) ? - "writer" : "reader", cache, (ulong) pos, + "writer" : "reader", (long) cache, (ulong) pos, cshare->running_threads)); if (cshare->source_cache) @@ -871,7 +872,7 @@ static void unlock_io_cache(IO_CACHE *cache) DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u", (cache == cshare->source_cache) ? "writer" : "reader", - cache, (ulong) cshare->pos_in_file, + (long) cache, (ulong) cshare->pos_in_file, cshare->total_threads)); cshare->running_threads= cshare->total_threads; diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 11e27bb19ad..d658e6fe055 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -418,9 +418,9 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, DBUG_PRINT("exit", ("disk_blocks: %d block_root: 0x%lx hash_entries: %d\ hash_root: 0x%lx hash_links: %d hash_link_root: 0x%lx", - keycache->disk_blocks, keycache->block_root, - keycache->hash_entries, keycache->hash_root, - keycache->hash_links, keycache->hash_link_root)); + keycache->disk_blocks, (long) keycache->block_root, + keycache->hash_entries, (long) keycache->hash_root, + keycache->hash_links, (long) keycache->hash_link_root)); bzero((gptr) keycache->changed_blocks, sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH); bzero((gptr) keycache->file_blocks, @@ -633,7 +633,7 @@ void change_key_cache_param(KEY_CACHE *keycache, uint division_limit, void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) { DBUG_ENTER("end_key_cache"); - DBUG_PRINT("enter", ("key_cache: 0x%lx", keycache)); + DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache)); if (!keycache->key_cache_inited) DBUG_VOID_RETURN; @@ -652,7 +652,7 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) keycache->blocks_changed= 0; } - DBUG_PRINT("status", ("used: %d changed: %d w_requests: %lu " + DBUG_PRINT("status", ("used: %lu changed: %lu w_requests: %lu " "writes: %lu r_requests: %lu reads: %lu", keycache->blocks_used, keycache->global_blocks_changed, (ulong) keycache->global_cache_w_requests, @@ -1085,7 +1085,7 @@ static void unreg_request(KEY_CACHE *keycache, if (block->temperature == BLOCK_WARM) keycache->warm_blocks--; block->temperature= BLOCK_HOT; - KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks=%u", + KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks: %lu", keycache->warm_blocks)); } link_block(keycache, block, hot, (my_bool)at_end); @@ -1104,7 +1104,7 @@ static void unreg_request(KEY_CACHE *keycache, keycache->warm_blocks++; block->temperature= BLOCK_WARM; } - KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks=%u", + KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks: %lu", keycache->warm_blocks)); } } @@ -1352,11 +1352,11 @@ static BLOCK_LINK *find_key_block(KEY_CACHE *keycache, DBUG_ENTER("find_key_block"); KEYCACHE_THREAD_TRACE("find_key_block:begin"); - DBUG_PRINT("enter", ("fd: %u pos %lu wrmode: %lu", - (uint) file, (ulong) filepos, (uint) wrmode)); - KEYCACHE_DBUG_PRINT("find_key_block", ("fd: %u pos: %lu wrmode: %lu", - (uint) file, (ulong) filepos, - (uint) wrmode)); + DBUG_PRINT("enter", ("fd: %d pos: %lu wrmode: %d", + file, (ulong) filepos, wrmode)); + KEYCACHE_DBUG_PRINT("find_key_block", ("fd: %d pos: %lu wrmode: %d", + file, (ulong) filepos, + wrmode)); #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) DBUG_EXECUTE("check_keycache2", test_key_cache(keycache, "start of find_key_block", 0);); @@ -1646,8 +1646,8 @@ restart: KEYCACHE_DBUG_ASSERT(page_status != -1); *page_st=page_status; KEYCACHE_DBUG_PRINT("find_key_block", - ("fd: %u pos %lu block->status %u page_status %lu", - (uint) file, (ulong) filepos, block->status, + ("fd: %d pos: %lu block->status: %u page_status: %u", + file, (ulong) filepos, block->status, (uint) page_status)); #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) @@ -2338,7 +2338,7 @@ static int flush_key_blocks_int(KEY_CACHE *keycache, BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache; int last_errno= 0; DBUG_ENTER("flush_key_blocks_int"); - DBUG_PRINT("enter",("file: %d blocks_used: %d blocks_changed: %d", + DBUG_PRINT("enter",("file: %d blocks_used: %lu blocks_changed: %lu", file, keycache->blocks_used, keycache->blocks_changed)); #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) @@ -2543,7 +2543,7 @@ int flush_key_blocks(KEY_CACHE *keycache, { int res; DBUG_ENTER("flush_key_blocks"); - DBUG_PRINT("enter", ("keycache: 0x%lx", keycache)); + DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache)); if (keycache->disk_blocks <= 0) DBUG_RETURN(0); diff --git a/mysys/mf_keycaches.c b/mysys/mf_keycaches.c index 38fef31fdd4..e5086014a27 100644 --- a/mysys/mf_keycaches.c +++ b/mysys/mf_keycaches.c @@ -159,7 +159,7 @@ static byte *safe_hash_search(SAFE_HASH *hash, const byte *key, uint length) result= hash->default_value; else result= ((SAFE_HASH_ENTRY*) result)->data; - DBUG_PRINT("exit",("data: 0x%lx", result)); + DBUG_PRINT("exit",("data: 0x%lx", (long) result)); DBUG_RETURN(result); } @@ -190,7 +190,7 @@ static my_bool safe_hash_set(SAFE_HASH *hash, const byte *key, uint length, SAFE_HASH_ENTRY *entry; my_bool error= 0; DBUG_ENTER("safe_hash_set"); - DBUG_PRINT("enter",("key: %.*s data: 0x%lx", length, key, data)); + DBUG_PRINT("enter",("key: %.*s data: 0x%lx", length, key, (long) data)); rw_wrlock(&hash->mutex); entry= (SAFE_HASH_ENTRY*) hash_search(&hash->hash, key, length); diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index d5346d530c3..c97ae83f6bc 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -48,7 +48,8 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size, uint pre_alloc_size __attribute__((unused))) { DBUG_ENTER("init_alloc_root"); - DBUG_PRINT("enter",("root: 0x%lx", mem_root)); + DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root)); + mem_root->free= mem_root->used= mem_root->pre_alloc= 0; mem_root->min_malloc= 32; mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE; @@ -146,7 +147,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) #if defined(HAVE_purify) && defined(EXTRA_DEBUG) reg1 USED_MEM *next; DBUG_ENTER("alloc_root"); - DBUG_PRINT("enter",("root: 0x%lx", mem_root)); + DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root)); DBUG_ASSERT(alloc_root_inited(mem_root)); @@ -160,8 +161,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) next->next= mem_root->used; next->size= Size; mem_root->used= next; - DBUG_PRINT("exit",("ptr: 0x%lx", (((char*) next)+ - ALIGN_SIZE(sizeof(USED_MEM))))); + DBUG_PRINT("exit",("ptr: 0x%lx", (long) (((char*) next)+ + ALIGN_SIZE(sizeof(USED_MEM))))); DBUG_RETURN((gptr) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM)))); #else uint get_size, block_size; @@ -169,7 +170,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) reg1 USED_MEM *next= 0; reg2 USED_MEM **prev; DBUG_ENTER("alloc_root"); - DBUG_PRINT("enter",("root: 0x%lx", mem_root)); + DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root)); DBUG_ASSERT(alloc_root_inited(mem_root)); Size= ALIGN_SIZE(Size); @@ -328,7 +329,7 @@ void free_root(MEM_ROOT *root, myf MyFlags) { reg1 USED_MEM *next,*old; DBUG_ENTER("free_root"); - DBUG_PRINT("enter",("root: 0x%lx flags: %u", root, (uint) MyFlags)); + DBUG_PRINT("enter",("root: 0x%lx flags: %u", (long) root, (uint) MyFlags)); if (!root) /* QQ: Should be deleted */ DBUG_VOID_RETURN; /* purecov: inspected */ diff --git a/mysys/my_dup.c b/mysys/my_dup.c index 4b7434e29ea..cdc15b3ebce 100644 --- a/mysys/my_dup.c +++ b/mysys/my_dup.c @@ -30,7 +30,7 @@ File my_dup(File file, myf MyFlags) File fd; const char *filename; DBUG_ENTER("my_dup"); - DBUG_PRINT("my",("file: %d MyFlags: %d", MyFlags)); + DBUG_PRINT("my",("file: %d MyFlags: %d", file, MyFlags)); fd = dup(file); filename= (((uint) file < my_file_limit) ? my_file_info[(int) file].name : "Unknown"); diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index f07beec9f39..6e81d40a2d6 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -79,7 +79,7 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) my_stream_opened++; my_file_info[fileno(fd)].type = STREAM_BY_FOPEN; pthread_mutex_unlock(&THR_LOCK_open); - DBUG_PRINT("exit",("stream: 0x%lx",fd)); + DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); DBUG_RETURN(fd); } pthread_mutex_unlock(&THR_LOCK_open); @@ -103,7 +103,7 @@ int my_fclose(FILE *fd, myf MyFlags) { int err,file; DBUG_ENTER("my_fclose"); - DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d",fd, MyFlags)); + DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) fd, MyFlags)); pthread_mutex_lock(&THR_LOCK_open); file=fileno(fd); @@ -163,7 +163,7 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) pthread_mutex_unlock(&THR_LOCK_open); } - DBUG_PRINT("exit",("stream: 0x%lx",fd)); + DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); DBUG_RETURN(fd); } /* my_fdopen */ diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c index 5b17e3ff51c..0f7f4cc888f 100644 --- a/mysys/my_fstream.c +++ b/mysys/my_fstream.c @@ -40,7 +40,7 @@ uint my_fread(FILE *stream, byte *Buffer, uint Count, myf MyFlags) uint readbytes; DBUG_ENTER("my_fread"); DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %d", - stream, Buffer, Count, MyFlags)); + (long) stream, (long) Buffer, Count, MyFlags)); if ((readbytes = (uint) fread(Buffer,sizeof(char),(size_t) Count,stream)) != Count) @@ -81,7 +81,7 @@ uint my_fwrite(FILE *stream, const byte *Buffer, uint Count, myf MyFlags) #endif DBUG_ENTER("my_fwrite"); DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %d", - stream, Buffer, Count, MyFlags)); + (long) stream, (long) Buffer, Count, MyFlags)); #if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM) errors=0; @@ -153,7 +153,7 @@ my_off_t my_fseek(FILE *stream, my_off_t pos, int whence, { DBUG_ENTER("my_fseek"); DBUG_PRINT("my",("stream: 0x%lx pos: %lu whence: %d MyFlags: %d", - stream, pos, whence, MyFlags)); + (long) stream, (long) pos, whence, MyFlags)); DBUG_RETURN(fseek(stream, (off_t) pos, whence) ? MY_FILEPOS_ERROR : (my_off_t) ftell(stream)); } /* my_seek */ @@ -166,7 +166,7 @@ my_off_t my_ftell(FILE *stream, myf MyFlags __attribute__((unused))) { off_t pos; DBUG_ENTER("my_ftell"); - DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d",stream, MyFlags)); + DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) stream, MyFlags)); pos=ftell(stream); DBUG_PRINT("exit",("ftell: %lu",(ulong) pos)); DBUG_RETURN((my_off_t) pos); diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 95dc5afeae9..878e4b5103c 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -59,13 +59,18 @@ char *disabled_my_option= (char*) "0"; my_bool my_getopt_print_errors= 1; -static void default_reporter(enum loglevel level __attribute__((unused)), +static void default_reporter(enum loglevel level, const char *format, ...) { va_list args; va_start(args, format); + if (level == WARNING_LEVEL) + fprintf(stderr, "%s", "Warning: "); + else if (level == INFORMATION_LEVEL) + fprintf(stderr, "%s", "Info: "); vfprintf(stderr, format, args); va_end(args); + fflush(stderr); } /* diff --git a/mysys/my_getpagesize.c b/mysys/my_getpagesize.c new file mode 100644 index 00000000000..ac4bd775ba9 --- /dev/null +++ b/mysys/my_getpagesize.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2000-2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 "mysys_priv.h" + +#ifndef HAVE_GETPAGESIZE + +#if defined __WIN__ + +int my_getpagesize(void) +{ + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwPageSize; +} + +#else + +/* Default implementation */ +int my_getpagesize(void) +{ + return (int)8192; +} + +#endif + +#endif + diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c index 5663ceaa60e..b6b6ee610a5 100644 --- a/mysys/my_getwd.c +++ b/mysys/my_getwd.c @@ -45,7 +45,7 @@ int my_getwd(my_string buf, uint size, myf MyFlags) { my_string pos; DBUG_ENTER("my_getwd"); - DBUG_PRINT("my",("buf: 0x%lx size: %d MyFlags %d", buf,size,MyFlags)); + DBUG_PRINT("my",("buf: 0x%lx size: %d MyFlags %d", (long) buf,size,MyFlags)); #if ! defined(MSDOS) if (curr_dir[0]) /* Current pos is saved here */ diff --git a/mysys/my_handler.c b/mysys/my_handler.c index 23d28956808..46144c0dff2 100644 --- a/mysys/my_handler.c +++ b/mysys/my_handler.c @@ -505,6 +505,7 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a) switch ((enum ha_base_keytype) keyseg->type) { case HA_KEYTYPE_TEXT: case HA_KEYTYPE_BINARY: + case HA_KEYTYPE_BIT: if (keyseg->flag & HA_SPACE_PACK) { int a_length; @@ -516,7 +517,9 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a) a= end; break; case HA_KEYTYPE_VARTEXT1: + case HA_KEYTYPE_VARTEXT2: case HA_KEYTYPE_VARBINARY1: + case HA_KEYTYPE_VARBINARY2: { int a_length; get_key_length(a_length, a); @@ -546,6 +549,10 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a) case HA_KEYTYPE_DOUBLE: a= end; break; + case HA_KEYTYPE_END: /* purecov: inspected */ + /* keep compiler happy */ + DBUG_ASSERT(0); + break; } } return keyseg; diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 1c5630ad14e..ae7b0baafbd 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -638,7 +638,7 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags) int m_used; DBUG_ENTER("my_stat"); DBUG_PRINT("my", ("path: '%s', stat_area: 0x%lx, MyFlags: %d", path, - (byte *) stat_area, my_flags)); + (long) stat_area, my_flags)); if ((m_used= (stat_area == NULL))) if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags))) diff --git a/mysys/my_lread.c b/mysys/my_lread.c index a96febe4474..ccf795631b8 100644 --- a/mysys/my_lread.c +++ b/mysys/my_lread.c @@ -27,8 +27,8 @@ uint32 my_lread(int Filedes, byte *Buffer, uint32 Count, myf MyFlags) { uint32 readbytes; DBUG_ENTER("my_lread"); - DBUG_PRINT("my",("Fd: %d Buffer: %ld Count: %ld MyFlags: %d", - Filedes, Buffer, Count, MyFlags)); + DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", + Filedes, (long) Buffer, (ulong) Count, MyFlags)); DBUG_PRINT("error", ("Deprecated my_lread() function should not be used.")); diff --git a/mysys/my_lwrite.c b/mysys/my_lwrite.c index 02c56a69ba4..85f4677932e 100644 --- a/mysys/my_lwrite.c +++ b/mysys/my_lwrite.c @@ -23,8 +23,8 @@ uint32 my_lwrite(int Filedes, const byte *Buffer, uint32 Count, myf MyFlags) { uint32 writenbytes; DBUG_ENTER("my_lwrite"); - DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %ld MyFlags: %d", - Filedes, Buffer, Count, MyFlags)); + DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", + Filedes, (long) Buffer, (ulong) Count, MyFlags)); DBUG_PRINT("error", ("Deprecated my_lwrite() function should not be used.")); diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c index f33db2655c4..c6d51e29f18 100644 --- a/mysys/my_malloc.c +++ b/mysys/my_malloc.c @@ -44,7 +44,7 @@ gptr my_malloc(unsigned int size, myf my_flags) } else if (my_flags & MY_ZEROFILL) bzero(point,size); - DBUG_PRINT("exit",("ptr: 0x%lx",point)); + DBUG_PRINT("exit",("ptr: 0x%lx", (long) point)); DBUG_RETURN(point); } /* my_malloc */ @@ -55,7 +55,7 @@ gptr my_malloc(unsigned int size, myf my_flags) void my_no_flags_free(gptr ptr) { DBUG_ENTER("my_free"); - DBUG_PRINT("my",("ptr: 0x%lx",ptr)); + DBUG_PRINT("my",("ptr: 0x%lx", (long) ptr)); if (ptr) free(ptr); DBUG_VOID_RETURN; diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c index 21bfddae46c..eb74aaeaae4 100644 --- a/mysys/my_mmap.c +++ b/mysys/my_mmap.c @@ -33,13 +33,6 @@ int my_msync(int fd, void *addr, size_t len, int flags) static SECURITY_ATTRIBUTES mmap_security_attributes= {sizeof(SECURITY_ATTRIBUTES), 0, TRUE}; -int my_getpagesize(void) -{ - SYSTEM_INFO si; - GetSystemInfo(&si); - return si.dwPageSize; -} - void *my_mmap(void *addr, size_t len, int prot, int flags, int fd, my_off_t offset) { diff --git a/mysys/my_pread.c b/mysys/my_pread.c index f378d548731..b1b9d9da950 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -30,7 +30,7 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, int error; DBUG_ENTER("my_pread"); DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d", - Filedes, (ulong) offset, Buffer, Count, MyFlags)); + Filedes, (ulong) offset, (long) Buffer, Count, MyFlags)); for (;;) { @@ -49,8 +49,8 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, if (error) { my_errno=errno; - DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d", - readbytes,Count,Filedes,my_errno)); + DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d", + (int) readbytes, Count,Filedes,my_errno)); #ifdef THREAD if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR) { @@ -87,7 +87,7 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, ulong written; DBUG_ENTER("my_pwrite"); DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %d MyFlags: %d", - Filedes, (ulong) offset,Buffer, Count, MyFlags)); + Filedes, (ulong) offset, (long) Buffer, Count, MyFlags)); errors=0; written=0L; for (;;) diff --git a/mysys/my_read.c b/mysys/my_read.c index 8b88e483fef..33eb3ddf334 100644 --- a/mysys/my_read.c +++ b/mysys/my_read.c @@ -39,7 +39,7 @@ uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags) uint readbytes, save_count; DBUG_ENTER("my_read"); DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d", - Filedes, Buffer, Count, MyFlags)); + Filedes, (long) Buffer, Count, MyFlags)); save_count= Count; for (;;) @@ -48,8 +48,8 @@ uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags) if ((readbytes= (uint) read(Filedes, Buffer, Count)) != Count) { my_errno= errno ? errno : -1; - DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d", - readbytes, Count, Filedes, my_errno)); + DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d", + (int) readbytes, Count, Filedes, my_errno)); #ifdef THREAD if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR) { diff --git a/mysys/my_realloc.c b/mysys/my_realloc.c index a385bf1e530..b521ae36b94 100644 --- a/mysys/my_realloc.c +++ b/mysys/my_realloc.c @@ -27,7 +27,7 @@ gptr my_realloc(gptr oldpoint, uint size, myf my_flags) { gptr point; DBUG_ENTER("my_realloc"); - DBUG_PRINT("my",("ptr: 0x%lx size: %u my_flags: %d",oldpoint, size, + DBUG_PRINT("my",("ptr: 0x%lx size: %u my_flags: %d", (long) oldpoint, size, my_flags)); if (!oldpoint && (my_flags & MY_ALLOW_ZERO_PTR)) @@ -60,6 +60,6 @@ gptr my_realloc(gptr oldpoint, uint size, myf my_flags) my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG), size); } #endif - DBUG_PRINT("exit",("ptr: 0x%lx",point)); + DBUG_PRINT("exit",("ptr: 0x%lx", (long) point)); DBUG_RETURN(point); } /* my_realloc */ diff --git a/mysys/my_seek.c b/mysys/my_seek.c index 69a24c2d3c6..e8c109acacd 100644 --- a/mysys/my_seek.c +++ b/mysys/my_seek.c @@ -61,7 +61,7 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, if (newpos == (os_off_t) -1) { my_errno=errno; - DBUG_PRINT("error",("lseek: %lu, errno: %d",newpos,errno)); + DBUG_PRINT("error",("lseek: %lu, errno: %d", (ulong) newpos,errno)); DBUG_RETURN(MY_FILEPOS_ERROR); } if ((my_off_t) newpos != pos) diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 4d23d01cd82..fcae18d4686 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -30,7 +30,10 @@ pthread_key(struct st_my_thread_var, THR_KEY_mysys); #endif /* USE_TLS */ pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open, THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap, - THR_LOCK_net, THR_LOCK_charset; + THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads; +pthread_cond_t THR_COND_threads; +uint THR_thread_count= 0; +uint my_thread_end_wait_time= 5; #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) pthread_mutex_t LOCK_localtime_r; #endif @@ -79,7 +82,7 @@ my_bool my_thread_global_init(void) #endif #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP /* - Set mutex type to "errorcheck" a.k.a "adaptive" + Set mutex type to "errorcheck" */ pthread_mutexattr_init(&my_errorcheck_mutexattr); pthread_mutexattr_settype(&my_errorcheck_mutexattr, @@ -94,6 +97,8 @@ my_bool my_thread_global_init(void) pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST); + pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST); + pthread_cond_init(&THR_COND_threads, NULL); #if defined( __WIN__) || defined(OS2) win_pthread_init(); #endif @@ -114,6 +119,27 @@ my_bool my_thread_global_init(void) void my_thread_global_end(void) { + struct timespec abstime; + my_bool all_threads_killed= 1; + + set_timespec(abstime, my_thread_end_wait_time); + pthread_mutex_lock(&THR_LOCK_threads); + while (THR_thread_count > 0) + { + int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads, + &abstime); + if (error == ETIMEDOUT || error == ETIME) + { + if (THR_thread_count) + fprintf(stderr, + "Error in my_thread_global_end(): %d threads didn't exit\n", + THR_thread_count); + all_threads_killed= 0; + break; + } + } + pthread_mutex_unlock(&THR_LOCK_threads); + pthread_key_delete(THR_KEY_mysys); #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP pthread_mutexattr_destroy(&my_fast_mutexattr); @@ -129,6 +155,11 @@ void my_thread_global_end(void) pthread_mutex_destroy(&THR_LOCK_heap); pthread_mutex_destroy(&THR_LOCK_net); pthread_mutex_destroy(&THR_LOCK_charset); + if (all_threads_killed) + { + pthread_mutex_destroy(&THR_LOCK_threads); + pthread_cond_destroy (&THR_COND_threads); + } #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) pthread_mutex_destroy(&LOCK_localtime_r); #endif @@ -140,10 +171,23 @@ void my_thread_global_end(void) static long thread_id=0; /* - We can't use mutex_locks here if we are using windows as - we may have compiled the program with SAFE_MUTEX, in which - case the checking of mutex_locks will not work until - the pthread_self thread specific variable is initialized. + Allocate thread specific memory for the thread, used by mysys and dbug + + SYNOPSIS + my_thread_init() + + NOTES + We can't use mutex_locks here if we are using windows as + we may have compiled the program with SAFE_MUTEX, in which + case the checking of mutex_locks will not work until + the pthread_self thread specific variable is initialized. + + This function may called multiple times for a thread, for example + if one uses my_init() followed by mysql_server_init(). + + RETURN + 0 ok + 1 Fatal error; mysys/dbug functions can't be used */ my_bool my_thread_init(void) @@ -154,9 +198,6 @@ my_bool my_thread_init(void) #ifdef EXTRA_DEBUG_THREADS fprintf(stderr,"my_thread_init(): thread_id=%ld\n",pthread_self()); #endif -#if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX) - pthread_mutex_lock(&THR_LOCK_lock); -#endif #if !defined(__WIN__) || defined(USE_TLS) if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys)) @@ -174,7 +215,7 @@ my_bool my_thread_init(void) } pthread_setspecific(THR_KEY_mysys,tmp); -#else +#else /* defined(__WIN__) && !(defined(USE_TLS) */ /* Skip initialization if the thread specific variable is already initialized */ @@ -182,7 +223,6 @@ my_bool my_thread_init(void) goto end; tmp= &THR_KEY_mysys; #endif - tmp->id= ++thread_id; #if defined(__WIN__) && defined(EMBEDDED_LIBRARY) tmp->thread_self= (pthread_t)getpid(); #endif @@ -190,22 +230,35 @@ my_bool my_thread_init(void) pthread_cond_init(&tmp->suspend, NULL); tmp->init= 1; + pthread_mutex_lock(&THR_LOCK_threads); + tmp->id= ++thread_id; + ++THR_thread_count; + pthread_mutex_unlock(&THR_LOCK_threads); end: -#if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX) - pthread_mutex_unlock(&THR_LOCK_lock); -#endif return error; } +/* + Deallocate memory used by the thread for book-keeping + + SYNOPSIS + my_thread_end() + + NOTE + This may be called multiple times for a thread. + This happens for example when one calls 'mysql_server_init()' + mysql_server_end() and then ends with a mysql_end(). +*/ + void my_thread_end(void) { struct st_my_thread_var *tmp; tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); #ifdef EXTRA_DEBUG_THREADS - fprintf(stderr,"my_thread_end(): tmp=%p,thread_id=%ld\n", - tmp,pthread_self()); + fprintf(stderr,"my_thread_end(): tmp: 0x%lx thread_id=%ld\n", + (long) tmp, pthread_self()); #endif if (tmp && tmp->init) { @@ -227,6 +280,18 @@ void my_thread_end(void) #else tmp->init= 0; #endif + + /* + Decrement counter for number of running threads. We are using this + in my_thread_global_end() to wait until all threads have called + my_thread_end and thus freed all memory they have allocated in + my_thread_init() and DBUG_xxxx + */ + pthread_mutex_lock(&THR_LOCK_threads); + DBUG_ASSERT(THR_thread_count != 0); + if (--THR_thread_count == 0) + pthread_cond_signal(&THR_COND_threads); + pthread_mutex_unlock(&THR_LOCK_threads); } /* The following free has to be done, even if my_thread_var() is 0 */ #if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS) diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c index 8c497e8f250..b56dacc135a 100644 --- a/mysys/my_wincond.c +++ b/mysys/my_wincond.c @@ -37,7 +37,7 @@ int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) int pthread_cond_destroy(pthread_cond_t *cond) { - return CloseHandle(cond->semaphore) ? 0 : EINVAL; + return CloseHandle(cond->semaphore) ? 0 : EINVAL; } @@ -51,20 +51,37 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) return 0 ; } + int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *abstime) { - struct _timeb curtime; int result; - long timeout; - _ftime(&curtime); - timeout= ((long) (abstime->tv_sec - curtime.time)*1000L + - (long)((abstime->tv_nsec/1000) - curtime.millitm)/1000L); - if (timeout < 0) /* Some safety */ - timeout = 0L; + long timeout; + union ft64 now; + + GetSystemTimeAsFileTime(&now.ft); + + /* + Calculate time left to abstime + - subtract start time from current time(values are in 100ns units) + - convert to millisec by dividing with 10000 + */ + timeout= (long)((abstime->tv.i64 - now.i64) / 10000); + + /* Don't allow the timeout to be negative */ + if (timeout < 0) + timeout= 0L; + + /* + Make sure the calucated timeout does not exceed original timeout + value which could cause "wait for ever" if system time changes + */ + if (timeout > abstime->max_timeout_msec) + timeout= abstime->max_timeout_msec; + InterlockedIncrement(&cond->waiting); LeaveCriticalSection(mutex); - result=WaitForSingleObject(cond->semaphore,timeout); + result= WaitForSingleObject(cond->semaphore,timeout); InterlockedDecrement(&cond->waiting); EnterCriticalSection(mutex); diff --git a/mysys/my_write.c b/mysys/my_write.c index ae8cb4ab02b..26b9a4f2444 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -27,7 +27,7 @@ uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags) ulong written; DBUG_ENTER("my_write"); DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %d MyFlags: %d", - Filedes, Buffer, Count, MyFlags)); + Filedes, (long) Buffer, Count, MyFlags)); errors=0; written=0L; for (;;) diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index f6d6644859e..b3466e36197 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -194,7 +194,7 @@ gptr _mymalloc(uint size, const char *filename, uint lineno, myf MyFlags) if ((MyFlags & MY_ZEROFILL) || !sf_malloc_quick) bfill(data, size, (char) (MyFlags & MY_ZEROFILL ? 0 : ALLOC_VAL)); /* Return a pointer to the real data */ - DBUG_PRINT("exit",("ptr: 0x%lx", data)); + DBUG_PRINT("exit",("ptr: 0x%lx", (long) data)); if (sf_min_adress > data) sf_min_adress= data; if (sf_max_adress < data) @@ -259,7 +259,7 @@ void _myfree(gptr ptr, const char *filename, uint lineno, myf myflags) { struct st_irem *irem; DBUG_ENTER("_myfree"); - DBUG_PRINT("enter",("ptr: 0x%lx", ptr)); + DBUG_PRINT("enter",("ptr: 0x%lx", (long) ptr)); if (!sf_malloc_quick) (void) _sanity (filename, lineno); @@ -410,7 +410,7 @@ void TERMINATE(FILE *file) } DBUG_PRINT("safe", ("%6u bytes at 0x%09lx, allocated at line %4d in '%s'", - irem->datasize, data, irem->linenum, irem->filename)); + irem->datasize, (long) data, irem->linenum, irem->filename)); irem= irem->next; } } @@ -447,7 +447,7 @@ static int _checkchunk(register struct st_irem *irem, const char *filename, fprintf(stderr, " discovered at %s:%d\n", filename, lineno); (void) fflush(stderr); DBUG_PRINT("safe",("Underrun at 0x%lx, allocated at %s:%d", - data, irem->filename, irem->linenum)); + (long) data, irem->filename, irem->linenum)); flag=1; } @@ -463,7 +463,7 @@ static int _checkchunk(register struct st_irem *irem, const char *filename, fprintf(stderr, " discovered at '%s:%d'\n", filename, lineno); (void) fflush(stderr); DBUG_PRINT("safe",("Overrun at 0x%lx, allocated at %s:%d", - data, + (long) data, irem->filename, irem->linenum)); flag=1; diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 51df50a4926..66848b94651 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -483,8 +483,8 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, data->owner= owner; /* Must be reset ! */ VOID(pthread_mutex_lock(&lock->mutex)); DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx type: %d", - data, data->owner->info->thread_id, - lock, (int) lock_type)); + (long) data, data->owner->info->thread_id, + (long) lock, (int) lock_type)); check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ? "enter read_lock" : "enter write_lock",0); if ((int) lock_type <= (int) TL_READ_NO_INSERT) @@ -659,7 +659,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, goto end; } } - DBUG_PRINT("lock",("write locked by thread: %ld, type: %ld", + DBUG_PRINT("lock",("write locked by thread: %ld, type: %d", lock->read.data->owner->info->thread_id, data->type)); } wait_queue= &lock->write_wait; @@ -740,7 +740,7 @@ void thr_unlock(THR_LOCK_DATA *data) enum thr_lock_type lock_type=data->type; DBUG_ENTER("thr_unlock"); DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx", - data, data->owner->info->thread_id, lock)); + (long) data, data->owner->info->thread_id, (long) lock)); pthread_mutex_lock(&lock->mutex); check_locks(lock,"start of release lock",0); @@ -913,7 +913,7 @@ thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner) { THR_LOCK_DATA **pos,**end; DBUG_ENTER("thr_multi_lock"); - DBUG_PRINT("lock",("data: 0x%lx count: %d",data,count)); + DBUG_PRINT("lock",("data: 0x%lx count: %d", (long) data, count)); if (count > 1) sort_locks(data,count); /* lock everything */ @@ -986,7 +986,7 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count) { THR_LOCK_DATA **pos,**end; DBUG_ENTER("thr_multi_unlock"); - DBUG_PRINT("lock",("data: 0x%lx count: %d",data,count)); + DBUG_PRINT("lock",("data: 0x%lx count: %d", (long) data, count)); for (pos=data,end=data+count; pos < end ; pos++) { @@ -1000,7 +1000,8 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count) else { DBUG_PRINT("lock",("Free lock: data: 0x%lx thread: %ld lock: 0x%lx", - *pos, (*pos)->owner->info->thread_id, (*pos)->lock)); + (long) *pos, (*pos)->owner->info->thread_id, + (long) (*pos)->lock)); } } DBUG_VOID_RETURN; diff --git a/mysys/tree.c b/mysys/tree.c index 0c9c04919b0..f295fa15575 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -84,12 +84,12 @@ static void rb_delete_fixup(TREE *tree,TREE_ELEMENT ***parent); static int test_rb_tree(TREE_ELEMENT *element); #endif -void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit, +void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit, int size, qsort_cmp2 compare, my_bool with_delete, tree_element_free free_element, void *custom_arg) { DBUG_ENTER("init_tree"); - DBUG_PRINT("enter",("tree: 0x%lx size: %d",tree,size)); + DBUG_PRINT("enter",("tree: 0x%lx size: %d", (long) tree, size)); if (default_alloc_size < DEFAULT_ALLOC_SIZE) default_alloc_size= DEFAULT_ALLOC_SIZE; @@ -128,7 +128,7 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit, } if (!(tree->with_delete=with_delete)) { - init_alloc_root(&tree->mem_root, default_alloc_size,0); + init_alloc_root(&tree->mem_root, (uint) default_alloc_size, 0); tree->mem_root.min_malloc=(sizeof(TREE_ELEMENT)+tree->size_of_element); } DBUG_VOID_RETURN; @@ -137,7 +137,7 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit, static void free_tree(TREE *tree, myf free_flags) { DBUG_ENTER("free_tree"); - DBUG_PRINT("enter",("tree: 0x%lx",tree)); + DBUG_PRINT("enter",("tree: 0x%lx", (long) tree)); if (tree->root) /* If initialized */ { diff --git a/mysys/typelib.c b/mysys/typelib.c index 230a2989cbd..8906b702aa8 100644 --- a/mysys/typelib.c +++ b/mysys/typelib.c @@ -49,7 +49,7 @@ int find_type(my_string x, TYPELIB *typelib, uint full_name) reg1 my_string i; reg2 const char *j; DBUG_ENTER("find_type"); - DBUG_PRINT("enter",("x: '%s' lib: 0x%lx",x,typelib)); + DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", x, (long) typelib)); if (!typelib->count) { diff --git a/ndb/config/type_kernel.mk.am b/ndb/config/type_kernel.mk.am index 703876ee2e9..ccb01709dfb 100644 --- a/ndb/config/type_kernel.mk.am +++ b/ndb/config/type_kernel.mk.am @@ -1,6 +1,9 @@ INCLUDES += \ - -I$(srcdir) -I$(top_srcdir)/include \ + -I$(srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/ndb/include \ -I$(top_srcdir)/ndb/src/kernel/vm \ -I$(top_srcdir)/ndb/src/kernel/error \ diff --git a/ndb/config/type_ndbapi.mk.am b/ndb/config/type_ndbapi.mk.am index ab84c683e86..18bc536fdee 100644 --- a/ndb/config/type_ndbapi.mk.am +++ b/ndb/config/type_ndbapi.mk.am @@ -1,6 +1,9 @@ INCLUDES += \ - -I$(srcdir) -I$(top_srcdir)/include \ + -I$(srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/mysys \ -I$(top_srcdir)/ndb/include \ -I$(top_srcdir)/ndb/include/kernel \ diff --git a/ndb/config/type_ndbapitest.mk.am b/ndb/config/type_ndbapitest.mk.am index 392c4e9fc70..e9a383eaad7 100644 --- a/ndb/config/type_ndbapitest.mk.am +++ b/ndb/config/type_ndbapitest.mk.am @@ -5,7 +5,10 @@ LDADD += $(top_builddir)/ndb/test/src/libNDBT.a \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ -INCLUDES += -I$(top_srcdir) -I$(top_srcdir)/include \ +INCLUDES += -I$(top_srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/ndb/include \ -I$(top_srcdir)/ndb/include/ndbapi \ -I$(top_srcdir)/ndb/include/util \ diff --git a/ndb/config/type_ndbapitools.mk.am b/ndb/config/type_ndbapitools.mk.am index d4eb090112d..3c5510880d4 100644 --- a/ndb/config/type_ndbapitools.mk.am +++ b/ndb/config/type_ndbapitools.mk.am @@ -5,7 +5,10 @@ LDADD += \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ -INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \ +INCLUDES += -I$(srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/ndb/include \ -I$(top_srcdir)/ndb/include/ndbapi \ -I$(top_srcdir)/ndb/include/util \ diff --git a/ndb/config/type_util.mk.am b/ndb/config/type_util.mk.am index 4f2d605dc91..de250ae1f43 100644 --- a/ndb/config/type_util.mk.am +++ b/ndb/config/type_util.mk.am @@ -1,5 +1,7 @@ INCLUDES += -I$(srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/ndb/include \ -I$(top_srcdir)/include \ -I$(top_srcdir)/mysys \ -I$(top_srcdir)/ndb/include \ diff --git a/ndb/include/logger/LogHandler.hpp b/ndb/include/logger/LogHandler.hpp index 8b9aa43d7a9..efb87bb3104 100644 --- a/ndb/include/logger/LogHandler.hpp +++ b/ndb/include/logger/LogHandler.hpp @@ -135,7 +135,7 @@ public: * * @param str the error string. */ - void setErrorStr(char* str); + void setErrorStr(const char* str); /** * Parse logstring parameters diff --git a/ndb/include/ndb_global.h.in b/ndb/include/ndb_global.h.in index 122b0edc400..f1eed73f71a 100644 --- a/ndb/include/ndb_global.h.in +++ b/ndb/include/ndb_global.h.in @@ -132,4 +132,10 @@ extern "C" { #define PATH_MAX 1024 #endif +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) +#define LINT_SET_PTR = {0,0} +#else +#define LINT_SET_PTR +#endif + #endif diff --git a/ndb/include/ndbapi/ndberror.h b/ndb/include/ndbapi/ndberror.h index 2225f68f08d..4d4eddfe617 100644 --- a/ndb/include/ndbapi/ndberror.h +++ b/ndb/include/ndbapi/ndberror.h @@ -93,7 +93,7 @@ typedef ndberror_classification_enum ndberror_classification; const char *ndberror_status_message(ndberror_status); const char *ndberror_classification_message(ndberror_classification); void ndberror_update(ndberror_struct *); -int ndb_error_string(int err_no, char *str, unsigned int size); +int ndb_error_string(int err_no, char *str, int size); #endif /* doxygen skip internal*/ diff --git a/ndb/include/util/InputStream.hpp b/ndb/include/util/InputStream.hpp index 4d7d06aeaa3..56c43686df1 100644 --- a/ndb/include/util/InputStream.hpp +++ b/ndb/include/util/InputStream.hpp @@ -25,6 +25,7 @@ */ class InputStream { public: + virtual ~InputStream() {} virtual char* gets(char * buf, int bufLen) = 0; }; diff --git a/ndb/include/util/OutputStream.hpp b/ndb/include/util/OutputStream.hpp index c7e009d4537..a834b577bb3 100644 --- a/ndb/include/util/OutputStream.hpp +++ b/ndb/include/util/OutputStream.hpp @@ -25,6 +25,7 @@ */ class OutputStream { public: + virtual ~OutputStream() {} virtual int print(const char * fmt, ...) = 0; virtual int println(const char * fmt, ...) = 0; virtual void flush() {}; diff --git a/ndb/include/util/SimpleProperties.hpp b/ndb/include/util/SimpleProperties.hpp index 438426fb62b..b29e65e21da 100644 --- a/ndb/include/util/SimpleProperties.hpp +++ b/ndb/include/util/SimpleProperties.hpp @@ -151,6 +151,7 @@ public: ValueType m_type; protected: Reader(); + virtual ~Reader() {} virtual void reset() = 0; virtual bool step(Uint32 len) = 0; @@ -169,6 +170,7 @@ public: bool add(Uint16 key, const char * value); bool add(Uint16 key, const void* value, int len); protected: + virtual ~Writer() {} virtual bool reset() = 0; virtual bool putWord(Uint32 val) = 0; virtual bool putWords(const Uint32 * src, Uint32 len) = 0; @@ -184,6 +186,7 @@ class SimplePropertiesLinearReader : public SimpleProperties::Reader { public: SimplePropertiesLinearReader(const Uint32 * src, Uint32 len); + virtual ~SimplePropertiesLinearReader() {} virtual void reset(); virtual bool step(Uint32 len); virtual bool getWord(Uint32 * dst); @@ -202,6 +205,7 @@ class LinearWriter : public SimpleProperties::Writer { public: LinearWriter(Uint32 * src, Uint32 len); + virtual ~LinearWriter() {} virtual bool reset(); virtual bool putWord(Uint32 val); virtual bool putWords(const Uint32 * src, Uint32 len); @@ -219,6 +223,7 @@ class UtilBufferWriter : public SimpleProperties::Writer { public: UtilBufferWriter(class UtilBuffer & buf); + virtual ~UtilBufferWriter() {} virtual bool reset(); virtual bool putWord(Uint32 val); virtual bool putWords(const Uint32 * src, Uint32 len); @@ -238,6 +243,7 @@ public: SimplePropertiesSectionReader(struct SegmentedSectionPtr &, class SectionSegmentPool &); + virtual ~SimplePropertiesSectionReader() {} virtual void reset(); virtual bool step(Uint32 len); virtual bool getWord(Uint32 * dst); @@ -270,6 +276,7 @@ class SimplePropertiesSectionWriter : public SimpleProperties::Writer { public: SimplePropertiesSectionWriter(class SectionSegmentPool &); + virtual ~SimplePropertiesSectionWriter() {} virtual bool reset(); virtual bool putWord(Uint32 val); virtual bool putWords(const Uint32 * src, Uint32 len); diff --git a/ndb/src/common/debugger/EventLogger.cpp b/ndb/src/common/debugger/EventLogger.cpp index c6f02a7807a..8027a6bd347 100644 --- a/ndb/src/common/debugger/EventLogger.cpp +++ b/ndb/src/common/debugger/EventLogger.cpp @@ -116,8 +116,7 @@ void getTextNDBStopForced(QQQQ) { int sphase = theData[4]; int extra = theData[5]; getRestartAction(theData[1],action_str); - if (signal) - reason_str.appfmt(" Initiated by signal %d.", signum); + reason_str.appfmt(" Initiated by signal %d.", signum); if (error) { ndbd_exit_classification cl; diff --git a/ndb/src/common/debugger/signaldata/BackupSignalData.cpp b/ndb/src/common/debugger/signaldata/BackupSignalData.cpp index 27fed22ac72..7410db44aa3 100644 --- a/ndb/src/common/debugger/signaldata/BackupSignalData.cpp +++ b/ndb/src/common/debugger/signaldata/BackupSignalData.cpp @@ -124,6 +124,9 @@ printABORT_BACKUP_ORD(FILE * out, const Uint32 * data, Uint32 len, Uint16 b){ sig->backupPtr, sig->backupId); return true; break; + case AbortBackupOrd::AbortScan: + case AbortBackupOrd::IncompatibleVersions: + return false; } return false; } diff --git a/ndb/src/common/logger/LogHandler.cpp b/ndb/src/common/logger/LogHandler.cpp index c11f962d4fb..47333f81812 100644 --- a/ndb/src/common/logger/LogHandler.cpp +++ b/ndb/src/common/logger/LogHandler.cpp @@ -164,9 +164,9 @@ LogHandler::getErrorStr() } void -LogHandler::setErrorStr(char* str) +LogHandler::setErrorStr(const char* str) { - m_errorStr= str; + m_errorStr= (char*) str; } bool diff --git a/ndb/src/common/portlib/NdbMutex.c b/ndb/src/common/portlib/NdbMutex.c index 4a170d87e5c..f0a1614ba8e 100644 --- a/ndb/src/common/portlib/NdbMutex.c +++ b/ndb/src/common/portlib/NdbMutex.c @@ -28,7 +28,7 @@ NdbMutex* NdbMutex_Create(void) DBUG_ENTER("NdbMutex_Create"); pNdbMutex = (NdbMutex*)NdbMem_Allocate(sizeof(NdbMutex)); - DBUG_PRINT("info",("NdbMem_Allocate 0x%lx",pNdbMutex)); + DBUG_PRINT("info",("NdbMem_Allocate 0x%lx", (long) pNdbMutex)); if (pNdbMutex == NULL) DBUG_RETURN(NULL); @@ -50,7 +50,7 @@ int NdbMutex_Destroy(NdbMutex* p_mutex) result = pthread_mutex_destroy(p_mutex); - DBUG_PRINT("info",("NdbMem_Free 0x%lx",p_mutex)); + DBUG_PRINT("info",("NdbMem_Free 0x%lx", (long) p_mutex)); NdbMem_Free(p_mutex); DBUG_RETURN(result); diff --git a/ndb/src/common/portlib/NdbThread.c b/ndb/src/common/portlib/NdbThread.c index 48d00956ec2..67c8f6faf50 100644 --- a/ndb/src/common/portlib/NdbThread.c +++ b/ndb/src/common/portlib/NdbThread.c @@ -122,7 +122,7 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func, assert(result==0); pthread_attr_destroy(&thread_attr); - DBUG_PRINT("exit",("ret: %lx", tmpThread)); + DBUG_PRINT("exit",("ret: 0x%lx", (long) tmpThread)); DBUG_RETURN(tmpThread); } @@ -131,7 +131,7 @@ void NdbThread_Destroy(struct NdbThread** p_thread) { DBUG_ENTER("NdbThread_Destroy"); if (*p_thread != NULL){ - DBUG_PRINT("enter",("*p_thread: %lx", * p_thread)); + DBUG_PRINT("enter",("*p_thread: 0x%lx", (long) *p_thread)); free(* p_thread); * p_thread = 0; } diff --git a/ndb/src/common/transporter/Transporter.cpp b/ndb/src/common/transporter/Transporter.cpp index 383456f1077..b2ee75e4754 100644 --- a/ndb/src/common/transporter/Transporter.cpp +++ b/ndb/src/common/transporter/Transporter.cpp @@ -39,8 +39,8 @@ Transporter::Transporter(TransporterRegistry &t_reg, int _byteorder, bool _compression, bool _checksum, bool _signalId) : m_s_port(s_port), remoteNodeId(rNodeId), localNodeId(lNodeId), - isServer(lNodeId==serverNodeId), isMgmConnection(_isMgmConnection), - m_packer(_signalId, _checksum), + isServer(lNodeId==serverNodeId), + m_packer(_signalId, _checksum), isMgmConnection(_isMgmConnection), m_type(_type), m_transporter_registry(t_reg) { diff --git a/ndb/src/common/util/File.cpp b/ndb/src/common/util/File.cpp index 056b7ff199b..33d6ca1d535 100644 --- a/ndb/src/common/util/File.cpp +++ b/ndb/src/common/util/File.cpp @@ -123,13 +123,25 @@ bool File_class::close() { bool rc = true; + int retval = 0; + if (m_file != NULL) { ::fflush(m_file); - rc = (::fclose(m_file) == 0 ? true : false); - m_file = NULL; // Try again? + retval = ::fclose(m_file); + while ( (retval != 0) && (errno == EINTR) ){ + retval = ::fclose(m_file); + } + if( retval == 0){ + rc = true; + } + else { + rc = false; + ndbout_c("ERROR: Close file error in File.cpp for %s",strerror(errno)); + } } - + m_file = NULL; + return rc; } diff --git a/ndb/src/common/util/InputStream.cpp b/ndb/src/common/util/InputStream.cpp index 1b0e809a047..adeca127eb5 100644 --- a/ndb/src/common/util/InputStream.cpp +++ b/ndb/src/common/util/InputStream.cpp @@ -65,6 +65,5 @@ SocketInputStream::gets(char * buf, int bufLen) { if(res == -1) return 0; - return buf; } diff --git a/ndb/src/common/util/NdbSqlUtil.cpp b/ndb/src/common/util/NdbSqlUtil.cpp index f3d70a5734a..ba451c4dd8b 100644 --- a/ndb/src/common/util/NdbSqlUtil.cpp +++ b/ndb/src/common/util/NdbSqlUtil.cpp @@ -136,7 +136,7 @@ NdbSqlUtil::m_typeList[] = { }, { // 22 Type::Bit, - NULL, + cmpBit, NULL }, { // 23 @@ -679,6 +679,17 @@ NdbSqlUtil::cmpText(const void* info, const void* p1, unsigned n1, const void* p } int +NdbSqlUtil::cmpBit(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full) +{ + Uint32 n = (n1 < n2) ? n1 : n2; + char* c1 = (char*)p1; + char* c2 = (char*)p2; + int ret = memcmp(p1, p2, n); + return ret; +} + + +int NdbSqlUtil::cmpTime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full) { if (n2 >= 3) { @@ -698,12 +709,6 @@ NdbSqlUtil::cmpTime(const void* info, const void* p1, unsigned n1, const void* p } // not yet -int -NdbSqlUtil::cmpBit(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full) -{ - assert(false); - return 0; -} int NdbSqlUtil::cmpLongvarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full) diff --git a/ndb/src/common/util/socket_io.cpp b/ndb/src/common/util/socket_io.cpp index ba2794e4374..9401d1cd6d0 100644 --- a/ndb/src/common/util/socket_io.cpp +++ b/ndb/src/common/util/socket_io.cpp @@ -53,10 +53,6 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis, if(buflen <= 1) return 0; - int sock_flags= fcntl(socket, F_GETFL); - if(fcntl(socket, F_SETFL, sock_flags | O_NONBLOCK) == -1) - return -1; - fd_set readset; FD_ZERO(&readset); FD_SET(socket, &readset); @@ -71,43 +67,70 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis, } if(selectRes == -1){ - fcntl(socket, F_SETFL, sock_flags); return -1; } - const int t = recv(socket, buf, buflen, MSG_PEEK); - - if(t < 1) + char* ptr = buf; + int len = buflen; + do { - fcntl(socket, F_SETFL, sock_flags); - return -1; - } + int t; + while((t = recv(socket, ptr, len, MSG_PEEK)) == -1 && errno == EINTR); + + if(t < 1) + { + return -1; + } - for(int i=0; i< t;i++) - { - if(buf[i] == '\n'){ - int r= recv(socket, buf, i+1, 0); - buf[i+1]= 0; - if(r < 1) { - fcntl(socket, F_SETFL, sock_flags); - return -1; + + for(int i = 0; i<t; i++) + { + if(ptr[i] == '\n') + { + /** + * Now consume + */ + for (len = 1 + i; len; ) + { + while ((t = recv(socket, ptr, len, 0)) == -1 && errno == EINTR); + if (t < 1) + return -1; + ptr += t; + len -= t; + } + if (i > 0 && buf[i-1] == '\r') + { + buf[i-1] = '\n'; + ptr--; + } + ptr[0]= 0; + return ptr - buf; } - - if(i > 0 && buf[i-1] == '\r'){ - buf[i-1] = '\n'; - buf[i]= '\0'; + } + + for (int tmp = t; tmp; ) + { + while ((t = recv(socket, ptr, tmp, 0)) == -1 && errno == EINTR); + if (t < 1) + { + return -1; } - - fcntl(socket, F_SETFL, sock_flags); - return r; + ptr += t; + len -= t; + tmp -= t; } - } - int r= recv(socket, buf, t, 0); - if(r>=0) - buf[r] = 0; - fcntl(socket, F_SETFL, sock_flags); - return r; + FD_ZERO(&readset); + FD_SET(socket, &readset); + timeout.tv_sec = (timeout_millis / 1000); + timeout.tv_usec = (timeout_millis % 1000) * 1000; + const int selectRes = select(socket + 1, &readset, 0, 0, &timeout); + if(selectRes != 1){ + return -1; + } + } while (len > 0); + + return -1; } extern "C" diff --git a/ndb/src/cw/cpcd/CPCD.hpp b/ndb/src/cw/cpcd/CPCD.hpp index aecc43150c4..3a69a03aa3f 100644 --- a/ndb/src/cw/cpcd/CPCD.hpp +++ b/ndb/src/cw/cpcd/CPCD.hpp @@ -63,6 +63,7 @@ struct CPCEvent { struct EventSubscriber { virtual void report(const CPCEvent &) = 0; + virtual ~EventSubscriber() {} }; /** diff --git a/ndb/src/kernel/Makefile.am b/ndb/src/kernel/Makefile.am index 389cb85c1d8..6e075f0f248 100644 --- a/ndb/src/kernel/Makefile.am +++ b/ndb/src/kernel/Makefile.am @@ -9,21 +9,21 @@ ndbd_SOURCES = main.cpp SimBlockList.cpp include $(top_srcdir)/ndb/config/type_kernel.mk.am INCLUDES += \ - -Iblocks/cmvmi \ - -Iblocks/dbacc \ - -Iblocks/dbdict \ - -Iblocks/dbdih \ - -Iblocks/dblqh \ - -Iblocks/dbtc \ - -Iblocks/dbtup \ - -Iblocks/ndbfs \ - -Iblocks/ndbcntr \ - -Iblocks/qmgr \ - -Iblocks/trix \ - -Iblocks/backup \ - -Iblocks/dbutil \ - -Iblocks/suma \ - -Iblocks/dbtux + -I$(srcdir)/blocks/cmvmi \ + -I$(srcdir)/blocks/dbacc \ + -I$(srcdir)/blocks/dbdict \ + -I$(srcdir)/blocks/dbdih \ + -I$(srcdir)/blocks/dblqh \ + -I$(srcdir)/blocks/dbtc \ + -I$(srcdir)/blocks/dbtup \ + -I$(srcdir)/blocks/ndbfs \ + -I$(srcdir)/blocks/ndbcntr \ + -I$(srcdir)/blocks/qmgr \ + -I$(srcdir)/blocks/trix \ + -I$(srcdir)/blocks/backup \ + -I$(srcdir)/blocks/dbutil \ + -I$(srcdir)/blocks/suma \ + -I$(srcdir)/blocks/dbtux LDADD += \ blocks/cmvmi/libcmvmi.a \ diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt index 74d5df2c1e6..16f5da8a553 100644 --- a/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/ndb/src/kernel/blocks/ERROR_codes.txt @@ -6,7 +6,7 @@ Next DBTUP 4014 Next DBLQH 5043 Next DBDICT 6007 Next DBDIH 7178 -Next DBTC 8038 +Next DBTC 8039 Next CMVMI 9000 Next BACKUP 10022 Next DBUTIL 11002 @@ -287,6 +287,11 @@ ABORT OF TCKEYREQ 8037 : Invalid schema version in TCINDXREQ +------ + +8038 : Simulate API disconnect just after SCAN_TAB_REQ + + CMVMI ----- 9000 Set RestartOnErrorInsert to restart -n diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index b00b1169095..8f3f6ffe55c 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -272,7 +272,7 @@ Backup::execCONTINUEB(Signal* signal) Uint32 tabPtr_I = Tdata2; Uint32 fragPtr_I = signal->theData[3]; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptr_I); if (tabPtr_I == RNIL) @@ -309,7 +309,7 @@ Backup::execCONTINUEB(Signal* signal) fragInfo->NoOfRecordsLow = htonl(fragPtr.p->noOfRecords & 0xFFFFFFFF); fragInfo->NoOfRecordsHigh = htonl(fragPtr.p->noOfRecords >> 32); fragInfo->FilePosLow = htonl(0 & 0xFFFFFFFF); - fragInfo->FilePosHigh = htonl(0 >> 32); + fragInfo->FilePosHigh = htonl(0); filePtr.p->operation.dataBuffer.updateWritePtr(sz); @@ -341,7 +341,7 @@ Backup::execCONTINUEB(Signal* signal) case BackupContinueB::BUFFER_UNDERFLOW: { jam(); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, Tdata1); checkFile(signal, filePtr); return; @@ -350,7 +350,7 @@ Backup::execCONTINUEB(Signal* signal) case BackupContinueB::BUFFER_FULL_SCAN: { jam(); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, Tdata1); checkScan(signal, filePtr); return; @@ -359,7 +359,7 @@ Backup::execCONTINUEB(Signal* signal) case BackupContinueB::BUFFER_FULL_FRAG_COMPLETE: { jam(); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, Tdata1); fragmentCompleted(signal, filePtr); return; @@ -368,7 +368,7 @@ Backup::execCONTINUEB(Signal* signal) case BackupContinueB::BUFFER_FULL_META: { jam(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, Tdata1); BackupFilePtr filePtr; @@ -377,7 +377,7 @@ Backup::execCONTINUEB(Signal* signal) if(buf.getFreeSize() + buf.getMinRead() < buf.getUsableSize()) { jam(); - TablePtr tabPtr; + TablePtr tabPtr LINT_SET_PTR; c_tablePool.getPtr(tabPtr, Tdata2); DEBUG_OUT("Backup - Buffer full - " << buf.getFreeSize() @@ -392,7 +392,7 @@ Backup::execCONTINUEB(Signal* signal) return; }//if - TablePtr tabPtr; + TablePtr tabPtr LINT_SET_PTR; c_tablePool.getPtr(tabPtr, Tdata2); GetTabInfoReq * req = (GetTabInfoReq *)signal->getDataPtrSend(); req->senderRef = reference(); @@ -912,6 +912,9 @@ Backup::checkNodeFail(Signal* signal, #endif Uint32 gsn, len, pos; + LINT_INIT(gsn); + LINT_INIT(len); + LINT_INIT(pos); ptr.p->nodes.bitANDC(mask); switch(ptr.p->masterData.gsn){ case GSN_DEFINE_BACKUP_REQ: @@ -1099,7 +1102,7 @@ Backup::execBACKUP_REQ(Signal* signal) void Backup::execUTIL_SEQUENCE_REF(Signal* signal) { - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; jamEntry(); UtilSequenceRef * utilRef = (UtilSequenceRef*)signal->getDataPtr(); ptr.i = utilRef->senderData; @@ -1153,7 +1156,7 @@ Backup::execUTIL_SEQUENCE_CONF(Signal* signal) return; } - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; ptr.i = conf->senderData; c_backupPool.getPtr(ptr); @@ -1194,7 +1197,7 @@ Backup::defineBackupMutex_locked(Signal* signal, Uint32 ptrI, Uint32 retVal){ jamEntry(); ndbrequire(retVal == 0); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; ptr.i = ptrI; c_backupPool.getPtr(ptr); @@ -1215,7 +1218,7 @@ Backup::dictCommitTableMutex_locked(Signal* signal, Uint32 ptrI,Uint32 retVal) /** * We now have both the mutexes */ - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; ptr.i = ptrI; c_backupPool.getPtr(ptr); @@ -1320,7 +1323,7 @@ Backup::execDEFINE_BACKUP_REF(Signal* signal) //const Uint32 backupId = ref->backupId; const Uint32 nodeId = ref->nodeId; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); ptr.p->setErrorCode(ref->errorCode); @@ -1337,7 +1340,7 @@ Backup::execDEFINE_BACKUP_CONF(Signal* signal) //const Uint32 backupId = conf->backupId; const Uint32 nodeId = refToNode(signal->senderBlockRef()); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); if (ERROR_INSERTED(10024)) @@ -1508,7 +1511,7 @@ Backup::execCREATE_TRIG_REF(Signal* signal) const Uint32 ptrI = ref->getConnectionPtr(); const Uint32 tableId = ref->getTableId(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); /** @@ -1623,7 +1626,7 @@ Backup::execSTART_BACKUP_REF(Signal* signal) const Uint32 signalNo = ref->signalNo; const Uint32 nodeId = ref->nodeId; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); ptr.p->setErrorCode(ref->errorCode); @@ -1641,7 +1644,7 @@ Backup::execSTART_BACKUP_CONF(Signal* signal) const Uint32 signalNo = conf->signalNo; const Uint32 nodeId = refToNode(signal->senderBlockRef()); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); startBackupReply(signal, ptr, nodeId, signalNo); @@ -1671,7 +1674,7 @@ Backup::startBackupReply(Signal* signal, BackupRecordPtr ptr, return; } - TablePtr tabPtr; + TablePtr tabPtr LINT_SET_PTR; c_tablePool.getPtr(tabPtr, ptr.p->masterData.startBackup.tablePtr); for(Uint32 i = 0; i<StartBackupReq::MaxTableTriggers; i++) { jam(); @@ -1765,7 +1768,7 @@ Backup::execALTER_TRIG_CONF(Signal* signal) AlterTrigConf* conf = (AlterTrigConf*)signal->getDataPtr(); const Uint32 ptrI = conf->getConnectionPtr(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); alterTrigReply(signal, ptr); @@ -1779,7 +1782,7 @@ Backup::execALTER_TRIG_REF(Signal* signal) AlterTrigRef* ref = (AlterTrigRef*)signal->getDataPtr(); const Uint32 ptrI = ref->getConnectionPtr(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); ptr.p->setErrorCode(ref->getErrorCode()); @@ -1823,7 +1826,7 @@ Backup::execWAIT_GCP_REF(Signal* signal) WaitGCPRef * ref = (WaitGCPRef*)signal->getDataPtr(); const Uint32 ptrI = ref->senderData; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); ndbrequire(ptr.p->masterRef == reference()); @@ -1847,7 +1850,7 @@ Backup::execWAIT_GCP_CONF(Signal* signal){ const Uint32 ptrI = conf->senderData; const Uint32 gcp = conf->gcp; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); ndbrequire(ptr.p->masterRef == reference()); @@ -2057,7 +2060,7 @@ Backup::execBACKUP_FRAGMENT_REF(Signal* signal) //const Uint32 backupId = ref->backupId; const Uint32 nodeId = ref->nodeId; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); TablePtr tabPtr; @@ -2206,7 +2209,7 @@ Backup::execDROP_TRIG_REF(Signal* signal) DropTrigRef* ref = (DropTrigRef*)signal->getDataPtr(); const Uint32 ptrI = ref->getConnectionPtr(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); //ndbrequire(ref->getErrorCode() == DropTrigRef::NoSuchTrigger); @@ -2221,7 +2224,7 @@ Backup::execDROP_TRIG_CONF(Signal* signal) DropTrigConf* conf = (DropTrigConf*)signal->getDataPtr(); const Uint32 ptrI = conf->getConnectionPtr(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); dropTrigReply(signal, ptr); @@ -2261,7 +2264,7 @@ Backup::execSTOP_BACKUP_REF(Signal* signal) //const Uint32 backupId = ref->backupId; const Uint32 nodeId = ref->nodeId; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); ptr.p->setErrorCode(ref->errorCode); @@ -2296,7 +2299,7 @@ Backup::execSTOP_BACKUP_CONF(Signal* signal) //const Uint32 backupId = conf->backupId; const Uint32 nodeId = refToNode(signal->senderBlockRef()); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); ptr.p->noOfLogBytes += conf->noOfLogBytes; @@ -2485,7 +2488,7 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal) DefineBackupReq* req = (DefineBackupReq*)signal->getDataPtr(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; const Uint32 ptrI = req->backupPtr; const Uint32 backupId = req->backupId; const BlockReference senderRef = req->senderRef; @@ -2663,7 +2666,7 @@ Backup::execLIST_TABLES_CONF(Signal* signal) ListTablesConf* conf = (ListTablesConf*)signal->getDataPtr(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, conf->senderData); const Uint32 len = signal->length() - ListTablesConf::HeaderLength; @@ -2711,7 +2714,7 @@ Backup::openFiles(Signal* signal, BackupRecordPtr ptr) { jam(); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; FsOpenReq * req = (FsOpenReq *)signal->getDataPtrSend(); req->userReference = reference(); @@ -2776,10 +2779,10 @@ Backup::execFSOPENREF(Signal* signal) const Uint32 userPtr = ref->userPointer; - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, userPtr); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, filePtr.p->backupPtr); ptr.p->setErrorCode(ref->errorCode); openFilesReply(signal, ptr, filePtr); @@ -2795,11 +2798,11 @@ Backup::execFSOPENCONF(Signal* signal) const Uint32 userPtr = conf->userPointer; const Uint32 filePointer = conf->filePointer; - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, userPtr); filePtr.p->filePointer = filePointer; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, filePtr.p->backupPtr); ndbrequire(filePtr.p->fileOpened == 0); @@ -2957,7 +2960,7 @@ Backup::execGET_TABINFOREF(Signal* signal) GetTabInfoRef * ref = (GetTabInfoRef*)signal->getDataPtr(); const Uint32 senderData = ref->senderData; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, senderData); defineBackupRef(signal, ptr, ref->errorCode); @@ -2978,7 +2981,7 @@ Backup::execGET_TABINFO_CONF(Signal* signal) const Uint32 len = conf->totalLen; const Uint32 senderData = conf->senderData; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, senderData); SegmentedSectionPtr dictTabInfoPtr; @@ -3212,7 +3215,7 @@ Backup::execDI_FCOUNTCONF(Signal* signal) fragPtr.p->scanned = 0; fragPtr.p->scanning = 0; fragPtr.p->tableId = tableId; - fragPtr.p->node = RNIL; + fragPtr.p->node = 0; }//for /** @@ -3421,7 +3424,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal) /** * Get file */ - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr); ndbrequire(filePtr.p->backupPtr == ptrI); @@ -3553,12 +3556,12 @@ Backup::execTRANSID_AI(Signal* signal) //const Uint32 transId2 = signal->theData[2]; const Uint32 dataLen = signal->length() - 3; - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, filePtrI); OperationRecord & op = filePtr.p->operation; - TablePtr tabPtr; + TablePtr tabPtr LINT_SET_PTR; c_tablePool.getPtr(tabPtr, op.tablePtr); Table & table = * tabPtr.p; @@ -3752,7 +3755,7 @@ Backup::execSCAN_FRAGREF(Signal* signal) ScanFragRef * ref = (ScanFragRef*)signal->getDataPtr(); const Uint32 filePtrI = ref->senderData; - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, filePtrI); filePtr.p->errorCode = ref->errorCode; @@ -3771,7 +3774,7 @@ Backup::execSCAN_FRAGCONF(Signal* signal) ScanFragConf * conf = (ScanFragConf*)signal->getDataPtr(); const Uint32 filePtrI = conf->senderData; - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, filePtrI); OperationRecord & op = filePtr.p->operation; @@ -3812,7 +3815,7 @@ Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr) filePtr.p->scanRunning = 0; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, filePtr.p->backupPtr); BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtrSend(); @@ -3835,7 +3838,7 @@ Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr) void Backup::backupFragmentRef(Signal * signal, BackupFilePtr filePtr) { - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, filePtr.p->backupPtr); ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REF; @@ -3891,7 +3894,7 @@ Backup::checkScan(Signal* signal, BackupFilePtr filePtr) sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal, 10000, ScanFragNextReq::SignalLength); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, filePtr.p->backupPtr); AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend(); ord->backupId = ptr.p->backupId; @@ -3922,7 +3925,8 @@ Backup::execFSAPPENDREF(Signal* signal) const Uint32 filePtrI = ref->userPointer; const Uint32 errCode = ref->errorCode; - BackupFilePtr filePtr; + + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, filePtrI); filePtr.p->fileRunning = 0; @@ -3942,7 +3946,7 @@ Backup::execFSAPPENDCONF(Signal* signal) const Uint32 filePtrI = signal->theData[0]; //conf->userPointer; const Uint32 bytes = signal->theData[1]; //conf->bytes; - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, filePtrI); OperationRecord & op = filePtr.p->operation; @@ -4030,8 +4034,8 @@ Backup::execBACKUP_TRIG_REQ(Signal* signal) /* TUP asks if this trigger is to be fired on this node. */ - TriggerPtr trigPtr; - TablePtr tabPtr; + TriggerPtr trigPtr LINT_SET_PTR; + TablePtr tabPtr LINT_SET_PTR; FragmentPtr fragPtr; Uint32 trigger_id = signal->theData[0]; Uint32 frag_id = signal->theData[1]; @@ -4059,7 +4063,7 @@ Backup::execTRIG_ATTRINFO(Signal* signal) { TrigAttrInfo * trg = (TrigAttrInfo*)signal->getDataPtr(); - TriggerPtr trigPtr; + TriggerPtr trigPtr LINT_SET_PTR; c_triggerPool.getPtr(trigPtr, trg->getTriggerId()); ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID); // Online... @@ -4090,7 +4094,7 @@ Backup::execTRIG_ATTRINFO(Signal* signal) { jam(); Uint32 save[TrigAttrInfo::StaticLength]; memcpy(save, signal->getDataPtr(), 4*TrigAttrInfo::StaticLength); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, trigPtr.p->backupPtr); trigPtr.p->errorCode = AbortBackupOrd::LogBufferFull; AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend(); @@ -4131,7 +4135,7 @@ Backup::execFIRE_TRIG_ORD(Signal* signal) const Uint32 gci = trg->getGCI(); const Uint32 trI = trg->getTriggerId(); - TriggerPtr trigPtr; + TriggerPtr trigPtr LINT_SET_PTR; c_triggerPool.getPtr(trigPtr, trI); ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID); @@ -4144,7 +4148,7 @@ Backup::execFIRE_TRIG_ORD(Signal* signal) ndbrequire(trigPtr.p->logEntry != 0); Uint32 len = trigPtr.p->logEntry->Length; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, trigPtr.p->backupPtr); if(gci != ptr.p->currGCP) { @@ -4215,7 +4219,7 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal) /** * Get backup record */ - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); ptr.p->slaveState.setState(STOPPING); @@ -4228,6 +4232,7 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal) BackupFilePtr filePtr; ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr); Uint32 * dst; + LINT_INIT(dst); ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, 1)); * dst = 0; filePtr.p->operation.dataBuffer.updateWritePtr(1); @@ -4240,6 +4245,7 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal) const Uint32 gcpSz = sizeof(BackupFormat::CtlFile::GCPEntry) >> 2; Uint32 * dst; + LINT_INIT(dst); ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, gcpSz)); BackupFormat::CtlFile::GCPEntry * gcp = @@ -4331,7 +4337,7 @@ Backup::execFSCLOSEREF(Signal* signal) FsRef * ref = (FsRef*)signal->getDataPtr(); const Uint32 filePtrI = ref->userPointer; - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, filePtrI); BackupRecordPtr ptr; @@ -4352,7 +4358,7 @@ Backup::execFSCLOSECONF(Signal* signal) FsConf * conf = (FsConf*)signal->getDataPtr(); const Uint32 filePtrI = conf->userPointer; - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, filePtrI); #ifdef DEBUG_ABORT @@ -4366,7 +4372,7 @@ Backup::execFSCLOSECONF(Signal* signal) filePtr.p->fileOpened = 0; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, filePtr.p->backupPtr); for(ptr.p->files.first(filePtr); filePtr.i!=RNIL;ptr.p->files.next(filePtr)) { @@ -4432,7 +4438,7 @@ Backup::execABORT_BACKUP_ORD(Signal* signal) dumpUsedResources(); #endif - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; if(requestType == AbortBackupOrd::ClientAbort) { if (getOwnNodeId() != getMasterNodeId()) { jam(); @@ -4561,7 +4567,7 @@ Backup::dumpUsedResources() jam(); for(Uint32 j = 0; j<3; j++) { jam(); - TriggerPtr trigPtr; + TriggerPtr trigPtr LINT_SET_PTR; if(tabPtr.p->triggerAllocated[j]) { jam(); c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]); @@ -4600,7 +4606,7 @@ Backup::cleanup(Signal* signal, BackupRecordPtr ptr) tabPtr.p->fragments.release(); for(Uint32 j = 0; j<3; j++) { jam(); - TriggerPtr trigPtr; + TriggerPtr trigPtr LINT_SET_PTR; if(tabPtr.p->triggerAllocated[j]) { jam(); c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]); @@ -4680,7 +4686,7 @@ Backup::execFSREMOVECONF(Signal* signal){ /** * Get backup record */ - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); c_backups.release(ptr); } diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp index d2f9150ade0..042021bc6e0 100644 --- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp +++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp @@ -91,6 +91,7 @@ Cmvmi::Cmvmi(const Configuration & conf) : addRecSignal(GSN_DUMP_STATE_ORD, &Cmvmi::execDUMP_STATE_ORD); addRecSignal(GSN_TESTSIG, &Cmvmi::execTESTSIG); + addRecSignal(GSN_NODE_START_REP, &Cmvmi::execNODE_START_REP, true); subscriberPool.setSize(5); @@ -340,6 +341,16 @@ void Cmvmi::execSTTOR(Signal* signal) jamEntry(); if (theStartPhase == 1){ jam(); + + if(theConfig.lockPagesInMainMemory()) + { + int res = NdbMem_MemLockAll(); + if(res != 0){ + g_eventLogger.warning("Failed to memlock pages"); + warningEvent("Failed to memlock pages"); + } + } + sendSTTORRY(signal); return; } else if (theStartPhase == 3) { @@ -360,18 +371,6 @@ void Cmvmi::execSTTOR(Signal* signal) execOPEN_COMREQ(signal); globalData.theStartLevel = NodeState::SL_STARTED; sendSTTORRY(signal); - } else { - jam(); - - if(theConfig.lockPagesInMainMemory()){ - int res = NdbMem_MemLockAll(); - if(res != 0){ - g_eventLogger.warning("Failed to memlock pages"); - warningEvent("Failed to memlock pages"); - } - } - - sendSTTORRY(signal); } } @@ -425,7 +424,8 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal) if(len == 2){ #ifdef ERROR_INSERT - if (! (ERROR_INSERTED(9000) && c_error_9000_nodes_mask.get(tStartingNode))) + if (! ((ERROR_INSERTED(9000) || ERROR_INSERTED(9002)) + && c_error_9000_nodes_mask.get(tStartingNode))) #endif { globalTransporterRegistry.do_connect(tStartingNode); @@ -446,7 +446,8 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal) jam(); #ifdef ERROR_INSERT - if (ERROR_INSERTED(9000) && c_error_9000_nodes_mask.get(i)) + if ((ERROR_INSERTED(9000) || ERROR_INSERTED(9002)) + && c_error_9000_nodes_mask.get(i)) continue; #endif @@ -697,6 +698,7 @@ Cmvmi::execTEST_ORD(Signal * signal){ // Do nothing break; } + globalSignalLoggers.flushSignalLog(); } #endif @@ -1144,9 +1146,9 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal) } #ifdef ERROR_INSERT - if (arg == 9000) + if (arg == 9000 || arg == 9002) { - SET_ERROR_INSERT_VALUE(9000); + SET_ERROR_INSERT_VALUE(arg); for (Uint32 i = 1; i<signal->getLength(); i++) c_error_9000_nodes_mask.set(signal->theData[i]); } @@ -1193,6 +1195,17 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal) #endif }//Cmvmi::execDUMP_STATE_ORD() +void +Cmvmi::execNODE_START_REP(Signal* signal) +{ +#ifdef ERROR_INSERT + if (ERROR_INSERTED(9002) && signal->theData[0] == getOwnNodeId()) + { + signal->theData[0] = 9001; + execDUMP_STATE_ORD(signal); + } +#endif +} BLOCK_FUNCTIONS(Cmvmi) @@ -1234,7 +1247,7 @@ Cmvmi::execTESTSIG(Signal* signal){ fprintf(stdout, "\n"); for(i = 0; i<signal->header.m_noOfSections; i++){ - SegmentedSectionPtr ptr; + SegmentedSectionPtr ptr = {0,0,0}; ndbout_c("-- Section %d --", i); signal->getSection(ptr, i); ndbrequire(ptr.p != 0); @@ -1292,7 +1305,7 @@ Cmvmi::execTESTSIG(Signal* signal){ LinearSectionPtr ptr[3]; const Uint32 secs = signal->getNoOfSections(); for(i = 0; i<secs; i++){ - SegmentedSectionPtr sptr; + SegmentedSectionPtr sptr = {0,0,0}; signal->getSection(sptr, i); ptr[i].sz = sptr.sz; ptr[i].p = new Uint32[sptr.sz]; @@ -1341,7 +1354,7 @@ Cmvmi::execTESTSIG(Signal* signal){ LinearSectionPtr ptr[3]; const Uint32 secs = signal->getNoOfSections(); for(i = 0; i<secs; i++){ - SegmentedSectionPtr sptr; + SegmentedSectionPtr sptr = {0,0,0}; signal->getSection(sptr, i); ptr[i].sz = sptr.sz; ptr[i].p = new Uint32[sptr.sz]; @@ -1407,7 +1420,7 @@ Cmvmi::execTESTSIG(Signal* signal){ const Uint32 secs = signal->getNoOfSections(); memset(g_test, 0, sizeof(g_test)); for(i = 0; i<secs; i++){ - SegmentedSectionPtr sptr; + SegmentedSectionPtr sptr = {0,0,0}; signal->getSection(sptr, i); g_test[i].sz = sptr.sz; g_test[i].p = new Uint32[sptr.sz]; diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp index f89c8f15e86..d050587e91d 100644 --- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp +++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp @@ -72,7 +72,8 @@ private: void handleSET_VAR_REQ(Signal* signal); void execTESTSIG(Signal* signal); - + void execNODE_START_REP(Signal* signal); + char theErrorMessage[256]; void sendSTTORRY(Signal* signal); diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 7ecdf2466ee..f922bfdf561 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -10054,8 +10054,8 @@ Dbdict::getDictLockType(Uint32 lockType) static const DictLockType lt[] = { { DictLockReq::NodeRestartLock, BS_NODE_RESTART, "NodeRestart" } }; - for (int i = 0; i < sizeof(lt)/sizeof(lt[0]); i++) { - if (lt[i].lockType == lockType) + for (unsigned int i = 0; i < sizeof(lt)/sizeof(lt[0]); i++) { + if ((Uint32) lt[i].lockType == lockType) return <[i]; } return NULL; @@ -10184,6 +10184,15 @@ Dbdict::checkDictLockQueue(Signal* signal, bool poll) break; } + if (c_blockState != BS_IDLE) + { + /** + * If state is BS_NODE_FAILURE, it might be that no op is running + */ + jam(); + break; + } + ndbrequire(c_blockState == BS_IDLE); lockPtr.p->locked = true; c_blockState = lockPtr.p->lt->blockState; @@ -10207,7 +10216,7 @@ Dbdict::execDICT_UNLOCK_ORD(Signal* signal) DictLockPtr lockPtr; c_dictLockQueue.getPtr(lockPtr, ord->lockPtr); - ndbrequire(lockPtr.p->lt->lockType == ord->lockType); + ndbrequire((Uint32) lockPtr.p->lt->lockType == ord->lockType); if (lockPtr.p->locked) { jam(); diff --git a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp index 53e54e96d2b..f1b3897c76f 100644 --- a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp +++ b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp @@ -1602,7 +1602,7 @@ private: void startInfoReply(Signal *, Uint32 nodeId); // DIH specifics for execNODE_START_REP (sendDictUnlockOrd) - void exec_node_start_rep(Signal* signal); + void execNODE_START_REP(Signal* signal); /* * Lock master DICT. Only current use is by starting node diff --git a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp index 2b878034258..bb96c4b8831 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp @@ -269,7 +269,8 @@ Dbdih::Dbdih(const class Configuration & config): addRecSignal(GSN_DICT_LOCK_CONF, &Dbdih::execDICT_LOCK_CONF); addRecSignal(GSN_DICT_LOCK_REF, &Dbdih::execDICT_LOCK_REF); - + addRecSignal(GSN_NODE_START_REP, &Dbdih::execNODE_START_REP, true); + apiConnectRecord = 0; connectRecord = 0; fileRecord = 0; diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 4aeb8136650..28384d7cb86 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -1390,7 +1390,7 @@ void Dbdih::execNDB_STTOR(Signal* signal) }//Dbdih::execNDB_STTOR() void -Dbdih::exec_node_start_rep(Signal* signal) +Dbdih::execNODE_START_REP(Signal* signal) { /* * Send DICT_UNLOCK_ORD when this node is SL_STARTED. diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp index 299cad16ec1..0691e52d0ee 100644 --- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp +++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp @@ -236,6 +236,7 @@ #define ZOPERATION_EVENT_REP 19 #define ZPREP_DROP_TABLE 20 #define ZENABLE_EXPAND_CHECK 21 +#define ZRETRY_TCKEYREF 22 /* ------------------------------------------------------------------------- */ /* NODE STATE DURING SYSTEM RESTART, VARIABLES CNODES_SR_STATE */ @@ -2276,6 +2277,7 @@ private: void releaseScanrec(Signal* signal); void seizeScanrec(Signal* signal); Uint32 sendKeyinfo20(Signal* signal, ScanRecord *, TcConnectionrec *); + void sendTCKEYREF(Signal*, Uint32 dst, Uint32 route, Uint32 cnt); void sendScanFragConf(Signal* signal, Uint32 scanCompleted); void initCopyrec(Signal* signal); void initCopyTc(Signal* signal); diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 4739450884c..3d93ce3fc31 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -464,6 +464,22 @@ void Dblqh::execCONTINUEB(Signal* signal) return; } } + case ZRETRY_TCKEYREF: + { + jam(); + Uint32 cnt = signal->theData[1]; + Uint32 ref = signal->theData[2]; + if (cnt < (10 * 60 * 5)) + { + jam(); + /** + * Only retry for 5 minutes...then hope that API has handled it..somehow + */ + memmove(signal->theData, signal->theData+3, 4*TcKeyRef::SignalLength); + sendTCKEYREF(signal, ref, 0, cnt); + } + return; + } default: ndbrequire(false); break; @@ -2370,7 +2386,7 @@ void Dblqh::noFreeRecordLab(Signal* signal, tcKeyRef->transId[0] = transid1; tcKeyRef->transId[1] = transid2; tcKeyRef->errorCode = errCode; - sendSignal(apiRef, GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB); + sendTCKEYREF(signal, apiRef, signal->getSendersBlockRef(), 0); } else { jam(); @@ -6576,8 +6592,7 @@ void Dblqh::continueAfterLogAbortWriteLab(Signal* signal) tcKeyRef->transId[0] = regTcPtr->transid[0]; tcKeyRef->transId[1] = regTcPtr->transid[1]; tcKeyRef->errorCode = regTcPtr->errorCode; - sendSignal(regTcPtr->applRef, - GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB); + sendTCKEYREF(signal, regTcPtr->applRef, regTcPtr->clientBlockref, 0); cleanUp(signal); return; }//if @@ -6612,6 +6627,29 @@ void Dblqh::continueAfterLogAbortWriteLab(Signal* signal) cleanUp(signal); }//Dblqh::continueAfterLogAbortWriteLab() +void +Dblqh::sendTCKEYREF(Signal* signal, Uint32 ref, Uint32 routeRef, Uint32 cnt) +{ + const Uint32 nodeId = refToNode(ref); + const bool connectedToNode = getNodeInfo(nodeId).m_connected; + + if (likely(connectedToNode)) + { + jam(); + sendSignal(ref, GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB); + } + else + { + jam(); + memmove(signal->theData + 3, signal->theData, 4*TcKeyRef::SignalLength); + signal->theData[0] = ZRETRY_TCKEYREF; + signal->theData[1] = cnt + 1; + signal->theData[2] = ref; + sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, + TcKeyRef::SignalLength + 3); + } +} + /* ########################################################################## * ####### MODULE TO HANDLE TC FAILURE ####### * diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp index bf6ce7129ba..792586d7baf 100644 --- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp +++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp @@ -942,7 +942,8 @@ public: NF_CHECK_SCAN = 0x2, NF_CHECK_TRANSACTION = 0x4, NF_CHECK_DROP_TAB = 0x8, - NF_NODE_FAIL_BITS = 0xF // All bits... + NF_NODE_FAIL_BITS = 0xF, // All bits... + NF_STARTED = 0x10 }; Uint32 m_nf_bits; NdbNodeBitmask m_lqh_trans_conf; @@ -1319,6 +1320,7 @@ private: void execCOMMITCONF(Signal* signal); void execABORTCONF(Signal* signal); void execNODE_FAILREP(Signal* signal); + void execNODE_START_REP(Signal* signal); void execINCL_NODEREQ(Signal* signal); void execTIME_SIGNAL(Signal* signal); void execAPI_FAILREQ(Signal* signal); diff --git a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp index 7bd308119fc..098373fb3de 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp @@ -290,7 +290,8 @@ Dbtc::Dbtc(const class Configuration & conf): addRecSignal(GSN_WAIT_DROP_TAB_CONF, &Dbtc::execWAIT_DROP_TAB_CONF); addRecSignal(GSN_ALTER_TAB_REQ, &Dbtc::execALTER_TAB_REQ); - + addRecSignal(GSN_NODE_START_REP, &Dbtc::execNODE_START_REP, true); + cacheRecord = 0; apiConnectRecord = 0; tcConnectRecord = 0; diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index cc39219590f..a436316f7c9 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -3068,7 +3068,28 @@ void Dbtc::tckeyreq050Lab(Signal* signal) }//if }//for } - }//if + + if (regTcPtr->tcNodedata[0] != getOwnNodeId()) + { + jam(); + for (Uint32 i = 0; i < tnoOfBackup + 1; i++) + { + HostRecordPtr hostPtr; + hostPtr.i = regTcPtr->tcNodedata[i]; + ptrCheckGuard(hostPtr, chostFilesize, hostRecord); + if (hostPtr.p->m_nf_bits & HostRecord::NF_STARTED) + { + jam(); + if (i != 0) + { + jam(); + regTcPtr->tcNodedata[0] = hostPtr.i; + } + break; + } + } + }//if + } jam(); regTcPtr->lastReplicaNo = 0; regTcPtr->noOfNodes = 1; @@ -7003,6 +7024,19 @@ void Dbtc::execNODE_FAILREP(Signal* signal) }//Dbtc::execNODE_FAILREP() void +Dbtc::execNODE_START_REP(Signal* signal) +{ + Uint32 nodeId = signal->theData[0]; + hostptr.i = nodeId; + ptrCheckGuard(hostptr, chostFilesize, hostRecord); + if (hostptr.p->m_nf_bits == 0) + { + jam(); + hostptr.p->m_nf_bits |= HostRecord::NF_STARTED; + } +} + +void Dbtc::checkNodeFailComplete(Signal* signal, Uint32 failedNodeId, Uint32 bit) @@ -8701,6 +8735,20 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) * IF ANY TO RECEIVE. **********************************************************/ scanptr.p->scanState = ScanRecord::WAIT_AI; + + if (ERROR_INSERTED(8038)) + { + /** + * Force API_FAILREQ + */ + DisconnectRep * const rep = (DisconnectRep *)signal->getDataPtrSend(); + rep->nodeId = refToNode(apiConnectptr.p->ndbapiBlockref); + rep->err = 8038; + + EXECUTE_DIRECT(CMVMI, GSN_DISCONNECT_REP, signal, 2); + CLEAR_ERROR_INSERT_VALUE; + } + return; SCAN_error_check: @@ -8790,6 +8838,7 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr, jam(); ScanFragRecPtr ptr; ndbrequire(list.seize(ptr)); + ptr.p->scanFragState = ScanFragRec::IDLE; ptr.p->scanRec = scanptr.i; ptr.p->scanFragId = 0; ptr.p->m_apiPtr = cdata[i]; @@ -9582,9 +9631,17 @@ Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){ ScanRecord* scanP = scanPtr.p; ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE); + ScanRecord::ScanState old = scanPtr.p->scanState; scanPtr.p->scanState = ScanRecord::CLOSING_SCAN; scanPtr.p->m_close_scan_req = req_received; + if (old == ScanRecord::WAIT_FRAGMENT_COUNT) + { + jam(); + scanPtr.p->scanState = old; + return; // Will continue on execDI_FCOUNTCONF + } + /** * Queue : Action * ============= : ================= @@ -9612,11 +9669,22 @@ Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){ ScanFragRecPtr curr = ptr; // Remove while iterating... running.next(ptr); - if(curr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF){ + switch(curr.p->scanFragState){ + case ScanFragRec::IDLE: + jam(); // real early abort + ndbrequire(old == ScanRecord::WAIT_AI); + running.release(curr); + continue; + case ScanFragRec::WAIT_GET_PRIMCONF: jam(); continue; + case ScanFragRec::LQH_ACTIVE: + jam(); + break; + default: + jamLine(curr.p->scanFragState); + ndbrequire(false); } - ndbrequire(curr.p->scanFragState == ScanFragRec::LQH_ACTIVE); curr.p->startFragTimer(ctcTimer); curr.p->scanFragState = ScanFragRec::LQH_ACTIVE; diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp index 0b66d9a45bb..c068a993792 100644 --- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp +++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp @@ -196,6 +196,7 @@ #define ZTRY_TO_UPDATE_ERROR 888 #define ZCALL_ERROR 890 #define ZTEMPORARY_RESOURCE_FAILURE 891 +#define ZUNSUPPORTED_BRANCH 892 #define ZSTORED_SEIZE_ATTRINBUFREC_ERROR 873 // Part of Scan diff --git a/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp b/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp index e9043a8b52d..07babd72ce1 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp @@ -444,6 +444,11 @@ int Dbtup::TUPKEY_abort(Signal* signal, int error_type) }//if break; + case 40: + ljam(); + terrorCode = ZUNSUPPORTED_BRANCH; + break; + default: ndbrequire(false); break; diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index 13c0bad9c7a..9917ac4e340 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -1876,6 +1876,11 @@ int Dbtup::interpreterNextLab(Signal* signal, // NULL==NULL and NULL<not-NULL res1 = r1_null && r2_null ? 0 : r1_null ? -1 : 1; } else { + jam(); + if (unlikely(sqlType.m_cmp == 0)) + { + return TUPKEY_abort(signal, 40); + } res1 = (*sqlType.m_cmp)(cs, s1, attrLen, s2, argLen, true); } } else { @@ -1883,6 +1888,11 @@ int Dbtup::interpreterNextLab(Signal* signal, // NULL like NULL is true (has no practical use) res1 = r1_null && r2_null ? 0 : -1; } else { + jam(); + if (unlikely(sqlType.m_like == 0)) + { + return TUPKEY_abort(signal, 40); + } res1 = (*sqlType.m_like)(cs, s1, attrLen, s2, argLen); } } diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp index 4b5c0b791f9..da2321bdf6f 100644 --- a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp +++ b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp @@ -132,7 +132,7 @@ Dbtux::searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos.m_pos = hi; return true; } - if (hi < currNode.getOccup()) { + if ((uint) hi < currNode.getOccup()) { jam(); treePos.m_pos = hi; return true; diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index 7fa41cb2694..af05eeb9e9a 100644 --- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -1524,6 +1524,11 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal) break; } + case StopRecord::SR_BLOCK_GCP_START_GCP: + case StopRecord::SR_WAIT_COMPLETE_GCP: + case StopRecord::SR_UNBLOCK_GCP_START_GCP: + case StopRecord::SR_CLUSTER_SHUTDOWN: + break; } } @@ -2283,7 +2288,7 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){ bool allNodesStopped = true; int i ; - for( i = 0; i< NdbNodeBitmask::Size; i++ ){ + for( i = 0; i < (int) NdbNodeBitmask::Size; i++ ){ if ( stopReq.nodes[i] != 0 ){ allNodesStopped = false; break; diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp index 51d06537dbb..68e649d8ae0 100644 --- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp +++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp @@ -160,7 +160,7 @@ void Qmgr::execCONTINUEB(Signal* signal) BaseString tmp; tmp.append("Shutting down node as total restart time exceeds " " StartFailureTimeout as set in config file "); - if(c_restartFailureTimeout == ~0) + if(c_restartFailureTimeout == (Uint32) ~0) tmp.append(" 0 (inifinite)"); else tmp.appfmt(" %d", c_restartFailureTimeout); @@ -1339,7 +1339,7 @@ Qmgr::check_startup(Signal* signal) if (now < partial_timeout) { jam(); - signal->theData[1] = c_restartPartialTimeout == ~0 ? 2 : 3; + signal->theData[1] = c_restartPartialTimeout == (Uint32) ~0 ? 2 : 3; signal->theData[2] = Uint32((partial_timeout - now + 500) / 1000); report_mask.assign(wait); retVal = 0; @@ -1356,7 +1356,7 @@ Qmgr::check_startup(Signal* signal) case CheckNodeGroups::Partitioning: if (now < partitioned_timeout && result != CheckNodeGroups::Win) { - signal->theData[1] = c_restartPartionedTimeout == ~0 ? 4 : 5; + signal->theData[1] = c_restartPartionedTimeout == (Uint32) ~0 ? 4 : 5; signal->theData[2] = Uint32((partitioned_timeout - now + 500) / 1000); report_mask.assign(c_definedNodes); report_mask.bitANDC(c_start.m_starting_nodes); @@ -1403,6 +1403,7 @@ missing_nodegroup: " starting: %s (missing fs for: %s)", mask1, mask2); progError(__LINE__, NDBD_EXIT_SR_RESTARTCONFLICT, buf); + return 0; // Deadcode } void diff --git a/ndb/src/kernel/error/ErrorReporter.cpp b/ndb/src/kernel/error/ErrorReporter.cpp index 6c8bb1fe615..e95cd5c132f 100644 --- a/ndb/src/kernel/error/ErrorReporter.cpp +++ b/ndb/src/kernel/error/ErrorReporter.cpp @@ -185,6 +185,7 @@ ErrorReporter::handleAssert(const char* message, const char* file, int line, int childReportError(ec); NdbShutdown(s_errorHandlerShutdownType); + exit(1); // Deadcode } void diff --git a/ndb/src/kernel/error/ErrorReporter.hpp b/ndb/src/kernel/error/ErrorReporter.hpp index 0ec84190238..dffec14dff2 100644 --- a/ndb/src/kernel/error/ErrorReporter.hpp +++ b/ndb/src/kernel/error/ErrorReporter.hpp @@ -29,7 +29,7 @@ public: static void setErrorHandlerShutdownType(NdbShutdownType nst = NST_ErrorHandler); static void handleAssert(const char* message, const char* file, - int line, int ec = NDBD_EXIT_PRGERR); + int line, int ec = NDBD_EXIT_PRGERR) __attribute__((__noreturn__)); static void handleError(int faultID, const char* problemData, diff --git a/ndb/src/kernel/error/ndbd_exit_codes.c b/ndb/src/kernel/error/ndbd_exit_codes.c index 1853130f93c..205af85575a 100644 --- a/ndb/src/kernel/error/ndbd_exit_codes.c +++ b/ndb/src/kernel/error/ndbd_exit_codes.c @@ -14,6 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <ndb_global.h> #include <ndbd_exit_codes.h> typedef struct ErrStruct { diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp index b4787209d55..d5bf2a911b8 100644 --- a/ndb/src/kernel/vm/SimulatedBlock.cpp +++ b/ndb/src/kernel/vm/SimulatedBlock.cpp @@ -658,24 +658,26 @@ SimulatedBlock::allocRecord(const char * type, size_t s, size_t n, bool clear) void * p = NULL; size_t size = n*s; + Uint64 real_size = (Uint64)((Uint64)n)*((Uint64)s); refresh_watch_dog(); - if (size > 0){ + if (real_size > 0){ #ifdef VM_TRACE_MEM - ndbout_c("%s::allocRecord(%s, %u, %u) = %u bytes", + ndbout_c("%s::allocRecord(%s, %u, %u) = %llu bytes", getBlockName(number()), type, s, n, - size); + real_size); #endif - p = ndbd_malloc(size); + if( real_size == (Uint64)size ) + p = ndbd_malloc(size); if (p == NULL){ char buf1[255]; char buf2[255]; BaseString::snprintf(buf1, sizeof(buf1), "%s could not allocate memory for %s", getBlockName(number()), type); - BaseString::snprintf(buf2, sizeof(buf2), "Requested: %ux%u = %u bytes", - (Uint32)s, (Uint32)n, (Uint32)size); + BaseString::snprintf(buf2, sizeof(buf2), "Requested: %ux%u = %llu bytes", + (Uint32)s, (Uint32)n, (Uint64)real_size); ERROR_SET(fatal, NDBD_EXIT_MEMALLOC, buf1, buf2); } @@ -917,15 +919,6 @@ SimulatedBlock::execCONTINUE_FRAGMENTED(Signal * signal){ void SimulatedBlock::execNODE_START_REP(Signal* signal) { - // common stuff for all blocks - - // block specific stuff by virtual method override (default empty) - exec_node_start_rep(signal); -} - -void -SimulatedBlock::exec_node_start_rep(Signal* signal) -{ } #ifdef VM_TRACE_TIME diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp index 4a3620a00ab..f7ca4ecbf38 100644 --- a/ndb/src/kernel/vm/SimulatedBlock.hpp +++ b/ndb/src/kernel/vm/SimulatedBlock.hpp @@ -424,7 +424,6 @@ private: void execSIGNAL_DROPPED_REP(Signal* signal); void execCONTINUE_FRAGMENTED(Signal* signal); void execNODE_START_REP(Signal* signal); - virtual void exec_node_start_rep(Signal* signal); Uint32 c_fragmentIdCounter; ArrayPool<FragmentInfo> c_fragmentInfoPool; diff --git a/ndb/src/kernel/vm/TransporterCallback.cpp b/ndb/src/kernel/vm/TransporterCallback.cpp index f315918b871..badd2af669c 100644 --- a/ndb/src/kernel/vm/TransporterCallback.cpp +++ b/ndb/src/kernel/vm/TransporterCallback.cpp @@ -56,7 +56,7 @@ const char *lookupConnectionError(Uint32 err) { int i= 0; while ((Uint32)connectionError[i].err != err && - (Uint32)connectionError[i].err != -1) + connectionError[i].err != -1) i++; return connectionError[i].text; } diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index cab06331bbc..8aa4f7213de 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -178,7 +178,7 @@ ndb_mgm_create_handle() h->mgmd_version_minor= -1; h->mgmd_version_build= -1; - DBUG_PRINT("info", ("handle=0x%x", (UintPtr)h)); + DBUG_PRINT("info", ("handle: 0x%lx", (long)h)); DBUG_RETURN(h); } @@ -195,7 +195,7 @@ int ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv) { DBUG_ENTER("ndb_mgm_set_connectstring"); - DBUG_PRINT("info", ("handle=0x%x", (UintPtr)handle)); + DBUG_PRINT("info", ("handle: 0x%lx", (long)handle)); handle->cfg.~LocalConfig(); new (&(handle->cfg)) LocalConfig; if (!handle->cfg.init(mgmsrv, 0) || @@ -237,7 +237,7 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle) DBUG_ENTER("ndb_mgm_destroy_handle"); if(!handle) DBUG_VOID_RETURN; - DBUG_PRINT("info", ("handle=0x%x", (UintPtr)(* handle))); + DBUG_PRINT("info", ("handle: 0x%lx", (long)(* handle))); /** * important! only disconnect if connected * other code relies on this @@ -2565,8 +2565,8 @@ int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length) args.put("length", length); BaseString data_string; - for (int i = 0; i < length; i++) - data_string.appfmt(" %u", data[i]); + for (int i = 0; i < (int) length; i++) + data_string.appfmt(" %lu", (ulong) data[i]); args.put("data", data_string.c_str()); diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index 2d096b10411..1dacd9689e8 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -653,7 +653,7 @@ static const char* helpTextDebug = ; #endif -struct { +struct st_cmd_help { const char *cmd; const char * help; }help_items[]={ @@ -2466,7 +2466,7 @@ CommandInterpreter::executeEventReporting(int processId, Vector<BaseString> specs; tmp.split(specs, " "); - for (int i=0; i < specs.size(); i++) + for (int i=0; i < (int) specs.size(); i++) { Vector<BaseString> spec; specs[i].split(spec, "="); diff --git a/ndb/src/mgmsrv/Makefile.am b/ndb/src/mgmsrv/Makefile.am index 7fd3fa66b43..effad38be10 100644 --- a/ndb/src/mgmsrv/Makefile.am +++ b/ndb/src/mgmsrv/Makefile.am @@ -23,7 +23,7 @@ INCLUDES_LOC = -I$(top_srcdir)/ndb/src/ndbapi \ -I$(top_srcdir)/ndb/src/common/mgmcommon \ -I$(top_srcdir)/ndb/src/mgmclient -LDADD_LOC = $(top_srcdir)/ndb/src/mgmclient/CommandInterpreter.o \ +LDADD_LOC = $(top_builddir)/ndb/src/mgmclient/CommandInterpreter.o \ $(top_builddir)/ndb/src/libndbclient.la \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index a2329c67bb7..766992af0cb 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -835,7 +835,7 @@ MgmtSrvr::sendVersionReq(int v_nodeId, Uint32 &version, const char **address) case GSN_API_VERSION_CONF: { const ApiVersionConf * const conf = CAST_CONSTPTR(ApiVersionConf, signal->getDataPtr()); - assert(conf->nodeId == v_nodeId); + assert((int) conf->nodeId == v_nodeId); version = conf->version; struct in_addr in; in.s_addr= conf->inet_addr; @@ -1573,7 +1573,7 @@ MgmtSrvr::setEventReportingLevelImpl(int nodeId, NodeBitmask nodes; nodes.clear(); Uint32 max = (nodeId == 0) ? (nodeId = 1, MAX_NDB_NODES) : nodeId; - for(; nodeId <= max; nodeId++) + for(; (Uint32) nodeId <= max; nodeId++) { if (nodeTypes[nodeId] != NODE_TYPE_DB) continue; @@ -2001,8 +2001,8 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId, int log_event) { DBUG_ENTER("MgmtSrvr::alloc_node_id"); - DBUG_PRINT("enter", ("nodeid=%d, type=%d, client_addr=%d", - *nodeId, type, client_addr)); + DBUG_PRINT("enter", ("nodeid: %d type: %d client_addr: 0x%ld", + *nodeId, type, (long) client_addr)); if (g_no_nodeid_checks) { if (*nodeId == 0) { error_string.appfmt("no-nodeid-checks set in management server.\n" diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index 7d59a303df2..a6dcc13a894 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -1337,7 +1337,7 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId) if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity,textF)) DBUG_VOID_RETURN; - char m_text[256]; + char m_text[512]; EventLogger::getText(m_text, sizeof(m_text), textF, theData, nodeId); @@ -1353,6 +1353,15 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId) if (ndb_logevent_body[i].index_fn) val= (*(ndb_logevent_body[i].index_fn))(val); str.appfmt("%s=%d\n",ndb_logevent_body[i].token, val); + if(strcmp(ndb_logevent_body[i].token,"error") == 0) + { + int m_text_len= strlen(m_text); + if(sizeof(m_text)-m_text_len-3 > 0) + { + BaseString::snprintf(m_text+m_text_len, 4 , " - "); + ndb_error_string(val, m_text+(m_text_len+3), sizeof(m_text)-m_text_len-3); + } + } } Vector<NDB_SOCKET_TYPE> copy; @@ -1699,7 +1708,7 @@ MgmApiSession::report_event(Parser_t::Context &ctx, BaseString tmp(data_string); Vector<BaseString> item; tmp.split(item, " "); - for (int i = 0; i < length ; i++) + for (int i = 0; (Uint32) i < length ; i++) { sscanf(item[i].c_str(), "%u", data+i); } diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp index 475561af225..8545c599341 100644 --- a/ndb/src/ndbapi/ClusterMgr.cpp +++ b/ndb/src/ndbapi/ClusterMgr.cpp @@ -213,7 +213,7 @@ ClusterMgr::forceHB() int nodeId= 0; for(int i=0; - NodeBitmask::NotFound!=(nodeId= waitForHBFromNodes.find(i)); + (int) NodeBitmask::NotFound != (nodeId= waitForHBFromNodes.find(i)); i= nodeId+1) { #ifdef DEBUG_REG diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp index bb59c16fb7c..ba8b0799398 100644 --- a/ndb/src/ndbapi/DictCache.cpp +++ b/ndb/src/ndbapi/DictCache.cpp @@ -116,7 +116,8 @@ void GlobalDictCache::printCache() NdbElement_t<Vector<TableVersion> > * curr = m_tableHash.getNext(0); while(curr != 0){ DBUG_PRINT("curr", ("len: %d, hash: %d, lk: %d, str: %s", - curr->len, curr->hash, curr->localkey1, curr->str)); + curr->len, curr->hash, curr->localkey1, + (char*) curr->str)); if (curr->theData){ Vector<TableVersion> * vers = curr->theData; const unsigned sz = vers->size(); diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index 9d1c78a5972..59a204be2a8 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -355,8 +355,9 @@ Ndb::startTransaction(const NdbDictionary::Table *table, { NdbTransaction *trans= startTransactionLocal(0, nodeId); - DBUG_PRINT("exit",("start trans: 0x%x transid: 0x%llx", - trans, trans ? trans->getTransactionId() : 0)); + DBUG_PRINT("exit",("start trans: 0x%lx transid: 0x%lx", + (long) trans, + (long) (trans ? trans->getTransactionId() : 0))); DBUG_RETURN(trans); } } else { @@ -377,7 +378,7 @@ Ndb::hupp(NdbTransaction* pBuddyTrans) { DBUG_ENTER("Ndb::hupp"); - DBUG_PRINT("enter", ("trans: 0x%x",pBuddyTrans)); + DBUG_PRINT("enter", ("trans: 0x%lx", (long) pBuddyTrans)); Uint32 aPriority = 0; if (pBuddyTrans == NULL){ @@ -402,8 +403,9 @@ Ndb::hupp(NdbTransaction* pBuddyTrans) } pCon->setTransactionId(pBuddyTrans->getTransactionId()); pCon->setBuddyConPtr((Uint32)pBuddyTrans->getTC_ConnectPtr()); - DBUG_PRINT("exit", ("hupp trans: 0x%x transid: 0x%llx", - pCon, pCon ? pCon->getTransactionId() : 0)); + DBUG_PRINT("exit", ("hupp trans: 0x%lx transid: 0x%lx", + (long) pCon, + (long) (pCon ? pCon->getTransactionId() : 0))); DBUG_RETURN(pCon); } else { DBUG_RETURN(NULL); @@ -490,8 +492,9 @@ Ndb::closeTransaction(NdbTransaction* aConnection) tCon = theTransactionList; theRemainingStartTransactions++; - DBUG_PRINT("info",("close trans: 0x%x transid: 0x%llx", - aConnection, aConnection->getTransactionId())); + DBUG_PRINT("info",("close trans: 0x%lx transid: 0x%lx", + (long) aConnection, + (long) aConnection->getTransactionId())); DBUG_PRINT("info",("magic number: 0x%x TCConPtr: 0x%x theMyRef: 0x%x 0x%x", aConnection->theMagicNumber, aConnection->theTCConPtr, aConnection->theMyRef, getReference())); @@ -774,7 +777,7 @@ Ndb::getAutoIncrementValue(const char* aTableName, } if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong) tupleId)); DBUG_RETURN(0); } @@ -795,7 +798,7 @@ Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, } if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong)tupleId)); DBUG_RETURN(0); } @@ -808,7 +811,7 @@ Ndb::getTupleIdFromNdb(Ndb_local_table_info* info, { assert(info->m_first_tuple_id < info->m_last_tuple_id); tupleId = ++info->m_first_tuple_id; - DBUG_PRINT("info", ("next cached value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("next cached value %lu", (ulong)tupleId)); } else { @@ -842,7 +845,7 @@ Ndb::readAutoIncrementValue(const char* aTableName, } if (readTupleIdFromNdb(info, tupleId) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong)tupleId)); DBUG_RETURN(0); } @@ -863,7 +866,7 @@ Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable, } if (readTupleIdFromNdb(info, tupleId) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong)tupleId)); DBUG_RETURN(0); } @@ -945,8 +948,8 @@ Ndb::setTupleIdInNdb(Ndb_local_table_info* info, { info->m_first_tuple_id = tupleId - 1; DBUG_PRINT("info", - ("Setting next auto increment cached value to %llu", - (ulonglong)tupleId)); + ("Setting next auto increment cached value to %lu", + (ulong)tupleId)); DBUG_RETURN(0); } } @@ -973,7 +976,8 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op) { DBUG_ENTER("Ndb::opTupleIdOnNdb"); Uint32 aTableId = info->m_table_impl->m_tableId; - DBUG_PRINT("enter", ("table=%u value=%llu op=%u", aTableId, opValue, op)); + DBUG_PRINT("enter", ("table: %u value: %lu op: %u", + aTableId, (ulong) opValue, op)); NdbTransaction* tConnection; NdbOperation* tOperation= 0; // Compiler warning if not initialized @@ -1047,8 +1051,8 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op) else { DBUG_PRINT("info", - ("Setting next auto increment value (db) to %llu", - (ulonglong)opValue)); + ("Setting next auto increment value (db) to %lu", + (ulong)opValue)); info->m_first_tuple_id = info->m_last_tuple_id = opValue - 1; } break; @@ -1244,7 +1248,7 @@ Ndb::internalize_index_name(const NdbTableImpl * table, if (!table) { DBUG_PRINT("error", ("!table")); - return ret; + DBUG_RETURN(ret); } if (fullyQualifiedNames) diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp index 835e33dfb40..42dec161307 100644 --- a/ndb/src/ndbapi/NdbOperationDefine.cpp +++ b/ndb/src/ndbapi/NdbOperationDefine.cpp @@ -407,10 +407,10 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo, const char* aValuePassed, Uint32 len) { DBUG_ENTER("NdbOperation::setValue"); - DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u", + DBUG_PRINT("enter", ("col: %s op: %d val: 0x%lx len: %u", tAttrInfo->m_name.c_str(), theOperationType, - aValuePassed, len)); + (long) aValuePassed, len)); if (aValuePassed != NULL) DBUG_DUMP("value", (char*)aValuePassed, len); diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp index 58a816e3c1a..11713678478 100644 --- a/ndb/src/ndbapi/NdbOperationExec.cpp +++ b/ndb/src/ndbapi/NdbOperationExec.cpp @@ -205,7 +205,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId) tcKeyReq->setKeyLength(tReqInfo, tTupKeyLen); // A simple read is always ignore error - abortOption = tSimpleIndicator ? AO_IgnoreError : abortOption; + abortOption = tSimpleIndicator ? (Uint8) AO_IgnoreError : abortOption; tcKeyReq->setAbortOption(tReqInfo, abortOption); Uint8 tDistrKeyIndicator = theDistrKeyIndicator_; diff --git a/ndb/src/ndbapi/NdbOperationInt.cpp b/ndb/src/ndbapi/NdbOperationInt.cpp index 41e0cb1d140..6defb37467f 100644 --- a/ndb/src/ndbapi/NdbOperationInt.cpp +++ b/ndb/src/ndbapi/NdbOperationInt.cpp @@ -1015,8 +1015,8 @@ NdbOperation::branch_col(Uint32 type, bool nopad, Uint32 Label){ DBUG_ENTER("NdbOperation::branch_col"); - DBUG_PRINT("enter", ("type=%u col=%u val=0x%x len=%u label=%u", - type, ColId, val, len, Label)); + DBUG_PRINT("enter", ("type: %u col:%u val: 0x%lx len: %u label: %u", + type, ColId, (long) val, len, Label)); if (val != NULL) DBUG_DUMP("value", (char*)val, len); diff --git a/ndb/src/ndbapi/NdbOperationSearch.cpp b/ndb/src/ndbapi/NdbOperationSearch.cpp index 4be7ccb313c..ede3240e9f4 100644 --- a/ndb/src/ndbapi/NdbOperationSearch.cpp +++ b/ndb/src/ndbapi/NdbOperationSearch.cpp @@ -58,10 +58,10 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo, Uint32 aVariableKeyLen) { DBUG_ENTER("NdbOperation::equal_impl"); - DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u", + DBUG_PRINT("enter", ("col: %s op: %d val: 0x%lx len: %u", tAttrInfo->m_name.c_str(), theOperationType, - aValuePassed, aVariableKeyLen)); + (long) aValuePassed, aVariableKeyLen)); if (aValuePassed != NULL) DBUG_DUMP("value", (char*)aValuePassed, aVariableKeyLen); diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index a0322f09256..92a1e476b45 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -653,9 +653,9 @@ NdbScanOperation::doSend(int ProcessorId) void NdbScanOperation::close(bool forceSend, bool releaseOp) { DBUG_ENTER("NdbScanOperation::close"); - DBUG_PRINT("enter", ("this=%x tcon=%x con=%x force=%d release=%d", - (UintPtr)this, - (UintPtr)m_transConnection, (UintPtr)theNdbCon, + DBUG_PRINT("enter", ("this: 0x%lx tcon: 0x%lx con: 0x%lx force: %d release: %d", + (long)this, + (long)m_transConnection, (long)theNdbCon, forceSend, releaseOp)); if(m_transConnection){ diff --git a/ndb/src/ndbapi/NdbTransaction.cpp b/ndb/src/ndbapi/NdbTransaction.cpp index 28bb9aeba55..483ef933caa 100644 --- a/ndb/src/ndbapi/NdbTransaction.cpp +++ b/ndb/src/ndbapi/NdbTransaction.cpp @@ -530,8 +530,8 @@ NdbTransaction::executeAsynchPrepare( ExecType aTypeOfExec, AbortOption abortOption) { DBUG_ENTER("NdbTransaction::executeAsynchPrepare"); - DBUG_PRINT("enter", ("aTypeOfExec: %d, aCallback: %x, anyObject: %x", - aTypeOfExec, aCallback, anyObject)); + DBUG_PRINT("enter", ("aTypeOfExec: %d, aCallback: 0x%lx, anyObject: Ox%lx", + aTypeOfExec, (long) aCallback, (long) anyObject)); /** * Reset error.code on execute @@ -923,7 +923,10 @@ NdbTransaction::release(){ * The user did not perform any rollback but simply closed the * transaction. We must rollback Ndb since Ndb have been contacted. ************************************************************************/ - execute(Rollback); + if (!theSimpleState) + { + execute(Rollback); + } }//if theMagicNumber = 0xFE11DC; theInUseState = false; @@ -1007,7 +1010,8 @@ void NdbTransaction::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp) { DBUG_ENTER("NdbTransaction::releaseExecutedScanOperation"); - DBUG_PRINT("enter", ("this=0x%x op=0x%x", (UintPtr)this, (UintPtr)cursorOp)); + DBUG_PRINT("enter", ("this: 0x%lx op=0x%lx", + (long)this, (long)cursorOp)); releaseScanOperation(&m_firstExecutedScanOp, 0, cursorOp); diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp index 6aaf44d0168..3ab9446e011 100644 --- a/ndb/src/ndbapi/Ndbif.cpp +++ b/ndb/src/ndbapi/Ndbif.cpp @@ -193,11 +193,11 @@ void Ndb::connected(Uint32 ref) ((Uint64)tmpTheNode << 40); theFirstTransId += theFacade->m_max_trans_id; // assert(0); - DBUG_PRINT("info",("connected with ref=%x, id=%d, no_db_nodes=%d, first_trans_id=%lx", + DBUG_PRINT("info",("connected with ref=%x, id=%d, no_db_nodes=%d, first_trans_id: 0x%lx", theMyRef, tmpTheNode, theImpl->theNoOfDBnodes, - theFirstTransId)); + (long) theFirstTransId)); theCommitAckSignal = new NdbApiSignal(theMyRef); theDictionary->m_receiver.m_reference= theMyRef; diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp index 40cac675b21..fbabe9e6dc6 100644 --- a/ndb/src/ndbapi/Ndbinit.cpp +++ b/ndb/src/ndbapi/Ndbinit.cpp @@ -39,7 +39,7 @@ Ndb::Ndb( Ndb_cluster_connection *ndb_cluster_connection, : theImpl(NULL) { DBUG_ENTER("Ndb::Ndb()"); - DBUG_PRINT("enter",("Ndb::Ndb this=0x%x", this)); + DBUG_PRINT("enter",("Ndb::Ndb this: 0x%lx", (long) this)); setup(ndb_cluster_connection, aDataBase, aSchema); DBUG_VOID_RETURN; } @@ -115,7 +115,7 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection, Ndb::~Ndb() { DBUG_ENTER("Ndb::~Ndb()"); - DBUG_PRINT("enter",("Ndb::~Ndb this=0x%x",this)); + DBUG_PRINT("enter",("Ndb::~Ndb this: 0x%lx",(long) this)); doDisconnect(); if (TransporterFacade::instance() != NULL && theNdbBlockNumber > 0){ diff --git a/ndb/src/ndbapi/Ndblist.cpp b/ndb/src/ndbapi/Ndblist.cpp index f82348fc91d..00ab4599fdf 100644 --- a/ndb/src/ndbapi/Ndblist.cpp +++ b/ndb/src/ndbapi/Ndblist.cpp @@ -361,7 +361,7 @@ void Ndb::releaseScanOperation(NdbIndexScanOperation* aScanOperation) { DBUG_ENTER("Ndb::releaseScanOperation"); - DBUG_PRINT("enter", ("op=%x", (UintPtr)aScanOperation)); + DBUG_PRINT("enter", ("op: 0x%lx", (long)aScanOperation)); #ifdef ndb_release_check_dup { NdbIndexScanOperation* tOp = theScanOpIdleList; while (tOp != NULL) { diff --git a/ndb/src/ndbapi/ndb_cluster_connection.cpp b/ndb/src/ndbapi/ndb_cluster_connection.cpp index 1e53558f179..3ae84125112 100644 --- a/ndb/src/ndbapi/ndb_cluster_connection.cpp +++ b/ndb/src/ndbapi/ndb_cluster_connection.cpp @@ -262,7 +262,7 @@ Ndb_cluster_connection_impl::Ndb_cluster_connection_impl(const char * m_name(0) { DBUG_ENTER("Ndb_cluster_connection"); - DBUG_PRINT("enter",("Ndb_cluster_connection this=0x%x", this)); + DBUG_PRINT("enter",("Ndb_cluster_connection this=0x%lx", (long) this)); g_eventLogger.createConsoleHandler(); g_eventLogger.setCategory("NdbApi"); diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index 6173292261d..660117ed4c2 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -278,6 +278,7 @@ ErrorBundle ErrorCodes[] = { { 885, AE, "Stack underflow in interpreter" }, { 886, AE, "More than 65535 instructions executed in interpreter" }, { 897, AE, "Update attempt of primary key via ndbcluster internal api (if this occurs via the MySQL server it is a bug, please report)" }, + { 892, AE, "Unsupported type in scan filter" }, { 4256, AE, "Must call Ndb::init() before this function" }, { 4257, AE, "Tried to read too much - too many getValue calls" }, @@ -680,11 +681,14 @@ const char *ndberror_classification_message(ndberror_classification classificati return empty_string; } -int ndb_error_string(int err_no, char *str, unsigned int size) +int ndb_error_string(int err_no, char *str, int size) { ndberror_struct error; - unsigned int len; + int len; + assert(size > 1); + if(size <= 1) + return 0; error.code = err_no; ndberror_update(&error); diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp index ba05bbad7bb..a8e28742757 100644 --- a/ndb/test/ndbapi/testDict.cpp +++ b/ndb/test/ndbapi/testDict.cpp @@ -1893,7 +1893,7 @@ runDictOps(NDBT_Context* ctx, NDBT_Step* step) // create indexes const char** indlist = NDBT_Tables::getIndexes(tabName); uint indnum = 0; - while (*indlist != 0) { + while (indlist != 0 && *indlist != 0) { uint count = 0; try_create_index: count++; diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp index c1502940655..082013f07cc 100644 --- a/ndb/test/ndbapi/testNodeRestart.cpp +++ b/ndb/test/ndbapi/testNodeRestart.cpp @@ -23,6 +23,7 @@ #include <Vector.hpp> #include <signaldata/DumpStateOrd.hpp> #include <Bitmask.hpp> +#include <RefConvert.hpp> int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){ @@ -919,6 +920,41 @@ int runBug20185(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int runBug24717(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + NdbRestarter restarter; + Ndb* pNdb = GETNDB(step); + + HugoTransactions hugoTrans(*ctx->getTab()); + + int dump[] = { 9002, 0 } ; + Uint32 ownNode = refToNode(pNdb->getReference()); + dump[1] = ownNode; + + for (; loops; loops --) + { + int nodeId = restarter.getRandomNotMasterNodeId(rand()); + restarter.restartOneDbNode(nodeId, false, true, true); + restarter.waitNodesNoStart(&nodeId, 1); + + if (restarter.dumpStateOneNode(nodeId, dump, 2)) + return NDBT_FAILED; + + restarter.startNodes(&nodeId, 1); + + for (Uint32 i = 0; i < 100; i++) + { + hugoTrans.pkReadRecords(pNdb, 100, 1, NdbOperation::LM_CommittedRead); + } + + restarter.waitClusterStarted(); + } + + return NDBT_OK; +} + NDBT_TESTSUITE(testNodeRestart); TESTCASE("NoLoad", @@ -1232,6 +1268,9 @@ TESTCASE("Bug20185", STEP(runBug20185); FINALIZER(runClearTable); } +TESTCASE("Bug24717", ""){ + INITIALIZER(runBug24717); +} NDBT_TESTSUITE_END(testNodeRestart); int main(int argc, const char** argv){ diff --git a/ndb/test/ndbapi/testScan.cpp b/ndb/test/ndbapi/testScan.cpp index 2802f1c950e..882ed649b9a 100644 --- a/ndb/test/ndbapi/testScan.cpp +++ b/ndb/test/ndbapi/testScan.cpp @@ -630,7 +630,7 @@ int runRestarter(NDBT_Context* ctx, NDBT_Step* step){ int nodeId = restarter.getDbNodeId(lastId); lastId = (lastId + 1) % restarter.getNumDbNodes(); - if(restarter.restartOneDbNode(nodeId) != 0){ + if(restarter.restartOneDbNode(nodeId, false, false, true) != 0){ g_err << "Failed to restartNextDbNode" << endl; result = NDBT_FAILED; break; @@ -1125,6 +1125,39 @@ runScanParallelism(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int +runBug24447(NDBT_Context* ctx, NDBT_Step* step){ + int loops = 1; //ctx->getNumLoops(); + int records = ctx->getNumRecords(); + int abort = ctx->getProperty("AbortProb", 15); + NdbRestarter restarter; + HugoTransactions hugoTrans(*ctx->getTab()); + int i = 0; + while (i<loops && !ctx->isTestStopped()) + { + g_info << i++ << ": "; + + int nodeId = restarter.getRandomNotMasterNodeId(rand()); + if (nodeId == -1) + nodeId = restarter.getMasterNodeId(); + if (restarter.insertErrorInNode(nodeId, 8038) != 0) + { + ndbout << "Could not insert error in node="<<nodeId<<endl; + return NDBT_FAILED; + } + + for (Uint32 j = 0; i<10; i++) + { + hugoTrans.scanReadRecords(GETNDB(step), records, abort, 0, + NdbOperation::LM_CommittedRead); + } + + } + restarter.insertErrorInAllNodes(0); + + return NDBT_OK; +} + NDBT_TESTSUITE(testScan); TESTCASE("ScanRead", "Verify scan requirement: It should be possible "\ @@ -1603,6 +1636,12 @@ TESTCASE("ScanParallelism", STEP(runScanParallelism); FINALIZER(runClearTable); } +TESTCASE("Bug24447", + ""){ + INITIALIZER(runLoadTable); + STEP(runBug24447); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testScan); int main(int argc, const char** argv){ diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index a544355abd6..bbfc2f630b9 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -414,6 +414,10 @@ cmd: testScan args: -n ScanParallelism max-time: 500 +cmd: testScan +args: -n Bug24447 T1 + +max-time: 500 cmd: testNodeRestart args: -n Bug15587 T1 @@ -453,6 +457,10 @@ max-time: 1000 cmd: testIndex args: -n Bug21384 +max-time: 1000 +cmd: testNodeRestart +args: -n Bug24717 T1 + # OLD FLEX max-time: 500 cmd: flexBench @@ -510,7 +518,7 @@ args: -n TemporaryTables T1 T6 T7 T8 max-time: 1500 cmd: testDict -args: -n Restart_NR2 T1 +args: -n Restart_NR2 T1 I3 # # TEST NDBAPI diff --git a/ndb/tools/drop_index.cpp b/ndb/tools/drop_index.cpp index aa207212dbe..c10211a9108 100644 --- a/ndb/tools/drop_index.cpp +++ b/ndb/tools/drop_index.cpp @@ -51,9 +51,6 @@ int main(int argc, char** argv){ NDB_INIT(argv[0]); load_defaults("my",load_default_groups,&argc,&argv); int ho_error; -#ifndef DBUG_OFF - "d:t:O,/tmp/ndb_drop_index.trace"; -#endif if ((ho_error=handle_options(&argc, &argv, my_long_options, ndb_std_get_one_option))) return NDBT_ProgramExit(NDBT_WRONGARGS); diff --git a/ndb/tools/drop_tab.cpp b/ndb/tools/drop_tab.cpp index d14c60a2c6d..61df4ee9b34 100644 --- a/ndb/tools/drop_tab.cpp +++ b/ndb/tools/drop_tab.cpp @@ -51,9 +51,6 @@ int main(int argc, char** argv){ NDB_INIT(argv[0]); load_defaults("my",load_default_groups,&argc,&argv); int ho_error; -#ifndef DBUG_OFF - "d:t:O,/tmp/ndb_drop_table.trace"; -#endif if ((ho_error=handle_options(&argc, &argv, my_long_options, ndb_std_get_one_option))) return NDBT_ProgramExit(NDBT_WRONGARGS); diff --git a/ndb/tools/ndb_config.cpp b/ndb/tools/ndb_config.cpp index 8b862391c8e..c65f7157c15 100644 --- a/ndb/tools/ndb_config.cpp +++ b/ndb/tools/ndb_config.cpp @@ -37,7 +37,6 @@ static int g_verbose = 0; static int try_reconnect = 3; static int g_nodes, g_connections, g_section; -static const char * g_connectstring = 0; static const char * g_query = 0; static int g_nodeid = 0; @@ -114,6 +113,7 @@ struct Match int m_key; BaseString m_value; virtual int eval(const Iter&); + virtual ~Match() {} }; struct HostMatch : public Match @@ -127,6 +127,7 @@ struct Apply Apply(int val) { m_key = val;} int m_key; virtual int apply(const Iter&); + virtual ~Apply() {} }; struct NodeTypeApply : public Apply @@ -484,7 +485,7 @@ fetch_configuration() ndb_mgm_set_error_stream(mgm, stderr); - if (ndb_mgm_set_connectstring(mgm, g_connectstring)) + if (ndb_mgm_set_connectstring(mgm, opt_connect_str)) { fprintf(stderr, "* %5d: %s\n", ndb_mgm_get_latest_error(mgm), diff --git a/netware/BUILD/nwbootstrap b/netware/BUILD/nwbootstrap index 48ff2a49667..e0c0b926619 100755 --- a/netware/BUILD/nwbootstrap +++ b/netware/BUILD/nwbootstrap @@ -25,7 +25,7 @@ revision="" rev="" build="" suffix="" -mwenv="" +#obsolete mwenv="" # show usage show_usage() @@ -151,14 +151,14 @@ echo "making files writable..." cd $target_dir chmod -R u+rw,g+rw . -# edit the mvenv file -echo "updating the mwenv environment file..." -mwenv="./netware/BUILD/mwenv" -mv -f $mwenv $mwenv.org -sed -e "s;WINE_BUILD_DIR;$wine_build_dir;g" \ - -e "s;BUILD_DIR;$build_dir;g" \ - -e "s;VERSION;$version;g" $mwenv.org > $mwenv -chmod +rwx $mwenv +#obsolete # edit the mvenv file +#obsolete echo "updating the mwenv environment file..." +#obsolete mwenv="./netware/BUILD/mwenv" +#obsolete mv -f $mwenv $mwenv.org +#obsolete sed -e "s;WINE_BUILD_DIR;$wine_build_dir;g" \ +#obsolete -e "s;BUILD_DIR;$build_dir;g" \ +#obsolete -e "s;VERSION;$version;g" $mwenv.org > $mwenv +#obsolete chmod +rwx $mwenv # edit the def file versions echo "updating *.def file versions..." diff --git a/netware/Makefile.am b/netware/Makefile.am index 648ce79c484..de39376f6a1 100644 --- a/netware/Makefile.am +++ b/netware/Makefile.am @@ -30,6 +30,8 @@ netware_build_files = client/mysql.def client/mysqladmin.def \ client/mysqlbinlog.def client/mysqlcheck.def \ client/mysqldump.def client/mysqlimport.def \ client/mysqlshow.def client/mysqltest.def \ + client/mysql_upgrade.def \ + tests/mysql_client_test.def \ extra/my_print_defaults.def \ extra/perror.def extra/replace.def \ extra/resolveip.def extra/comp_err.def \ @@ -69,7 +71,8 @@ EXTRA_DIST= $(BUILT_SOURCES) comp_err.def init_db.sql install_test_db.ncf \ mysql_test_run.def mysql_waitpid.def mysqladmin.def \ mysqlbinlog.def mysqlcheck.def mysqld.def \ mysqld_safe.c mysqld_safe.def mysqldump.def mysqlimport.def \ - mysqlshow.def mysqltest.def perror.def \ + mysqlshow.def mysqltest.def mysql_upgrade.def perror.def \ + mysql_client_test.def \ replace.def resolve_stack_dump.def resolveip.def test_db.sql \ static_init_db.sql \ BUILD/apply-patch BUILD/compile-AUTOTOOLS \ diff --git a/netware/comp_err.def b/netware/comp_err.def index f27b40c7b78..f5b18bbdb9a 100644 --- a/netware/comp_err.def +++ b/netware/comp_err.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 File Compiler" VERSION 4, 0 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/isamchk.def b/netware/isamchk.def index 31cf3fc569a..8ae2c0ca96c 100644 --- a/netware/isamchk.def +++ b/netware/isamchk.def @@ -6,7 +6,7 @@ SCREENNAME "MySQL ISAM Table Check Tool" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL ISAM Table Check Tool" VERSION 4, 0 -STACKSIZE 65536 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/isamlog.def b/netware/isamlog.def index 52f9de0d928..777d73a7835 100644 --- a/netware/isamlog.def +++ b/netware/isamlog.def @@ -5,6 +5,7 @@ MODULE libc.nlm COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL ISAM Table Log Tool" VERSION 4, 0 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/libmysql.def b/netware/libmysql.def index 8a34754e092..d9d4c752612 100644 --- a/netware/libmysql.def +++ b/netware/libmysql.def @@ -7,6 +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 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/my_print_defaults.def b/netware/my_print_defaults.def index 778a5204ebd..acba6c81b49 100644 --- a/netware/my_print_defaults.def +++ b/netware/my_print_defaults.def @@ -5,7 +5,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, 17 -STACKSIZE 32767 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/myisam_ftdump.def b/netware/myisam_ftdump.def index 9639404b53b..78123537a54 100644 --- a/netware/myisam_ftdump.def +++ b/netware/myisam_ftdump.def @@ -6,7 +6,7 @@ SCREENNAME "MySQL MyISAM Table Dump Tool" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL MyISAM Table Dump Tool" VERSION 4, 0 -STACKSIZE 65536 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/myisamchk.def b/netware/myisamchk.def index b7ec5ac9474..9805eb4ec1b 100644 --- a/netware/myisamchk.def +++ b/netware/myisamchk.def @@ -6,7 +6,7 @@ SCREENNAME "MySQL MyISAM Table Check Tool[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL MyISAM Table Check Tool" VERSION 4, 0 -STACKSIZE 65536 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/myisamlog.def b/netware/myisamlog.def index 553a818a2ae..925650eac7b 100644 --- a/netware/myisamlog.def +++ b/netware/myisamlog.def @@ -6,7 +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 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/myisampack.def b/netware/myisampack.def index d1f85fe03f8..877a143fd2e 100644 --- a/netware/myisampack.def +++ b/netware/myisampack.def @@ -6,7 +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 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysql.def b/netware/mysql.def index 16acc7babe1..4e44f4882d1 100644 --- a/netware/mysql.def +++ b/netware/mysql.def @@ -6,7 +6,7 @@ SCREENNAME "MySQL Monitor[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Monitor" VERSION 4, 0 -STACKSIZE 32768 +STACKSIZE 131072 MULTIPLE XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysql_client_test.def b/netware/mysql_client_test.def new file mode 100644 index 00000000000..9a6f63ec4d7 --- /dev/null +++ b/netware/mysql_client_test.def @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------------ +# MySQL Test +#------------------------------------------------------------------------------ +MODULE libc.nlm +COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." +DESCRIPTION "MySQL Client Test" +VERSION 4, 0 +STACKSIZE 131072 +XDCDATA ../netware/mysql.xdc +#DEBUG diff --git a/netware/mysql_install_db.def b/netware/mysql_install_db.def index 372bbf15570..e3dc57fe44c 100644 --- a/netware/mysql_install_db.def +++ b/netware/mysql_install_db.def @@ -6,7 +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 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysql_test_run.def b/netware/mysql_test_run.def index d4d4baee168..c8afd305978 100644 --- a/netware/mysql_test_run.def +++ b/netware/mysql_test_run.def @@ -2,10 +2,10 @@ # MySQL Test Run #------------------------------------------------------------------------------ MODULE libc.nlm -STACKSIZE 65536 SCREENNAME "MySQL Test Run" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Test Run" VERSION 4, 0 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysql_upgrade.def b/netware/mysql_upgrade.def new file mode 100644 index 00000000000..7b5718ffb1b --- /dev/null +++ b/netware/mysql_upgrade.def @@ -0,0 +1,11 @@ +#------------------------------------------------------------------------------ +# MySQL Admin +#------------------------------------------------------------------------------ +MODULE libc.nlm +COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." +DESCRIPTION "MySQL Upgrade Tool" +VERSION 4, 0 +STACKSIZE 131072 +XDCDATA ../netware/mysql.xdc +#DEBUG + diff --git a/netware/mysql_waitpid.def b/netware/mysql_waitpid.def index da0884ccba3..6e9cc76f139 100644 --- a/netware/mysql_waitpid.def +++ b/netware/mysql_waitpid.def @@ -6,7 +6,7 @@ MODULE libc.nlm COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Tool - Wait for a Program to Terminate" VERSION 4, 0 -STACKSIZE 65536 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqladmin.def b/netware/mysqladmin.def index 6532cab84a0..03f15dfdd08 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 32768 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqlbinlog.def b/netware/mysqlbinlog.def index aced63429c5..88024acc318 100644 --- a/netware/mysqlbinlog.def +++ b/netware/mysqlbinlog.def @@ -6,7 +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 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqlcheck.def b/netware/mysqlcheck.def index 1b90b2a1dbe..b9028c237d1 100644 --- a/netware/mysqlcheck.def +++ b/netware/mysqlcheck.def @@ -6,7 +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 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqld.def b/netware/mysqld.def index 42c2d176a1b..bb7b8129983 100644 --- a/netware/mysqld.def +++ b/netware/mysqld.def @@ -6,7 +6,7 @@ COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Res DESCRIPTION "MySQL Database Server" VERSION 4, 0 MULTIPLE -STACKSIZE 65536 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqld_safe.def b/netware/mysqld_safe.def index ff3f1924906..5c436cc97ca 100644 --- a/netware/mysqld_safe.def +++ b/netware/mysqld_safe.def @@ -6,7 +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 +STACKSIZE 131072 MULTIPLE XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqldump.def b/netware/mysqldump.def index 5d7999c789f..2e745492cf3 100644 --- a/netware/mysqldump.def +++ b/netware/mysqldump.def @@ -6,7 +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 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqlimport.def b/netware/mysqlimport.def index f98d8021a73..5db6b940ce7 100644 --- a/netware/mysqlimport.def +++ b/netware/mysqlimport.def @@ -6,7 +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 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqlshow.def b/netware/mysqlshow.def index b7b84a94067..386cb98c091 100644 --- a/netware/mysqlshow.def +++ b/netware/mysqlshow.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Show[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Show Tool" VERSION 4, 0 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqltest.def b/netware/mysqltest.def index e134acede07..f0ee5f7e6a4 100644 --- a/netware/mysqltest.def +++ b/netware/mysqltest.def @@ -5,6 +5,7 @@ MODULE libc.nlm COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Test Case Tool" VERSION 4, 0 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/pack_isam.def b/netware/pack_isam.def index 9ea72a4f2e7..514b57b04bd 100644 --- a/netware/pack_isam.def +++ b/netware/pack_isam.def @@ -7,6 +7,7 @@ COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Res DESCRIPTION "MySQL ISAM Table Pack Tool" SCREENNAME "MySQL ISAM Table Pack Tool" VERSION 4, 0 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/perror.def b/netware/perror.def index d67bd6191b4..fc95de3476a 100644 --- a/netware/perror.def +++ b/netware/perror.def @@ -5,7 +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 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/replace.def b/netware/replace.def index 19348ee4245..7feccdbff41 100644 --- a/netware/replace.def +++ b/netware/replace.def @@ -5,6 +5,7 @@ MODULE libc.nlm COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Text Replacement Tool" VERSION 4, 0 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/resolve_stack_dump.def b/netware/resolve_stack_dump.def index 01042699d61..20098c1b4e0 100644 --- a/netware/resolve_stack_dump.def +++ b/netware/resolve_stack_dump.def @@ -6,7 +6,7 @@ MODULE libc.nlm COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Stack Dump Resolve Tool" VERSION 4, 0 -STACKSIZE 65536 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/resolveip.def b/netware/resolveip.def index 244f52bb969..1962d61be53 100644 --- a/netware/resolveip.def +++ b/netware/resolveip.def @@ -5,6 +5,7 @@ MODULE libc.nlm COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL IP/Hostname Resolve Tool" VERSION 4, 0 +STACKSIZE 131072 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/regex/regexec.c b/regex/regexec.c index 88bcc02323d..338c1bfa7fe 100644 --- a/regex/regexec.c +++ b/regex/regexec.c @@ -15,7 +15,8 @@ #include "utils.h" #include "regex2.h" -static int nope = 0; /* for use in asserts; shuts lint up */ +/* for use in asserts */ +#define nope 0 /* macros for manipulating states, small version */ #define states long diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 512e8a574ed..ec1c6b70bb6 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -240,11 +240,12 @@ $CP mysql-test/lib/*.pl $BASE/mysql-test/lib $CP mysql-test/lib/*.sql $BASE/mysql-test/lib $CP mysql-test/t/*.def $BASE/mysql-test/t $CP mysql-test/include/*.inc $BASE/mysql-test/include +$CP mysql-test/include/*.test $BASE/mysql-test/include $CP mysql-test/t/*.def $BASE/mysql-test/t $CP mysql-test/std_data/*.dat mysql-test/std_data/*.frm \ mysql-test/std_data/*.pem mysql-test/std_data/Moscow_leap \ mysql-test/std_data/des_key_file mysql-test/std_data/*.*001 \ - mysql-test/std_data/*.cnf \ + mysql-test/std_data/*.cnf mysql-test/std_data/*.MY* \ $BASE/mysql-test/std_data $CP mysql-test/t/*.test mysql-test/t/*.imtest \ mysql-test/t/*.disabled mysql-test/t/*.opt \ diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index 3044e51a4fd..5709fb96793 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -1,5 +1,5 @@ -- This script converts any old privilege tables to privilege tables suitable --- for MySQL 4.0. +-- for MySQL 4.1 -- You can safely ignore all 'Duplicate column' and 'Unknown column' errors" -- because these just mean that your tables are already up to date. @@ -46,9 +46,8 @@ ADD x509_subject BLOB NOT NULL; ALTER TABLE user MODIFY ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL; -- --- Create tables_priv and columns_priv if they don't exists +-- tables_priv -- - CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, @@ -56,22 +55,38 @@ CREATE TABLE IF NOT EXISTS tables_priv ( Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp(14), - Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') COLLATE utf8_general_ci DEFAULT '' NOT NULL, - Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, + Table_priv set('Select','Insert','Update','Delete','Create', + 'Drop','Grant','References','Index','Alter') + COLLATE utf8_general_ci DEFAULT '' NOT NULL, + Column_priv set('Select','Insert','Update','References') + COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name) ) CHARACTER SET utf8 COLLATE utf8_bin; --- Fix collation of set fields + ALTER TABLE tables_priv - modify Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') COLLATE utf8_general_ci DEFAULT '' NOT NULL, - modify Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL; -ALTER TABLE procs_priv ENGINE=MyISAM, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; -ALTER TABLE procs_priv - modify Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL; -ALTER TABLE procs_priv - add Routine_type enum('FUNCTION','PROCEDURE') COLLATE utf8_general_ci NOT NULL AFTER Routine_name; -ALTER TABLE procs_priv - modify Timestamp timestamp(14) AFTER Proc_priv; + ADD KEY Grantor (Grantor); + +ALTER TABLE tables_priv + MODIFY Host char(60) NOT NULL default '', + MODIFY Db char(64) NOT NULL default '', + MODIFY User char(16) NOT NULL default '', + MODIFY Table_name char(64) NOT NULL default '', + MODIFY Grantor char(77) NOT NULL default '', + ENGINE=MyISAM, + CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; +ALTER TABLE tables_priv + MODIFY Column_priv set('Select','Insert','Update','References') + COLLATE utf8_general_ci DEFAULT '' NOT NULL, + MODIFY Table_priv set('Select','Insert','Update','Delete','Create', + 'Drop','Grant','References','Index','Alter', + 'Create View','Show view') + COLLATE utf8_general_ci DEFAULT '' NOT NULL, + COMMENT='Table privileges'; + +-- +-- columns_priv +-- CREATE TABLE IF NOT EXISTS columns_priv ( Host char(60) DEFAULT '' NOT NULL, Db char(64) DEFAULT '' NOT NULL, @@ -82,16 +97,25 @@ CREATE TABLE IF NOT EXISTS columns_priv ( Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) CHARACTER SET utf8 COLLATE utf8_bin; --- Fix collation of set fields -ALTER TABLE columns_priv - MODIFY Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL; - --- -- Name change of Type -> Column_priv from MySQL 3.22.12 --- +ALTER TABLE columns_priv + CHANGE Type Column_priv set('Select','Insert','Update','References') + COLLATE utf8_general_ci DEFAULT '' NOT NULL; -ALTER TABLE columns_priv change Type Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL; +ALTER TABLE columns_priv + MODIFY Host char(60) NOT NULL default '', + MODIFY Db char(64) NOT NULL default '', + MODIFY User char(16) NOT NULL default '', + MODIFY Table_name char(64) NOT NULL default '', + MODIFY Column_name char(64) NOT NULL default '', + ENGINE=MyISAM, + CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin, + COMMENT='Column privileges'; + +ALTER TABLE columns_priv + MODIFY Column_priv set('Select','Insert','Update','References') + COLLATE utf8_general_ci DEFAULT '' NOT NULL; -- -- Add the new 'type' column to the func table. @@ -100,7 +124,7 @@ ALTER TABLE columns_priv change Type Column_priv set('Select','Insert','Update', ALTER TABLE func add type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL; -- --- Change the user,db and host tables to MySQL 4.0 format +-- Change the user,db and host tables to current format -- # Detect whether we had Show_db_priv @@ -142,14 +166,12 @@ ADD Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT ADD Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; alter table user change max_questions max_questions int(11) unsigned DEFAULT 0 NOT NULL; -alter table tables_priv add KEY Grantor (Grantor); + alter table db comment='Database privileges'; alter table host comment='Host privileges; Merged with database privileges'; alter table user comment='Users and global privileges'; alter table func comment='User defined functions'; -alter table tables_priv comment='Table privileges'; -alter table columns_priv comment='Column privileges'; -- Convert all tables to UTF-8 with binary collation -- and reset all char columns to correct width @@ -223,25 +245,6 @@ ALTER TABLE func ENGINE=MyISAM, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; ALTER TABLE func MODIFY type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL; -ALTER TABLE columns_priv - MODIFY Host char(60) NOT NULL default '', - MODIFY Db char(64) NOT NULL default '', - MODIFY User char(16) NOT NULL default '', - MODIFY Table_name char(64) NOT NULL default '', - MODIFY Column_name char(64) NOT NULL default '', - ENGINE=MyISAM, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; -ALTER TABLE columns_priv - MODIFY Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL; -ALTER TABLE tables_priv - MODIFY Host char(60) NOT NULL default '', - MODIFY Db char(64) NOT NULL default '', - MODIFY User char(16) NOT NULL default '', - MODIFY Table_name char(64) NOT NULL default '', - MODIFY Grantor char(77) NOT NULL default '', - ENGINE=MyISAM, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; -ALTER TABLE tables_priv - MODIFY Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') COLLATE utf8_general_ci DEFAULT '' NOT NULL, - MODIFY Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL; # # Detect whether we had Create_view_priv @@ -274,11 +277,6 @@ ALTER TABLE user ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAUL ALTER TABLE user MODIFY Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv; # -# Show/Create views table privileges (v5.0) -# -ALTER TABLE tables_priv MODIFY Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL; - -# # Assign create/show view privileges to people who have create provileges # UPDATE user SET Create_view_priv=Create_priv, Show_view_priv=Create_priv where user<>"" AND @hadCreateViewPriv = 0; @@ -344,22 +342,41 @@ UPDATE user LEFT JOIN db USING (Host,User) SET Create_user_priv='Y' WHERE @hadCreateUserPriv = 0 AND (user.Grant_priv = 'Y' OR db.Grant_priv = 'Y'); -# -# Create some possible missing tables -# +-- +-- procs_priv +-- CREATE TABLE IF NOT EXISTS procs_priv ( -Host char(60) binary DEFAULT '' NOT NULL, -Db char(64) binary DEFAULT '' NOT NULL, -User char(16) binary DEFAULT '' NOT NULL, -Routine_name char(64) binary DEFAULT '' NOT NULL, -Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, -Grantor char(77) DEFAULT '' NOT NULL, -Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, -Timestamp timestamp(14), -PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), -KEY Grantor (Grantor) + Host char(60) binary DEFAULT '' NOT NULL, + Db char(64) binary DEFAULT '' NOT NULL, + User char(16) binary DEFAULT '' NOT NULL, + Routine_name char(64) binary DEFAULT '' NOT NULL, + Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, + Grantor char(77) DEFAULT '' NOT NULL, + Proc_priv set('Execute','Alter Routine','Grant') + COLLATE utf8_general_ci DEFAULT '' NOT NULL, + Timestamp timestamp(14), + PRIMARY KEY (Host, Db, User, Routine_name, Routine_type), + KEY Grantor (Grantor) ) CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; +ALTER TABLE procs_priv + ENGINE=MyISAM, + CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; + +ALTER TABLE procs_priv + MODIFY Proc_priv set('Execute','Alter Routine','Grant') + COLLATE utf8_general_ci DEFAULT '' NOT NULL; + +ALTER TABLE procs_priv + ADD Routine_type enum('FUNCTION','PROCEDURE') + COLLATE utf8_general_ci NOT NULL AFTER Routine_name; + +ALTER TABLE procs_priv + MODIFY Timestamp timestamp(14) AFTER Proc_priv; + +-- +-- help_topic +-- CREATE TABLE IF NOT EXISTS help_topic ( help_topic_id int unsigned not null, name varchar(64) not null, @@ -435,7 +452,7 @@ PRIMARY KEY TranTime (Transition_time) # -# Create proc table if it doesn't exists +# Create proc table if it does not exists # CREATE TABLE IF NOT EXISTS proc ( diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 5d7933e5277..e43b586054e 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -33,6 +33,7 @@ parse_arguments() { case "$arg" in --force) force=1 ;; --basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; + --srcdir=*) srcdir=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; --ldata=*|--datadir=*) ldata=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; --user=*) # Note that the user will be passed to mysqld so that it runs @@ -78,6 +79,7 @@ ldata= execdir= bindir= basedir= +srcdir= force=0 verbose=0 fill_help_tables="" @@ -106,18 +108,24 @@ else fi # find fill_help_tables.sh -for i in $basedir/support-files $basedir/share $basedir/share/mysql $basedir/scripts `pwd` `pwd`/scripts @pkgdatadir@ -do - if test -f $i/fill_help_tables.sql - then - pkgdatadir=$i - fi -done - -if test -f $pkgdatadir/fill_help_tables.sql +if test -n "$srcdir" then - fill_help_tables=$pkgdatadir/fill_help_tables.sql + fill_help_tables=$srcdir/scripts/fill_help_tables.sql else + for i in $basedir/support-files $basedir/share $basedir/share/mysql \ + $basedir/scripts `pwd` `pwd`/scripts @pkgdatadir@ + do + if test -f $i/fill_help_tables.sql + then + pkgdatadir=$i + fi + done + + fill_help_tables=$pkgdatadir/fill_help_tables.sql +fi + +if test ! -f $fill_help_tables +then echo "Could not find help file 'fill_help_tables.sql' in @pkgdatadir@ or inside $basedir". exit 1; fi @@ -130,7 +138,13 @@ scriptdir=$bindir if test "$windows" = 1 then mysqld="./sql/mysqld" - mysqld_opt="--language=./sql/share/english" + if test -n "$srcdir" -a -f $srcdir/sql/share/english/errmsg.sys + then + langdir=$srcdir/sql/share/english + else + langdir=./sql/share/english + fi + mysqld_opt="--language=$langdir" scriptdir="./scripts" fi diff --git a/scripts/mysqlbug.sh b/scripts/mysqlbug.sh index 6aed140b79d..880ab248a90 100644 --- a/scripts/mysqlbug.sh +++ b/scripts/mysqlbug.sh @@ -132,7 +132,13 @@ if test -z "$VISUAL" then if test -z "$EDITOR" then - EDIT=emacs + # Honor debian sensible-editor + if test -x "/usr/bin/sensible-editor" + then + EDIT=/usr/bin/sensible-editor + else + EDIT=emacs + fi else EDIT="$EDITOR" fi diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 2dcc8dc7bc4..c9c0b21b584 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -472,6 +472,14 @@ sub find_groups { $data[$i] = $line; } + if (-f "/etc/mysql/my.cnf" && -r "/etc/mysql/my.cnf") + { + open(MY_CNF, "</etc/mysql/my.cnf") && (@tmp=<MY_CNF>) && close(MY_CNF); + } + for (; ($line = shift @tmp); $i++) + { + $data[$i] = $line; + } if (defined($ENV{MYSQL_HOME}) && -f "$ENV{MYSQL_HOME}/my.cnf" && -r "$ENV{MYSQL_HOME}/my.cnf") { @@ -482,6 +490,14 @@ sub find_groups { $data[$i] = $line; } + if (-f "/etc/mysql/my.cnf" && -r "/etc/mysql/my.cnf") + { + open(MY_CNF, "</etc/mysql/my.cnf") && (@tmp=<MY_CNF>) && close(MY_CNF); + } + for (; ($line = shift @tmp); $i++) + { + $data[$i] = $line; + } if (-f "$homedir/.my.cnf" && -r "$homedir/.my.cnf") { open(MY_CNF, "<$homedir/.my.cnf") && (@tmp=<MY_CNF>) && close(MY_CNF); @@ -491,7 +507,7 @@ sub find_groups $data[$i] = $line; } } - chop @data; + chomp @data; # Make a list of the wanted group ids if (defined($raw_gids)) { diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 02a961dc3ec..52fe282f916 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -211,6 +211,7 @@ if [ ! -d $mysql_unix_port_dir ] then mkdir $mysql_unix_port_dir chown $user $mysql_unix_port_dir + chmod 755 $mysql_unix_port_dir fi # Use the mysqld-max binary by default if the user doesn't specify a binary diff --git a/scripts/mysqldumpslow.sh b/scripts/mysqldumpslow.sh index ccb006f692d..ff82a35ec3f 100644 --- a/scripts/mysqldumpslow.sh +++ b/scripts/mysqldumpslow.sh @@ -40,6 +40,7 @@ unless (@ARGV) { warn "basedir=$basedir\n" if $opt{v}; my $datadir = ($defaults =~ m/--datadir=(.*)/)[0]; + my $slowlog = ($defaults =~ m/--log-slow-queries=(.*)/)[0]; if (!$datadir or $opt{i}) { # determine the datadir from the instances section of /etc/my.cnf, if any my $instances = `my_print_defaults instances`; @@ -55,8 +56,13 @@ unless (@ARGV) { warn "datadir=$datadir\n" if $opt{v}; } - @ARGV = <$datadir/$opt{h}-slow.log>; - die "Can't find '$datadir/$opt{h}-slow.log'\n" unless @ARGV; + if ( -f $slowlog ) { + @ARGV = ($slowlog); + die "Can't find '$slowlog'\n" unless @ARGV; + } else { + @ARGV = <$datadir/$opt{h}-slow.log>; + die "Can't find '$datadir/$opt{h}-slow.log'\n" unless @ARGV; + } } warn "\nReading mysql slow query log from @ARGV\n"; diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index 3587a599160..9fabb1923a8 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -222,17 +222,14 @@ void Guardian_thread::run() while (node != NULL) { - struct timespec timeout; - GUARD_NODE *current_node= (GUARD_NODE *) node->data; instance= ((GUARD_NODE *) node->data)->instance; process_instance(instance, current_node, &guarded_instances, node); node= node->next; } - timeout.tv_sec= time(NULL) + monitoring_interval; - timeout.tv_nsec= 0; - + set_timespec(timeout, monitoring_interval); + /* check the loop predicate before sleeping */ if (!(shutdown_requested && (!(guarded_instances)))) thread_registry.cond_timedwait(&thread_info, &COND_guardian, diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index daa8082ef2f..39793b9a234 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -476,10 +476,9 @@ int Instance::stop() waitchild= options.shutdown_delay_val; kill_instance(SIGTERM); - /* sleep on condition to wait for SIGCHLD */ - timeout.tv_sec= time(NULL) + waitchild; - timeout.tv_nsec= 0; + /* sleep on condition to wait for SIGCHLD */ + set_timespec(timeout, waitchild); if (pthread_mutex_lock(&LOCK_instance)) return ER_STOP_INSTANCE; diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc index bf39c843f0a..a19914dfdd2 100644 --- a/server-tools/instance-manager/mysql_connection.cc +++ b/server-tools/instance-manager/mysql_connection.cc @@ -163,7 +163,7 @@ Mysql_connection_thread::~Mysql_connection_thread() void Mysql_connection_thread::run() { - log_info("accepted mysql connection %d", connection_id); + log_info("accepted mysql connection %lu", connection_id); my_thread_init(); @@ -173,7 +173,7 @@ void Mysql_connection_thread::run() return; } - log_info("connection %d is checked successfully", connection_id); + log_info("connection %lu is checked successfully", connection_id); vio_keepalive(vio, TRUE); @@ -312,7 +312,7 @@ int Mysql_connection_thread::do_command() packet= (char*) net.read_pos; enum enum_server_command command= (enum enum_server_command) (uchar) *packet; - log_info("connection %d: packet_length=%d, command=%d", + log_info("connection %lu: packet_length=%lu, command=%d", connection_id, packet_length, command); return dispatch_command(command, packet + 1, packet_length - 1); } @@ -323,27 +323,27 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command, { switch (command) { case COM_QUIT: // client exit - log_info("query for connection %d received quit command", connection_id); + log_info("query for connection %lu received quit command", connection_id); return 1; case COM_PING: - log_info("query for connection %d received ping command", connection_id); + log_info("query for connection %lu received ping command", connection_id); net_send_ok(&net, connection_id, NULL); break; case COM_QUERY: { - log_info("query for connection %d : ----\n%s\n-------------------------", + log_info("query for connection %lu : ----\n%s\n-------------------------", connection_id,packet); if (Command *command= parse_command(&instance_map, packet)) { int res= 0; - log_info("query for connection %d successefully parsed",connection_id); + log_info("query for connection %lu successefully parsed",connection_id); res= command->execute(&net, connection_id); delete command; if (!res) - log_info("query for connection %d executed ok",connection_id); + log_info("query for connection %lu executed ok",connection_id); else { - log_info("query for connection %d executed err=%d",connection_id,res); + log_info("query for connection %lu executed err=%d",connection_id,res); net_send_error(&net, res); return 0; } @@ -356,7 +356,7 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command, break; } default: - log_info("query for connection %d received unknown command",connection_id); + log_info("query for connection %lu received unknown command",connection_id); net_send_error(&net, ER_UNKNOWN_COM_ERROR); break; } diff --git a/server-tools/instance-manager/portability.h b/server-tools/instance-manager/portability.h index 23a5a5bd14c..7992a06c336 100644 --- a/server-tools/instance-manager/portability.h +++ b/server-tools/instance-manager/portability.h @@ -15,7 +15,6 @@ #define snprintf _snprintf #define SIGKILL 9 -#define SHUT_RDWR 0x2 /*TODO: fix this */ #define PROTOCOL_VERSION 10 diff --git a/sql-common/client.c b/sql-common/client.c index fc913f3f3cf..c8984e29a34 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -598,7 +598,7 @@ cli_safe_read(MYSQL *mysql) if (len == packet_error || len == 0) { - DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", + DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %lu", vio_description(net->vio),len)); #ifdef MYSQL_SERVER if (net->vio && vio_was_interrupted(net->vio)) @@ -753,6 +753,29 @@ void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate) DBUG_VOID_RETURN; } + +static void set_mysql_extended_error(MYSQL *mysql, int errcode, + const char *sqlstate, + const char *format, ...) +{ + NET *net; + va_list args; + DBUG_ENTER("set_mysql_extended_error"); + DBUG_PRINT("enter", ("error :%d '%s'", errcode, format)); + DBUG_ASSERT(mysql != 0); + + net= &mysql->net; + net->last_errno= errcode; + va_start(args, format); + my_vsnprintf(net->last_error, sizeof(net->last_error)-1, + format, args); + va_end(args); + strmov(net->sqlstate, sqlstate); + + DBUG_VOID_RETURN; +} + + /* Flush result set sent from server */ @@ -850,6 +873,7 @@ static int check_license(MYSQL *mysql) void end_server(MYSQL *mysql) { + int save_errno= errno; DBUG_ENTER("end_server"); if (mysql->net.vio != 0) { @@ -862,6 +886,7 @@ void end_server(MYSQL *mysql) } net_end(&mysql->net); free_old_query(mysql); + errno= save_errno; DBUG_VOID_RETURN; } @@ -870,7 +895,7 @@ void STDCALL mysql_free_result(MYSQL_RES *result) { DBUG_ENTER("mysql_free_result"); - DBUG_PRINT("enter",("mysql_res: %lx",result)); + DBUG_PRINT("enter",("mysql_res: 0x%lx", (long) result)); if (result) { MYSQL *mysql= result->handle; @@ -1191,6 +1216,8 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, for (row=data->data; row ; row = row->next,field++) { uchar *pos; + /* fields count may be wrong */ + DBUG_ASSERT((uint) (field - result) < fields); cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7); field->catalog = strdup_root(alloc,(char*) row->data[0]); field->db = strdup_root(alloc,(char*) row->data[1]); @@ -1366,7 +1393,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, DBUG_PRINT("info",("status: %u warning_count: %u", mysql->server_status, mysql->warning_count)); } - DBUG_PRINT("exit",("Got %d rows",result->rows)); + DBUG_PRINT("exit", ("Got %lu rows", (ulong) result->rows)); DBUG_RETURN(result); } @@ -2031,7 +2058,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, if (mysql->options.connect_timeout && vio_poll_read(net->vio, mysql->options.connect_timeout)) { - set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); + set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate, + ER(CR_SERVER_LOST_EXTENDED), + "waiting for initial communication packet", + errno); goto error; } @@ -2040,8 +2070,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, */ if ((pkt_length=cli_safe_read(mysql)) == packet_error) + { + if (mysql->net.last_errno == CR_SERVER_LOST) + set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate, + ER(CR_SERVER_LOST_EXTENDED), + "reading initial communication packet", + errno); goto error; - + } /* Check if version of protocol matches current one */ mysql->protocol_version= net->read_pos[0]; @@ -2175,7 +2211,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, */ if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net)) { - set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); + set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate, + ER(CR_SERVER_LOST_EXTENDED), + "sending connection information to server", + errno); goto error; } @@ -2254,7 +2293,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, /* Write authentication package */ if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) { - set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); + set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate, + ER(CR_SERVER_LOST_EXTENDED), + "sending authentication information", + errno); goto error; } @@ -2264,7 +2306,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, */ if ((pkt_length=cli_safe_read(mysql)) == packet_error) + { + if (mysql->net.last_errno == CR_SERVER_LOST) + set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate, + ER(CR_SERVER_LOST_EXTENDED), + "reading authorization packet", + errno); goto error; + } if (pkt_length == 1 && net->read_pos[0] == 254 && mysql->server_capabilities & CLIENT_SECURE_CONNECTION) @@ -2276,12 +2325,22 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, scramble_323(buff, mysql->scramble, passwd); if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net)) { - set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); + set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate, + ER(CR_SERVER_LOST_EXTENDED), + "sending password information", + errno); goto error; } /* Read what server thinks about out new auth message report */ if (cli_safe_read(mysql) == packet_error) + { + if (mysql->net.last_errno == CR_SERVER_LOST) + set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate, + ER(CR_SERVER_LOST_EXTENDED), + "reading final connect information", + errno); goto error; + } } if (client_flag & CLIENT_COMPRESS) /* We will use compression */ @@ -2292,8 +2351,15 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, goto error; #endif - if (db && mysql_select_db(mysql,db)) + if (db && mysql_select_db(mysql, db)) + { + if (mysql->net.last_errno == CR_SERVER_LOST) + set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate, + ER(CR_SERVER_LOST_EXTENDED), + "Setting intital database", + errno); goto error; + } if (mysql->options.init_commands) { @@ -2324,7 +2390,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, goto error; #endif - DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); + DBUG_PRINT("exit", ("Mysql handler: 0x%lx", (long) mysql)); reset_sigpipe(mysql); DBUG_RETURN(mysql); @@ -2697,7 +2763,7 @@ int STDCALL mysql_real_query(MYSQL *mysql, const char *query, ulong length) { DBUG_ENTER("mysql_real_query"); - DBUG_PRINT("enter",("handle: %lx",mysql)); + DBUG_PRINT("enter",("handle: 0x%lx", (long) mysql)); DBUG_PRINT("query",("Query = '%-.4096s'",query)); if (mysql_send_query(mysql,query,length)) diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 403c645af0b..2669f234143 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -76,8 +76,8 @@ uint calc_days_in_year(uint year) 1 error */ -static my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date, - ulong flags, int *was_cut) +my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date, + ulong flags, int *was_cut) { if (not_zero_date) { @@ -431,7 +431,7 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, goto err; } - if (check_date(l_time, not_zero_date, flags, was_cut)) + if (check_date(l_time, not_zero_date != 0, flags, was_cut)) goto err; l_time->time_type= (number_of_fields <= 3 ? @@ -532,15 +532,15 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, if ((uint) (end-str) > 1 && str != end_of_days && my_isdigit(&my_charset_latin1, *str)) { /* Found days part */ - date[0]= value; + date[0]= (ulong) value; state= 1; /* Assume next is hours */ found_days= 1; } else if ((end-str) > 1 && *str == time_separator && my_isdigit(&my_charset_latin1, str[1])) { - date[0]=0; /* Assume we found hours */ - date[1]=value; + date[0]= 0; /* Assume we found hours */ + date[1]= (ulong) value; state=2; found_hours=1; str++; /* skip ':' */ @@ -549,9 +549,9 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, { /* String given as one number; assume HHMMSS format */ date[0]= 0; - date[1]= value/10000; - date[2]= value/100 % 100; - date[3]= value % 100; + date[1]= (ulong) (value/10000); + date[2]= (ulong) (value/100 % 100); + date[3]= (ulong) (value % 100); state=4; goto fractional; } @@ -561,7 +561,7 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, { for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++) value=value*10L + (long) (*str - '0'); - date[state++]=value; + date[state++]= (ulong) value; if (state == 4 || (end-str) < 2 || *str != time_separator || !my_isdigit(&my_charset_latin1,str[1])) break; @@ -596,7 +596,7 @@ fractional: value*= (long) log_10_int[field_length]; else if (field_length < 0) *warning|= MYSQL_TIME_WARN_TRUNCATED; - date[4]=value; + date[4]= (ulong) value; } else date[4]=0; @@ -965,7 +965,7 @@ my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, */ if ((tmp < TIMESTAMP_MIN_VALUE) || (tmp > TIMESTAMP_MAX_VALUE)) tmp= 0; -end: + return (my_time_t) tmp; } /* my_system_gmt_sec */ diff --git a/sql/Makefile.am b/sql/Makefile.am index d9cea960915..cbb87f16d80 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -148,10 +148,15 @@ mysql_tzinfo_to_sql.o: $(mysql_tzinfo_to_sql_SOURCES) sql_yacc.cc: sql_yacc.yy sql_yacc.h: sql_yacc.yy +# Be careful here, note that we use VPATH and might or might not have +# a pregenerated "sql_yacc.cc" in $(srcdir) or one we just built in +# $(builddir). And it has to work if $(srcdir) == $(builddir). sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS) + @SED@ -e 's/__attribute__ ((__unused__))//' $< > sql_yacc.cc-new + @MV@ sql_yacc.cc-new sql_yacc.cc @echo "Note: The following compile may take a long time." @echo "If it fails, re-run configure with --with-low-memory" - $(CXXCOMPILE) $(LM_CFLAGS) -c $< + $(CXXCOMPILE) $(LM_CFLAGS) -c sql_yacc.cc # This generates lex_hash.h # NOTE Built sources should depend on their sources not the tool diff --git a/sql/field.cc b/sql/field.cc index 684ce5602d4..1c85b5a774b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -47,6 +47,8 @@ uchar Field_null::null[1]={1}; const char field_separator=','; #define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE 320 +#define LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE 128 +#define DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE 128 #define BLOB_PACK_LENGTH_TO_MAX_LENGH(arg) \ ((ulong) ((LL(1) << min(arg, 4) * 8) - LL(1))) @@ -1399,6 +1401,7 @@ Field_str::Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, field_charset=charset; if (charset->state & MY_CS_BINSORT) flags|=BINARY_FLAG; + field_derivation= DERIVATION_IMPLICIT; } @@ -2425,6 +2428,13 @@ int Field_new_decimal::store_decimal(const my_decimal *decimal_value) } +int Field_new_decimal::store_time(TIME *ltime, timestamp_type t_type) +{ + my_decimal decimal_value; + return store_value(date2my_decimal(ltime, &decimal_value)); +} + + double Field_new_decimal::val_real(void) { double dbl; @@ -4805,7 +4815,7 @@ int Field_time::store_time(TIME *ltime, timestamp_type type) (ltime->minute * 100 + ltime->second); if (ltime->neg) tmp= -tmp; - return Field_time::store((longlong) tmp); + return Field_time::store((longlong) tmp, FALSE); } @@ -5399,7 +5409,21 @@ int Field_newdate::store_time(TIME *ltime,timestamp_type type) long tmp; int error= 0; if (type == MYSQL_TIMESTAMP_DATE || type == MYSQL_TIMESTAMP_DATETIME) + { tmp=ltime->year*16*32+ltime->month*32+ltime->day; + if (check_date(ltime, tmp != 0, + (TIME_FUZZY_DATE | + (current_thd->variables.sql_mode & + (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | + MODE_INVALID_DATES))), &error)) + { + char buff[12]; + String str(buff, sizeof(buff), &my_charset_latin1); + make_date((DATE_TIME_FORMAT *) 0, ltime, &str); + set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, + str.ptr(), str.length(), MYSQL_TIMESTAMP_DATE, 1); + } + } else { tmp=0; @@ -5608,8 +5632,22 @@ int Field_datetime::store_time(TIME *ltime,timestamp_type type) structure always fit into DATETIME range. */ if (type == MYSQL_TIMESTAMP_DATE || type == MYSQL_TIMESTAMP_DATETIME) + { tmp=((ltime->year*10000L+ltime->month*100+ltime->day)*LL(1000000)+ (ltime->hour*10000L+ltime->minute*100+ltime->second)); + if (check_date(ltime, tmp != 0, + (TIME_FUZZY_DATE | + (current_thd->variables.sql_mode & + (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | + MODE_INVALID_DATES))), &error)) + { + char buff[19]; + String str(buff, sizeof(buff), &my_charset_latin1); + make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str); + set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, + str.ptr(), str.length(), MYSQL_TIMESTAMP_DATETIME,1); + } + } else { tmp=0; @@ -5783,37 +5821,148 @@ void Field_datetime::sql_type(String &res) const ** A string may be varchar or binary ****************************************************************************/ +/* + Report "not well formed" or "cannot convert" error + after storing a character string info a field. + + SYNOPSIS + check_string_copy_error() + field - Field + well_formed_error_pos - where not well formed data was first met + cannot_convert_error_pos - where a not-convertable character was first met + end - end of the string + + NOTES + As of version 5.0 both cases return the same error: + + "Invalid string value: 'xxx' for column 't' at row 1" + + Future versions will possibly introduce a new error message: + + "Cannot convert character string: 'xxx' for column 't' at row 1" + + RETURN + FALSE - If errors didn't happen + TRUE - If an error happened +*/ + +static bool +check_string_copy_error(Field_str *field, + const char *well_formed_error_pos, + const char *cannot_convert_error_pos, + const char *end) +{ + const char *pos, *end_orig; + char tmp[64], *t; + + if (!(pos= well_formed_error_pos) && + !(pos= cannot_convert_error_pos)) + return FALSE; + + end_orig= end; + set_if_smaller(end, pos + 6); + + for (t= tmp; pos < end; pos++) + { + if (((unsigned char) *pos) >= 0x20 && + ((unsigned char) *pos) <= 0x7F) + { + *t++= *pos; + } + else + { + *t++= '\\'; + *t++= 'x'; + *t++= _dig_vec_upper[((unsigned char) *pos) >> 4]; + *t++= _dig_vec_upper[((unsigned char) *pos) & 15]; + } + } + if (end_orig > end) + { + *t++= '.'; + *t++= '.'; + *t++= '.'; + } + *t= '\0'; + push_warning_printf(field->table->in_use, + field->table->in_use->abort_on_warning ? + MYSQL_ERROR::WARN_LEVEL_ERROR : + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, + ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), + "string", tmp, field->field_name, + (ulong) field->table->in_use->row_count); + return TRUE; +} + + + +/* + Send a truncation warning or a truncation error + after storing a too long character string info a field. + + SYNOPSIS + report_data_too_long() + field - Field + + RETURN + N/A +*/ + +inline void +report_data_too_long(Field_str *field) +{ + if (field->table->in_use->abort_on_warning) + field->set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); + else + field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); +} + + +/* + Test if the given string contains important data: + not spaces for character string, + or any data for binary string. + + SYNOPSIS + test_if_important_data() + cs Character set + str String to test + strend String end + + RETURN + FALSE - If string does not have important data + TRUE - If string has some important data +*/ + +static bool +test_if_important_data(CHARSET_INFO *cs, const char *str, const char *strend) +{ + if (cs != &my_charset_bin) + str+= cs->cset->scan(cs, str, strend, MY_SEQ_SPACES); + return (str < strend); +} + + /* Copy a string and fill with space */ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) { - int error= 0, well_formed_error; - uint32 not_used; - char buff[STRING_BUFFER_USUAL_SIZE]; - String tmpstr(buff,sizeof(buff), &my_charset_bin); uint copy_length; + const char *well_formed_error_pos; + const char *cannot_convert_error_pos; + const char *from_end_pos; /* 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(); - if (conv_errors) - error= 2; - } - - /* 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); - memmove(ptr, from, copy_length); + copy_length= well_formed_copy_nchars(field_charset, + ptr, field_length, + cs, from, length, + field_length / field_charset->mbmaxlen, + &well_formed_error_pos, + &cannot_convert_error_pos, + &from_end_pos); /* Append spaces if the string was shorter than the field. */ if (copy_length < field_length) @@ -5821,32 +5970,23 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) field_length-copy_length, field_charset->pad_char); + if (check_string_copy_error(this, well_formed_error_pos, + cannot_convert_error_pos, from + length)) + return 2; + /* 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) + if ((from_end_pos < from + length) && table->in_use->count_cuted_fields) { - if (binary()) - error= 2; - else + if (test_if_important_data(field_charset, from_end_pos, from + length)) { - 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; + report_data_too_long(this); + return 2; } } - if (error) - { - if (table->in_use->abort_on_warning) - set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); - else - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); - } - return error; + return 0; } @@ -5918,19 +6058,49 @@ int Field_longstr::store_decimal(const my_decimal *d) double Field_string::val_real(void) { - int not_used; - char *end_not_used; + int error; + char *end; CHARSET_INFO *cs= charset(); - return my_strntod(cs,ptr,field_length,&end_not_used,¬_used); + double result; + + result= my_strntod(cs,ptr,field_length,&end,&error); + if (!table->in_use->no_errors && + (error || (field_length != (uint32)(end - ptr) && + !check_if_only_end_space(cs, end, ptr + field_length)))) + { + char buf[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; + String tmp(buf, sizeof(buf), cs); + tmp.copy(ptr, field_length, cs); + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), + "DOUBLE", tmp.c_ptr()); + } + return result; } longlong Field_string::val_int(void) { - int not_used; - char *end_not_used; - CHARSET_INFO *cs=charset(); - return my_strntoll(cs,ptr,field_length,10,&end_not_used,¬_used); + int error; + char *end; + CHARSET_INFO *cs= charset(); + longlong result; + + result= my_strntoll(cs,ptr,field_length,10,&end,&error); + if (!table->in_use->no_errors && + (error || (field_length != (uint32)(end - ptr) && + !check_if_only_end_space(cs, end, ptr + field_length)))) + { + char buf[LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE]; + String tmp(buf, sizeof(buf), cs); + tmp.copy(ptr, field_length, cs); + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), + "INTEGER", tmp.c_ptr()); + } + return result; } @@ -5947,8 +6117,20 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)), my_decimal *Field_string::val_decimal(my_decimal *decimal_value) { - str2my_decimal(E_DEC_FATAL_ERROR, ptr, field_length, charset(), + int err= str2my_decimal(E_DEC_FATAL_ERROR, ptr, field_length, charset(), decimal_value); + if (!table->in_use->no_errors && err) + { + char buf[DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE]; + CHARSET_INFO *cs= charset(); + String tmp(buf, sizeof(buf), cs); + tmp.copy(ptr, field_length, cs); + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), + "DECIMAL", tmp.c_ptr()); + } + return decimal_value; } @@ -6179,58 +6361,35 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table, int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) { - uint32 not_used, copy_length; - char buff[STRING_BUFFER_USUAL_SIZE]; - String tmpstr(buff,sizeof(buff), &my_charset_bin); - int error_code= 0, well_formed_error; - enum MYSQL_ERROR::enum_warning_level level= MYSQL_ERROR::WARN_LEVEL_WARN; + uint copy_length; + const char *well_formed_error_pos; + const char *cannot_convert_error_pos; + const char *from_end_pos; + + copy_length= well_formed_copy_nchars(field_charset, + ptr + length_bytes, field_length, + cs, from, length, + field_length / field_charset->mbmaxlen, + &well_formed_error_pos, + &cannot_convert_error_pos, + &from_end_pos); - /* 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(); - if (conv_errors) - error_code= WARN_DATA_TRUNCATED; - } - /* - Make sure we don't break a multibyte sequence - as well as don't copy a malformed data. - */ - copy_length= field_charset->cset->well_formed_len(field_charset, - from,from+length, - field_length/ - field_charset->mbmaxlen, - &well_formed_error); - memmove(ptr + length_bytes, from, copy_length); if (length_bytes == 1) *ptr= (uchar) copy_length; else int2store(ptr, copy_length); + if (check_string_copy_error(this, well_formed_error_pos, + cannot_convert_error_pos, from + length)) + return 2; + // Check if we lost something other than just trailing spaces - if ((copy_length < length) && table->in_use->count_cuted_fields && - !error_code) - { - 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) + if ((from_end_pos < from + length) && table->in_use->count_cuted_fields) { - if (level == MYSQL_ERROR::WARN_LEVEL_WARN && - table->in_use->abort_on_warning) - error_code= ER_DATA_TOO_LONG; - set_warning(level, error_code, 1); + if (test_if_important_data(field_charset, from_end_pos, from + length)) + report_data_too_long(this); + else /* If we lost only spaces then produce a NOTE, not a WARNING */ + set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); return 2; } return 0; @@ -6812,68 +6971,70 @@ void Field_blob::put_length(char *pos, uint32 length) int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) { - int error= 0, well_formed_error; + uint copy_length, new_length; + const char *well_formed_error_pos; + const char *cannot_convert_error_pos; + const char *from_end_pos, *tmp; + char buff[STRING_BUFFER_USUAL_SIZE]; + String tmpstr(buff,sizeof(buff), &my_charset_bin); + if (!length) { bzero(ptr,Field_blob::pack_length()); + return 0; } - else - { - bool was_conversion; - char buff[STRING_BUFFER_USUAL_SIZE]; - String tmpstr(buff,sizeof(buff), &my_charset_bin); - uint copy_length; - uint32 not_used; - /* Convert character set if necessary */ - if ((was_conversion= String::needs_conversion(length, cs, field_charset, - ¬_used))) - { - uint conv_errors; - if (tmpstr.copy(from, length, cs, field_charset, &conv_errors)) - { - /* Fatal OOM error */ - bzero(ptr,Field_blob::pack_length()); - return -1; - } - from= tmpstr.ptr(); - length= tmpstr.length(); - if (conv_errors) - error= 2; - } - - copy_length= max_data_length(); - /* - copy_length is OK as last argument to well_formed_len as this is never - used to limit the length of the data. The cut of long data is done with - the 'min()' call below. - */ - copy_length= field_charset->cset->well_formed_len(field_charset, - from,from + - min(length, copy_length), - copy_length, - &well_formed_error); - if (copy_length < length) - error= 2; - Field_blob::store_length(copy_length); - if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH) - { // Must make a copy - if (from != value.ptr()) // For valgrind - { - value.copy(from,copy_length,charset()); - from=value.ptr(); - } + if (from == value.ptr()) + { + uint32 dummy_offset; + if (!String::needs_conversion(length, cs, field_charset, &dummy_offset)) + { + Field_blob::store_length(length); + bmove(ptr+packlength,(char*) &from,sizeof(char*)); + return 0; } - bmove(ptr+packlength,(char*) &from,sizeof(char*)); + if (tmpstr.copy(from, length, cs)) + goto oom_error; + from= tmpstr.ptr(); } - if (error) + + new_length= min(max_data_length(), field_charset->mbmaxlen * length); + if (value.alloc(new_length)) + goto oom_error; + + /* + "length" is OK as "nchars" argument to well_formed_copy_nchars as this + is never used to limit the length of the data. The cut of long data + is done with the new_length value. + */ + copy_length= well_formed_copy_nchars(field_charset, + (char*) value.ptr(), new_length, + cs, from, length, + length, + &well_formed_error_pos, + &cannot_convert_error_pos, + &from_end_pos); + + Field_blob::store_length(copy_length); + tmp= value.ptr(); + bmove(ptr+packlength,(char*) &tmp,sizeof(char*)); + + if (check_string_copy_error(this, well_formed_error_pos, + cannot_convert_error_pos, from + length)) + return 2; + + if (copy_length < length) { - if (table->in_use->abort_on_warning) - set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); - else - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + report_data_too_long(this); + return 2; } + return 0; + +oom_error: + /* Fatal OOM error */ + bzero(ptr,Field_blob::pack_length()); + return -1; } @@ -7969,7 +8130,7 @@ int Field_bit::store_decimal(const my_decimal *val) { int err= 0; longlong i= convert_decimal2longlong(val, 1, &err); - return test(err | store(i)); + return test(err | store(i, TRUE)); } @@ -8122,7 +8283,7 @@ Field_bit_as_char::Field_bit_as_char(char *ptr_arg, uint32 len_arg, int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs) { int delta; - uchar bits= field_length & 7; + uchar bits= (uchar) (field_length & 7); for (; length && !*from; from++, length--); // skip left 0's delta= bytes_in_rec - length; diff --git a/sql/field.h b/sql/field.h index 01b05d886a8..b79e8fc0d13 100644 --- a/sql/field.h +++ b/sql/field.h @@ -302,6 +302,9 @@ public: virtual CHARSET_INFO *sort_charset(void) const { return charset(); } virtual bool has_charset(void) const { return FALSE; } virtual void set_charset(CHARSET_INFO *charset) { } + virtual enum Derivation derivation(void) const + { return DERIVATION_IMPLICIT; } + virtual void set_derivation(enum Derivation derivation) { } bool set_warning(MYSQL_ERROR::enum_warning_level, unsigned int code, int cuted_increment); bool check_int(const char *str, int length, const char *int_end, @@ -373,6 +376,7 @@ public: class Field_str :public Field { protected: CHARSET_INFO *field_charset; + enum Derivation field_derivation; public: Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, @@ -387,6 +391,9 @@ public: uint size_of() const { return sizeof(*this); } CHARSET_INFO *charset(void) const { return field_charset; } void set_charset(CHARSET_INFO *charset) { field_charset=charset; } + enum Derivation derivation(void) const { return field_derivation; } + virtual void set_derivation(enum Derivation derivation_arg) + { field_derivation= derivation_arg; } bool binary() const { return field_charset == &my_charset_bin; } uint32 max_length() { return field_length; } friend class create_field; @@ -489,6 +496,7 @@ public: int store(const char *to, uint length, CHARSET_INFO *charset); int store(double nr); int store(longlong nr, bool unsigned_val); + int store_time(TIME *ltime, timestamp_type t_type); int store_decimal(const my_decimal *); double val_real(void); longlong val_int(void); diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 95ff985376d..3286695d733 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -309,6 +309,21 @@ static void do_field_string(Copy_field *copy) } +static void do_field_varbinary_pre50(Copy_field *copy) +{ + char buff[MAX_FIELD_WIDTH]; + copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset()); + copy->from_field->val_str(©->tmp); + + /* Use the same function as in 4.1 to trim trailing spaces */ + uint length= my_lengthsp_8bit(&my_charset_bin, copy->tmp.c_ptr_quick(), + copy->from_field->field_length); + + copy->to_field->store(copy->tmp.c_ptr_quick(), length, + copy->tmp.charset()); +} + + static void do_field_int(Copy_field *copy) { longlong value= copy->from_field->val_int(); @@ -571,6 +586,15 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*) if (from->result_type() == STRING_RESULT) { /* + Detect copy from pre 5.0 varbinary to varbinary as of 5.0 and + use special copy function that removes trailing spaces and thus + repairs data. + */ + if (from->type() == MYSQL_TYPE_VAR_STRING && !from->has_charset() && + to->type() == MYSQL_TYPE_VARCHAR && !to->has_charset()) + return do_field_varbinary_pre50; + + /* If we are copying date or datetime's we have to check the dates if we don't allow 'all' dates. */ diff --git a/sql/filesort.cc b/sql/filesort.cc index b063b416191..38c941b30f4 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -109,6 +109,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, DBUG_PUSH(""); /* No DBUG here */ #endif FILESORT_INFO table_sort; + TABLE_LIST *tab= table->pos_in_table_list; + Item_subselect *subselect= tab ? tab->containing_subselect() : 0; /* Don't use table->sort in filesort as it is also used by QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end @@ -121,7 +123,6 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, my_b_clear(&tempfile); my_b_clear(&buffpek_pointers); buffpek=0; - sort_keys= (uchar **) NULL; error= 1; bzero((char*) ¶m,sizeof(param)); param.sort_length= sortlength(thd, sortorder, s_length, &multi_byte_charset); @@ -202,13 +203,15 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, ulong old_memavl; ulong keys= memavl/(param.rec_length+sizeof(char*)); param.keys=(uint) min(records+1, keys); - if ((sort_keys= (uchar **) make_char_array(param.keys, param.rec_length, - MYF(0)))) + if (table_sort.sort_keys || + (table_sort.sort_keys= (uchar **) make_char_array(param.keys, param.rec_length, + MYF(0)))) break; old_memavl=memavl; if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory) memavl= min_sort_memory; } + sort_keys= table_sort.sort_keys; if (memavl < min_sort_memory) { my_error(ER_OUTOFMEMORY,MYF(ME_ERROR+ME_WAITTANG), @@ -235,8 +238,12 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, } else { - if (!(buffpek=read_buffpek_from_file(&buffpek_pointers, maxbuffer))) + if (!table_sort.buffpek && table_sort.buffpek_len < maxbuffer && + !(table_sort.buffpek= + (byte *) read_buffpek_from_file(&buffpek_pointers, maxbuffer))) goto err; + buffpek= (BUFFPEK *) table_sort.buffpek; + table_sort.buffpek_len= maxbuffer; close_cached_file(&buffpek_pointers); /* Open cached file if it isn't open */ if (! my_b_inited(outfile) && @@ -269,8 +276,14 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, err: if (param.tmp_buffer) x_free(param.tmp_buffer); - x_free((gptr) sort_keys); - x_free((gptr) buffpek); + if (!subselect || !subselect->is_uncacheable()) + { + x_free((gptr) sort_keys); + table_sort.sort_keys= 0; + x_free((gptr) buffpek); + table_sort.buffpek= 0; + table_sort.buffpek_len= 0; + } close_cached_file(&tempfile); close_cached_file(&buffpek_pointers); if (my_b_inited(outfile)) @@ -296,18 +309,32 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, DBUG_POP(); /* Ok to DBUG */ #endif memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO)); - DBUG_PRINT("exit",("records: %ld",records)); + DBUG_PRINT("exit",("records: %ld", (long) records)); DBUG_RETURN(error ? HA_POS_ERROR : records); } /* filesort */ -void filesort_free_buffers(TABLE *table) +void filesort_free_buffers(TABLE *table, bool full) { if (table->sort.record_pointers) { my_free((gptr) table->sort.record_pointers,MYF(0)); table->sort.record_pointers=0; } + if (full) + { + if (table->sort.sort_keys ) + { + x_free((gptr) table->sort.sort_keys); + table->sort.sort_keys= 0; + } + if (table->sort.buffpek) + { + x_free((gptr) table->sort.buffpek); + table->sort.buffpek= 0; + table->sort.buffpek_len= 0; + } + } if (table->sort.addon_buf) { my_free((char *) table->sort.addon_buf, MYF(0)); @@ -947,7 +974,7 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, Put all room used by freed buffer to use in adjacent buffer. Note, that we can't simply distribute memory evenly between all buffers, because new areas must not overlap with old ones. - SYNOPSYS + SYNOPSIS reuse_freed_buff() queue IN list of non-empty buffers, without freed buffer reuse IN empty buffer diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 5a8bd48d699..2674b2e65f7 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -206,9 +206,10 @@ void insert_symbols() void insert_sql_functions() { - size_t i= 0; + int i= 0; SYMBOL *cur; - for (cur= sql_functions; i<array_elements(sql_functions); cur++, i++){ + for (cur= sql_functions; i < (int) array_elements(sql_functions); cur++, i++) + { hash_lex_struct *root= get_hash_struct_by_len(&root_by_len,cur->length,&max_len); insert_into_hash(root,cur->name,0,-i-1,1); diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc index 189c5facfab..e3f979952e0 100644 --- a/sql/ha_archive.cc +++ b/sql/ha_archive.cc @@ -211,7 +211,7 @@ bool archive_db_init() max_zfile_size= INT_MAX16; break; case 8: - max_zfile_size= LONGLONG_MAX; + max_zfile_size= (z_off_t) LONGLONG_MAX; break; case 4: default: @@ -327,8 +327,8 @@ int ha_archive::read_meta_file(File meta_file, ha_rows *rows) DBUG_PRINT("ha_archive::read_meta_file", ("Check %d", (uint)meta_buffer[0])); DBUG_PRINT("ha_archive::read_meta_file", ("Version %d", (uint)meta_buffer[1])); - DBUG_PRINT("ha_archive::read_meta_file", ("Rows %lld", *rows)); - DBUG_PRINT("ha_archive::read_meta_file", ("Checkpoint %lld", check_point)); + DBUG_PRINT("ha_archive::read_meta_file", ("Rows %lu", (ulong) *rows)); + DBUG_PRINT("ha_archive::read_meta_file", ("Checkpoint %lu", (ulong) check_point)); DBUG_PRINT("ha_archive::read_meta_file", ("Dirty %d", (int)meta_buffer[18])); if ((meta_buffer[0] != (uchar)ARCHIVE_CHECK_HEADER) || @@ -359,8 +359,8 @@ int ha_archive::write_meta_file(File meta_file, ha_rows rows, bool dirty) *(meta_buffer + 18)= (uchar)dirty; DBUG_PRINT("ha_archive::write_meta_file", ("Check %d", (uint)ARCHIVE_CHECK_HEADER)); DBUG_PRINT("ha_archive::write_meta_file", ("Version %d", (uint)ARCHIVE_VERSION)); - DBUG_PRINT("ha_archive::write_meta_file", ("Rows %llu", (ulonglong)rows)); - DBUG_PRINT("ha_archive::write_meta_file", ("Checkpoint %llu", check_point)); + DBUG_PRINT("ha_archive::write_meta_file", ("Rows %lu", (ulong)rows)); + DBUG_PRINT("ha_archive::write_meta_file", ("Checkpoint %lu", (ulong) check_point)); DBUG_PRINT("ha_archive::write_meta_file", ("Dirty %d", (uint)dirty)); VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0))); @@ -495,7 +495,7 @@ int ha_archive::init_archive_writer() } share->archive_write_open= TRUE; info(HA_STATUS_TIME); - share->approx_file_size= data_file_length; + share->approx_file_size= (ulong) data_file_length; DBUG_RETURN(0); } @@ -676,13 +676,14 @@ int ha_archive::real_write_row(byte *buf, gzFile writer) if (share->approx_file_size > max_zfile_size - total_row_length) { info(HA_STATUS_TIME); - share->approx_file_size= data_file_length; + share->approx_file_size= (ulong) data_file_length; if (share->approx_file_size > max_zfile_size - total_row_length) DBUG_RETURN(HA_ERR_RECORD_FILE_FULL); } share->approx_file_size+= total_row_length; written= gzwrite(writer, buf, table->s->reclength); - DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %d", written, table->s->reclength)); + DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %lu", (int) written, + table->s->reclength)); if (!delayed_insert || !bulk_insert) share->dirty= TRUE; @@ -782,7 +783,7 @@ int ha_archive::rnd_init(bool scan) if (scan) { scan_rows= share->rows_recorded; - DBUG_PRINT("info", ("archive will retrieve %llu rows", scan_rows)); + DBUG_PRINT("info", ("archive will retrieve %lu rows", (ulong) scan_rows)); records= 0; /* @@ -822,7 +823,8 @@ int ha_archive::get_row(gzFile file_to_read, byte *buf) DBUG_ENTER("ha_archive::get_row"); read= gzread(file_to_read, buf, table->s->reclength); - DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %d", read, table->s->reclength)); + DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %lu", (int) read, + table->s->reclength)); if (read == Z_STREAM_ERROR) DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); @@ -1017,7 +1019,8 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) share->rows_recorded++; } } - DBUG_PRINT("info", ("recovered %llu archive rows", share->rows_recorded)); + DBUG_PRINT("info", ("recovered %lu archive rows", + (ulong) share->rows_recorded)); my_free((char*)buf, MYF(0)); if (rc && rc != HA_ERR_END_OF_FILE) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 8be1e40f42d..9abfcdc61c6 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -557,8 +557,8 @@ static int parse_url_error(FEDERATED_SHARE *share, TABLE *table, int error_num) if (share->scheme) { DBUG_PRINT("info", - ("error: parse_url. Returning error code %d \ - freeing share->scheme %lx", error_num, share->scheme)); + ("error: parse_url. Returning error code %d freeing share->scheme 0x%lx", + error_num, (long) share->scheme)); my_free((gptr) share->scheme, MYF(0)); share->scheme= 0; } @@ -624,7 +624,7 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, MYF(0)); share->connect_string_length= table->s->connect_string.length; - DBUG_PRINT("info",("parse_url alloced share->scheme %lx", share->scheme)); + DBUG_PRINT("info",("parse_url alloced share->scheme 0x%lx", (long) share->scheme)); /* remove addition of null terminator and store length @@ -1249,7 +1249,6 @@ bool ha_federated::create_where_from_key(String *to, if (tmp.append(FEDERATED_CLOSEPAREN)) DBUG_RETURN(1); -next_loop: if (store_length >= length) break; DBUG_PRINT("info", ("remainder %d", remainder)); @@ -1664,7 +1663,7 @@ void ha_federated::update_auto_increment(void) DBUG_ENTER("ha_federated::update_auto_increment"); thd->insert_id(mysql->last_used_con->insert_id); - DBUG_PRINT("info",("last_insert_id %d", auto_increment_value)); + DBUG_PRINT("info",("last_insert_id: %ld", (long) auto_increment_value)); DBUG_VOID_RETURN; } @@ -1914,11 +1913,11 @@ int ha_federated::delete_row(const byte *buf) { DBUG_RETURN(stash_remote_error()); } - deleted+= mysql->affected_rows; - records-= mysql->affected_rows; + deleted+= (ha_rows) mysql->affected_rows; + records-= (ha_rows) mysql->affected_rows; DBUG_PRINT("info", - ("rows deleted %d rows deleted for all time %d", - int(mysql->affected_rows), deleted)); + ("rows deleted %ld rows deleted for all time %ld", + (long) mysql->affected_rows, (long) deleted)); DBUG_RETURN(0); } @@ -2270,7 +2269,6 @@ int ha_federated::rnd_next(byte *buf) int ha_federated::read_next(byte *buf, MYSQL_RES *result) { int retval; - my_ulonglong num_rows; MYSQL_ROW row; DBUG_ENTER("ha_federated::read_next"); diff --git a/sql/ha_federated.h b/sql/ha_federated.h index 11e5a4f634f..c04ce09e75d 100644 --- a/sql/ha_federated.h +++ b/sql/ha_federated.h @@ -232,8 +232,7 @@ public: */ double scan_time() { - DBUG_PRINT("info", - ("records %d", records)); + DBUG_PRINT("info", ("records %ld", (long) records)); return (double)(records*1000); } /* diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 34ef888a029..3cf7593bd8a 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -631,7 +631,7 @@ int ha_heap::create(const char *name, TABLE *table_arg, } mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*)); max_rows = (ha_rows) (table->in_use->variables.max_heap_table_size / - mem_per_row); + (ulonglong) mem_per_row); if (table_arg->found_next_number_field) { keydef[share->next_number_index].flag|= HA_AUTO_KEY; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index e9ccc0ccede..5548cb66e7f 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2739,7 +2739,6 @@ ha_innobase::store_key_val_for_row( CHARSET_INFO* cs; ulint key_len; - ulint len; ulint true_len; int error=0; ulint blob_len; @@ -4215,7 +4214,7 @@ ha_innobase::rnd_pos( } if (error) { - DBUG_PRINT("error", ("Got error: %ld", error)); + DBUG_PRINT("error", ("Got error: %d", error)); DBUG_RETURN(error); } @@ -4225,7 +4224,7 @@ ha_innobase::rnd_pos( error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT); if (error) { - DBUG_PRINT("error", ("Got error: %ld", error)); + DBUG_PRINT("error", ("Got error: %d", error)); } change_active_index(keynr); diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 8e40105780b..19ec1b29da3 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1557,7 +1557,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, } } DBUG_PRINT("loop",("found: 0x%lx recpos: %d minpos: %d length: %d", - found,recpos,minpos,length)); + (long) found, recpos, minpos, length)); if (recpos != minpos) { // Reserved space (Null bits?) bzero((char*) recinfo_pos,sizeof(*recinfo_pos)); diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 33da88bbdd4..5e613a63303 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -108,7 +108,7 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) if (table->s->reclength != mean_rec_length && mean_rec_length) { - DBUG_PRINT("error",("reclength: %d mean_rec_length: %d", + DBUG_PRINT("error",("reclength: %lu mean_rec_length: %lu", table->s->reclength, mean_rec_length)); goto err; } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 957a3055e70..9873a70b7fc 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -822,8 +822,8 @@ int ha_ndbcluster::get_ndb_blobs_value(NdbBlob *last_ndb_blob, { char *buf= m_blobs_buffer + offset; uint32 len= 0xffffffff; // Max uint32 - DBUG_PRINT("value", ("read blob ptr=%x len=%u", - (UintPtr)buf, (uint)blob_len)); + DBUG_PRINT("value", ("read blob ptr: 0x%lx len: %u", + (long)buf, (uint)blob_len)); if (ndb_blob->readData(buf, len) != 0) DBUG_RETURN(-1); DBUG_ASSERT(len == blob_len); @@ -1059,6 +1059,7 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase) int error= 0; const char *index_name; char unique_index_name[FN_LEN]; + bool null_in_unique_index= false; static const char* unique_suffix= "$unique"; KEY* key_info= tab->key_info; const char **key_name= tab->s->keynames.type_names; @@ -1096,8 +1097,14 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase) error= create_unique_index(unique_index_name, key_info); break; case UNIQUE_INDEX: - if (!(error= check_index_fields_not_null(i))) - error= create_unique_index(unique_index_name, key_info); + if (check_index_fields_not_null(i)) + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NULL_COLUMN_IN_INDEX, + "Ndb does not support unique index on NULL valued attributes, index access with NULL value will become full table scan"); + null_in_unique_index= true; + } + error= create_unique_index(unique_index_name, key_info); break; case ORDERED_INDEX: error= create_ordered_index(index_name, key_info); @@ -1129,6 +1136,11 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase) m_index[i].unique_index= (void *) index; error= fix_unique_index_attr_order(m_index[i], index, key_info); } + if (idx_type == UNIQUE_INDEX && + phase != ILBP_CREATE && + check_index_fields_not_null(i)) + null_in_unique_index= true; + m_index[i].null_in_unique_index= null_in_unique_index; } DBUG_RETURN(error); @@ -1150,7 +1162,7 @@ NDB_INDEX_TYPE ha_ndbcluster::get_index_type_from_table(uint inx) const ORDERED_INDEX); } -int ha_ndbcluster::check_index_fields_not_null(uint inx) +bool ha_ndbcluster::check_index_fields_not_null(uint inx) { KEY* key_info= table->key_info + inx; KEY_PART_INFO* key_part= key_info->key_part; @@ -1161,14 +1173,10 @@ int ha_ndbcluster::check_index_fields_not_null(uint inx) { Field* field= key_part->field; if (field->maybe_null()) - { - my_printf_error(ER_NULL_COLUMN_IN_INDEX,ER(ER_NULL_COLUMN_IN_INDEX), - MYF(0),field->field_name); - DBUG_RETURN(ER_NULL_COLUMN_IN_INDEX); - } + DBUG_RETURN(true); } - DBUG_RETURN(0); + DBUG_RETURN(false); } void ha_ndbcluster::release_metadata() @@ -1261,6 +1269,12 @@ inline NDB_INDEX_TYPE ha_ndbcluster::get_index_type(uint idx_no) const return m_index[idx_no].type; } +inline bool ha_ndbcluster::has_null_in_unique_index(uint idx_no) const +{ + DBUG_ASSERT(idx_no < MAX_KEY); + return m_index[idx_no].null_in_unique_index; +} + /* Get the flags for an index @@ -1596,7 +1610,7 @@ bool ha_ndbcluster::check_all_operations_for_error(NdbTransaction *trans, * primary key or unique index values */ -int ha_ndbcluster::peek_indexed_rows(const byte *record) +int ha_ndbcluster::peek_indexed_rows(const byte *record, bool check_pk) { NdbTransaction *trans= m_active_trans; NdbOperation *op; @@ -1609,7 +1623,7 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record) (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type); first= NULL; - if (table->s->primary_key != MAX_KEY) + if (check_pk && table->s->primary_key != MAX_KEY) { /* * Fetch any row with colliding primary key @@ -1774,7 +1788,7 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor) all pending update or delete operations should be sent to NDB */ - DBUG_PRINT("info", ("ops_pending: %d", m_ops_pending)); + DBUG_PRINT("info", ("ops_pending: %ld", (long) m_ops_pending)); if (m_ops_pending) { if (m_transaction_on) @@ -2090,6 +2104,42 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key, } /* + Unique index scan in NDB (full table scan with scan filter) + */ + +int ha_ndbcluster::unique_index_scan(const KEY* key_info, + const byte *key, + uint key_len, + byte *buf) +{ + int res; + NdbScanOperation *op; + NdbTransaction *trans= m_active_trans; + + DBUG_ENTER("unique_index_scan"); + DBUG_PRINT("enter", ("Starting new scan on %s", m_tabname)); + + NdbOperation::LockMode lm= + (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type); + bool need_pk = (lm == NdbOperation::LM_Read); + if (!(op=trans->getNdbScanOperation((const NDBTAB *) m_table)) || + op->readTuples(lm, + (need_pk)?NdbScanOperation::SF_KeyInfo:0, + parallelism)) + ERR_RETURN(trans->getNdbError()); + m_active_cursor= op; + if (generate_scan_filter_from_key(op, key_info, key, key_len, buf)) + DBUG_RETURN(ndb_err(trans)); + if ((res= define_read_attrs(buf, op))) + DBUG_RETURN(res); + + if (execute_no_commit(this,trans,false) != 0) + DBUG_RETURN(ndb_err(trans)); + DBUG_PRINT("exit", ("Scan started successfully")); + DBUG_RETURN(next_result(buf)); +} + +/* Start full table scan in NDB */ @@ -2166,7 +2216,7 @@ int ha_ndbcluster::write_row(byte *record) start_bulk_insert will set parameters to ensure that each write_row is committed individually */ - int peek_res= peek_indexed_rows(record); + int peek_res= peek_indexed_rows(record, true); if (!peek_res) { @@ -2335,8 +2385,26 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) NdbScanOperation* cursor= m_active_cursor; NdbOperation *op; uint i; + bool pk_update= (table->s->primary_key != MAX_KEY && + key_cmp(table->s->primary_key, old_data, new_data)); DBUG_ENTER("update_row"); + /* + * If IGNORE the ignore constraint violations on primary and unique keys, + * but check that it is not part of INSERT ... ON DUPLICATE KEY UPDATE + */ + if (m_ignore_dup_key && thd->lex->sql_command == SQLCOM_UPDATE) + { + int peek_res= peek_indexed_rows(new_data, pk_update); + + if (!peek_res) + { + DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY); + } + if (peek_res != HA_ERR_KEY_NOT_FOUND) + DBUG_RETURN(peek_res); + } + statistic_increment(thd->status_var.ha_update_count, &LOCK_status); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) { @@ -2346,8 +2414,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) } /* Check for update of primary key for special handling */ - if ((table->s->primary_key != MAX_KEY) && - (key_cmp(table->s->primary_key, old_data, new_data))) + if (pk_update) { int read_res, insert_res, delete_res, undo_res; @@ -2763,7 +2830,7 @@ int ha_ndbcluster::index_read(byte *buf, } else if (type == UNIQUE_INDEX) { - DBUG_RETURN(1); + DBUG_RETURN(unique_index_scan(key_info, key, key_len, buf)); } break; case ORDERED_INDEX: @@ -2856,12 +2923,13 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key, bool eq_r, bool sorted, byte* buf) { - KEY* key_info; + ndb_index_type type= get_index_type(active_index); +KEY* key_info; int error= 1; DBUG_ENTER("ha_ndbcluster::read_range_first_to_buf"); DBUG_PRINT("info", ("eq_r: %d, sorted: %d", eq_r, sorted)); - switch (get_index_type(active_index)){ + switch (type){ case PRIMARY_KEY_ORDERED_INDEX: case PRIMARY_KEY_INDEX: key_info= table->key_info + active_index; @@ -2887,6 +2955,14 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key, error= unique_index_read(start_key->key, start_key->length, buf); DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error); } + else if (type == UNIQUE_INDEX) + { + error= unique_index_scan(key_info, + start_key->key, + start_key->length, + buf); + DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error); + } break; default: break; @@ -2976,7 +3052,7 @@ int ha_ndbcluster::close_scan() Take over any pending transactions to the deleteing/updating transaction before closing the scan */ - DBUG_PRINT("info", ("ops_pending: %d", m_ops_pending)); + DBUG_PRINT("info", ("ops_pending: %ld", (long) m_ops_pending)); if (execute_no_commit(this,trans,false) != 0) { no_uncommitted_rows_execute_failure(); DBUG_RETURN(ndb_err(trans)); @@ -3542,8 +3618,8 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) Thd_ndb *thd_ndb= get_thd_ndb(thd); Ndb *ndb= thd_ndb->ndb; - DBUG_PRINT("enter", ("thd: %x, thd_ndb: %x, thd_ndb->lock_count: %d", - thd, thd_ndb, thd_ndb->lock_count)); + DBUG_PRINT("enter", ("thd: 0x%lx thd_ndb: 0x%lx thd_ndb->lock_count: %d", + (long) thd, (long) thd_ndb, thd_ndb->lock_count)); if (lock_type != F_UNLCK) { @@ -3847,7 +3923,8 @@ int ndbcluster_commit(THD *thd, bool all) while ((share= it++)) { pthread_mutex_lock(&share->mutex); - DBUG_PRINT("info", ("Invalidate commit_count for %s, share->commit_count: %d ", share->table_name, share->commit_count)); + DBUG_PRINT("info", ("Invalidate commit_count for %s, share->commit_count: %lu", + share->table_name, (ulong) share->commit_count)); share->commit_count= 0; share->commit_count_lock++; pthread_mutex_unlock(&share->mutex); @@ -4281,7 +4358,7 @@ int ha_ndbcluster::create(const char *name, if (packfrm(data, length, &pack_data, &pack_length)) DBUG_RETURN(2); - DBUG_PRINT("info", ("setFrm data=%x, len=%d", pack_data, pack_length)); + DBUG_PRINT("info", ("setFrm data: 0x%lx len: %d", (long) pack_data, pack_length)); tab.setFrm(pack_data, pack_length); my_free((char*)data, MYF(0)); my_free((char*)pack_data, MYF(0)); @@ -5237,7 +5314,7 @@ bool ndbcluster_init() } { char buf[128]; - my_snprintf(buf, sizeof(buf), "mysqld --server-id=%d", server_id); + my_snprintf(buf, sizeof(buf), "mysqld --server-id=%lu", server_id); g_ndb_cluster_connection->set_name(buf); } g_ndb_cluster_connection->set_optimized_node_selection @@ -5813,9 +5890,9 @@ static NDB_SHARE* get_share(const char *table_name) share->use_count++; DBUG_PRINT("share", - ("table_name: %s, length: %d, use_count: %d, commit_count: %d", + ("table_name: %s length: %d use_count: %d commit_count: %lu", share->table_name, share->table_name_length, share->use_count, - share->commit_count)); + (ulong) share->commit_count)); pthread_mutex_unlock(&ndbcluster_mutex); return share; } @@ -5862,14 +5939,14 @@ static int packfrm(const void *data, uint len, uint blob_len; frm_blob_struct* blob; DBUG_ENTER("packfrm"); - DBUG_PRINT("enter", ("data: %x, len: %d", data, len)); + DBUG_PRINT("enter", ("data: 0x%lx, len: %d", (long) data, len)); error= 1; org_len= len; if (my_compress((byte*)data, &org_len, &comp_len)) goto err; - DBUG_PRINT("info", ("org_len: %d, comp_len: %d", org_len, comp_len)); + DBUG_PRINT("info", ("org_len: %lu comp_len: %lu", org_len, comp_len)); DBUG_DUMP("compressed", (char*)data, org_len); error= 2; @@ -5889,7 +5966,7 @@ static int packfrm(const void *data, uint len, *pack_len= blob_len; error= 0; - DBUG_PRINT("exit", ("pack_data: %x, pack_len: %d", *pack_data, *pack_len)); + DBUG_PRINT("exit", ("pack_data: 0x%lx, pack_len: %d", (long) *pack_data, *pack_len)); err: DBUG_RETURN(error); @@ -5903,13 +5980,13 @@ static int unpackfrm(const void **unpack_data, uint *unpack_len, byte *data; ulong complen, orglen, ver; DBUG_ENTER("unpackfrm"); - DBUG_PRINT("enter", ("pack_data: %x", pack_data)); + DBUG_PRINT("enter", ("pack_data: 0x%lx", (long) pack_data)); complen= uint4korr((char*)&blob->head.complen); orglen= uint4korr((char*)&blob->head.orglen); ver= uint4korr((char*)&blob->head.ver); - DBUG_PRINT("blob",("ver: %d complen: %d orglen: %d", + DBUG_PRINT("blob",("ver: %lu complen: %lu orglen: %lu", ver,complen,orglen)); DBUG_DUMP("blob->data", (char*) blob->data, complen); @@ -5928,7 +6005,7 @@ static int unpackfrm(const void **unpack_data, uint *unpack_len, *unpack_data= data; *unpack_len= complen; - DBUG_PRINT("exit", ("frmdata: %x, len: %d", *unpack_data, *unpack_len)); + DBUG_PRINT("exit", ("frmdata: 0x%lx, len: %d", (long) *unpack_data, *unpack_len)); DBUG_RETURN(0); } @@ -6116,6 +6193,30 @@ ha_ndbcluster::release_completed_operations(NdbTransaction *trans, trans->releaseCompletedOperations(); } +bool +ha_ndbcluster::null_value_index_search(KEY_MULTI_RANGE *ranges, + KEY_MULTI_RANGE *end_range, + HANDLER_BUFFER *buffer) +{ + DBUG_ENTER("null_value_index_search"); + KEY* key_info= table->key_info + active_index; + KEY_MULTI_RANGE *range= ranges; + ulong reclength= table->s->reclength; + byte *curr= (byte*)buffer->buffer; + byte *end_of_buffer= (byte*)buffer->buffer_end; + + for (; range<end_range && curr+reclength <= end_of_buffer; + range++) + { + const byte *key= range->start_key.key; + uint key_len= range->start_key.length; + if (check_null_in_key(key_info, key, key_len)) + DBUG_RETURN(true); + curr += reclength; + } + DBUG_RETURN(false); +} + int ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, KEY_MULTI_RANGE *ranges, @@ -6132,11 +6233,14 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, NdbOperation* op; Thd_ndb *thd_ndb= get_thd_ndb(current_thd); - if (uses_blob_value(m_retrieve_all_fields)) + /** + * blobs and unique hash index with NULL can't be batched currently + */ + if (uses_blob_value(m_retrieve_all_fields) || + (index_type == UNIQUE_INDEX && + has_null_in_unique_index(active_index) && + null_value_index_search(ranges, ranges+range_count, buffer))) { - /** - * blobs can't be batched currently - */ m_disable_multi_read= TRUE; DBUG_RETURN(handler::read_multi_range_first(found_range_p, ranges, @@ -6192,7 +6296,6 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, goto range; /* fall through */ case PRIMARY_KEY_INDEX: - { multi_range_curr->range_flag |= UNIQUE_RANGE; if ((op= m_active_trans->getNdbOperation(tab)) && !op->readTuple(lm) && @@ -6203,8 +6306,6 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, else ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError()); break; - } - break; case UNIQUE_ORDERED_INDEX: if (!(multi_range_curr->start_key.length == key_info->key_length && multi_range_curr->start_key.flag == HA_READ_KEY_EXACT && @@ -6213,18 +6314,16 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, goto range; /* fall through */ case UNIQUE_INDEX: - { multi_range_curr->range_flag |= UNIQUE_RANGE; if ((op= m_active_trans->getNdbIndexOperation(unique_idx, tab)) && - !op->readTuple(lm) && - !set_index_key(op, key_info, multi_range_curr->start_key.key) && - !define_read_attrs(curr, op) && - (op->setAbortOption(AO_IgnoreError), TRUE)) - curr += reclength; + !op->readTuple(lm) && + !set_index_key(op, key_info, multi_range_curr->start_key.key) && + !define_read_attrs(curr, op) && + (op->setAbortOption(AO_IgnoreError), TRUE)) + curr += reclength; else - ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError()); + ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError()); break; - } case ORDERED_INDEX: { range: @@ -6521,7 +6620,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) my_thread_init(); DBUG_ENTER("ndb_util_thread"); - DBUG_PRINT("enter", ("ndb_cache_check_time: %d", ndb_cache_check_time)); + DBUG_PRINT("enter", ("ndb_cache_check_time: %lu", ndb_cache_check_time)); thd= new THD; /* note that contructor of THD uses DBUG_ */ THD_CHECK_SENTRY(thd); @@ -6550,7 +6649,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) &abstime); pthread_mutex_unlock(&LOCK_ndb_util_thread); - DBUG_PRINT("ndb_util_thread", ("Started, ndb_cache_check_time: %d", + DBUG_PRINT("ndb_util_thread", ("Started, ndb_cache_check_time: %lu", ndb_cache_check_time)); if (abort_loop) @@ -7447,7 +7546,7 @@ void ndb_serialize_cond(const Item *item, void *arg) if (context->expecting(Item::INT_ITEM)) { Item_int *int_item= (Item_int *) item; - DBUG_PRINT("info", ("value %d", int_item->value)); + DBUG_PRINT("info", ("value %ld", (long) int_item->value)); NDB_ITEM_QUALIFICATION q; q.value_type= Item::INT_ITEM; curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); @@ -7470,7 +7569,7 @@ void ndb_serialize_cond(const Item *item, void *arg) context->supported= FALSE; break; case Item::REAL_ITEM: - DBUG_PRINT("info", ("REAL_ITEM %s")); + DBUG_PRINT("info", ("REAL_ITEM")); if (context->expecting(Item::REAL_ITEM)) { Item_float *float_item= (Item_float *) item; @@ -7518,7 +7617,7 @@ void ndb_serialize_cond(const Item *item, void *arg) context->supported= FALSE; break; case Item::DECIMAL_ITEM: - DBUG_PRINT("info", ("DECIMAL_ITEM %s")); + DBUG_PRINT("info", ("DECIMAL_ITEM")); if (context->expecting(Item::DECIMAL_ITEM)) { Item_decimal *decimal_item= (Item_decimal *) item; @@ -7967,31 +8066,12 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack, NdbScanOperation *op) { DBUG_ENTER("generate_scan_filter"); + if (ndb_cond_stack) { - DBUG_PRINT("info", ("Generating scan filter")); NdbScanFilter filter(op); - bool multiple_cond= FALSE; - // Wrap an AND group around multiple conditions - if (ndb_cond_stack->next) { - multiple_cond= TRUE; - if (filter.begin() == -1) - DBUG_RETURN(1); - } - for (Ndb_cond_stack *stack= ndb_cond_stack; - (stack); - stack= stack->next) - { - Ndb_cond *cond= stack->ndb_cond; - - if (build_scan_filter(cond, &filter)) - { - DBUG_PRINT("info", ("build_scan_filter failed")); - DBUG_RETURN(1); - } - } - if (multiple_cond && filter.end() == -1) - DBUG_RETURN(1); + + DBUG_RETURN(generate_scan_filter_from_cond(ndb_cond_stack, filter)); } else { @@ -8002,6 +8082,88 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack, } int +ha_ndbcluster::generate_scan_filter_from_cond(Ndb_cond_stack *ndb_cond_stack, + NdbScanFilter& filter) +{ + DBUG_ENTER("generate_scan_filter_from_cond"); + bool multiple_cond= FALSE; + + DBUG_PRINT("info", ("Generating scan filter")); + // Wrap an AND group around multiple conditions + if (ndb_cond_stack->next) + { + multiple_cond= TRUE; + if (filter.begin() == -1) + DBUG_RETURN(1); + } + for (Ndb_cond_stack *stack= ndb_cond_stack; + (stack); + stack= stack->next) + { + Ndb_cond *cond= stack->ndb_cond; + + if (build_scan_filter(cond, &filter)) + { + DBUG_PRINT("info", ("build_scan_filter failed")); + DBUG_RETURN(1); + } + } + if (multiple_cond && filter.end() == -1) + DBUG_RETURN(1); + + DBUG_RETURN(0); +} + +int ha_ndbcluster::generate_scan_filter_from_key(NdbScanOperation *op, + const KEY* key_info, + const byte *key, + uint key_len, + byte *buf) +{ + KEY_PART_INFO* key_part= key_info->key_part; + KEY_PART_INFO* end= key_part+key_info->key_parts; + NdbScanFilter filter(op); + int res; + + DBUG_ENTER("generate_scan_filter_from_key"); + filter.begin(NdbScanFilter::AND); + for (; key_part != end; key_part++) + { + Field* field= key_part->field; + uint32 pack_len= field->pack_length(); + const byte* ptr= key; + char buf[256]; + DBUG_PRINT("info", ("Filtering value for %s", field->field_name)); + DBUG_DUMP("key", (char*)ptr, pack_len); + if (key_part->null_bit) + { + DBUG_PRINT("info", ("Generating ISNULL filter")); + if (filter.isnull(key_part->fieldnr-1) == -1) + DBUG_RETURN(1); + } + else + { + DBUG_PRINT("info", ("Generating EQ filter")); + if (filter.cmp(NdbScanFilter::COND_EQ, + key_part->fieldnr-1, + ptr, + pack_len) == -1) + DBUG_RETURN(1); + } + key += key_part->store_length; + } + // Add any pushed condition + if (m_cond_stack && + (res= generate_scan_filter_from_cond(m_cond_stack, filter))) + DBUG_RETURN(res); + + if (filter.end() == -1) + DBUG_RETURN(1); + + DBUG_RETURN(0); +} + +int ndbcluster_show_status(THD* thd) { Protocol *protocol= thd->protocol; diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index d0f7c020184..5d66a7920f9 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -56,6 +56,7 @@ typedef struct ndb_index_data { void *index; void *unique_index; unsigned char *unique_index_attrid_map; + bool null_in_unique_index; } NDB_INDEX_DATA; typedef struct st_ndbcluster_share { @@ -546,7 +547,9 @@ class ha_ndbcluster: public handler KEY_MULTI_RANGE*ranges, uint range_count, bool sorted, HANDLER_BUFFER *buffer); int read_multi_range_next(KEY_MULTI_RANGE **found_range_p); - + bool null_value_index_search(KEY_MULTI_RANGE *ranges, + KEY_MULTI_RANGE *end_range, + HANDLER_BUFFER *buffer); bool get_error_message(int error, String *buf); int info(uint); int extra(enum ha_extra_function operation); @@ -649,7 +652,8 @@ private: void release_metadata(); NDB_INDEX_TYPE get_index_type(uint idx_no) const; NDB_INDEX_TYPE get_index_type_from_table(uint index_no) const; - int check_index_fields_not_null(uint index_no); + bool has_null_in_unique_index(uint idx_no) const; + bool check_index_fields_not_null(uint index_no); int pk_read(const byte *key, uint key_len, byte *buf); int complemented_pk_read(const byte *old_data, byte *new_data); @@ -657,12 +661,17 @@ private: const NdbOperation *first, const NdbOperation *last, uint errcode); - int peek_indexed_rows(const byte *record); + int peek_indexed_rows(const byte *record, bool check_pk); int unique_index_read(const byte *key, uint key_len, byte *buf); int ordered_index_scan(const key_range *start_key, const key_range *end_key, bool sorted, bool descending, byte* buf); + int unique_index_scan(const KEY* key_info, + const byte *key, + uint key_len, + byte *buf); + int full_table_scan(byte * buf); int fetch_next(NdbScanOperation* op); int next_result(byte *buf); @@ -725,6 +734,13 @@ bool uses_blob_value(bool all_fields); int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter); int generate_scan_filter(Ndb_cond_stack* cond_stack, NdbScanOperation* op); + int generate_scan_filter_from_cond(Ndb_cond_stack* cond_stack, + NdbScanFilter& filter); + int generate_scan_filter_from_key(NdbScanOperation* op, + const KEY* key_info, + const byte *key, + uint key_len, + byte *buf); friend int execute_commit(ha_ndbcluster*, NdbTransaction*); friend int execute_no_commit(ha_ndbcluster*, NdbTransaction*, bool); diff --git a/sql/handler.cc b/sql/handler.cc index cff8213edec..65ed7b43855 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -474,7 +474,6 @@ int ha_init() { int error= 0; handlerton **types; - show_table_alias_st *table_alias; total_ha= savepoint_alloc_size= 0; if (ha_init_errors()) @@ -885,8 +884,8 @@ int ha_commit_or_rollback_by_xid(XID *xid, bool commit) if ((*types)->state == SHOW_OPTION_YES && (*types)->recover) { if ((*(commit ? (*types)->commit_by_xid : - (*types)->rollback_by_xid))(xid)); - res= 0; + (*types)->rollback_by_xid))(xid)) + res= 0; } } return res; @@ -1533,7 +1532,7 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) */ DBUG_PRINT("info",("auto_increment: nr: %lu cannot honour " "auto_increment_offset: %lu", - nr, variables->auto_increment_offset)); + (ulong) nr, variables->auto_increment_offset)); return nr; } if (variables->auto_increment_increment == 1) @@ -1779,7 +1778,7 @@ void handler::print_error(int error, myf errflag) { /* Key is unknown */ str.copy("", 0, system_charset_info); - key_nr= -1; + key_nr= (uint) -1; } else { @@ -1798,8 +1797,8 @@ void handler::print_error(int error, myf errflag) break; } case HA_ERR_NULL_IN_SPATIAL: - textno= ER_UNKNOWN_ERROR; - break; + my_error(ER_CANT_CREATE_GEOMETRY_OBJECT, MYF(0)); + DBUG_VOID_RETURN; case HA_ERR_FOUND_DUPP_UNIQUE: textno=ER_DUP_UNIQUE; break; @@ -1982,6 +1981,10 @@ int handler::check_old_types() { return HA_ADMIN_NEEDS_ALTER; } + if ((*field)->type() == MYSQL_TYPE_VAR_STRING) + { + return HA_ADMIN_NEEDS_ALTER; + } } } return 0; diff --git a/sql/item.cc b/sql/item.cc index d181edb4ecd..d14956dee84 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -272,6 +272,32 @@ my_decimal *Item::val_decimal_from_string(my_decimal *decimal_value) } +my_decimal *Item::val_decimal_from_date(my_decimal *decimal_value) +{ + DBUG_ASSERT(fixed == 1); + TIME ltime; + if (get_date(<ime, TIME_FUZZY_DATE)) + { + my_decimal_set_zero(decimal_value); + return 0; + } + return date2my_decimal(<ime, decimal_value); +} + + +my_decimal *Item::val_decimal_from_time(my_decimal *decimal_value) +{ + DBUG_ASSERT(fixed == 1); + TIME ltime; + if (get_time(<ime)) + { + my_decimal_set_zero(decimal_value); + return 0; + } + return date2my_decimal(<ime, decimal_value); +} + + double Item::val_real_from_decimal() { /* Note that fix_fields may not be called for Item_avg_field items */ @@ -295,6 +321,25 @@ longlong Item::val_int_from_decimal() return result; } +int Item::save_time_in_field(Field *field) +{ + TIME ltime; + if (get_time(<ime)) + return set_field_to_null(field); + field->set_notnull(); + return field->store_time(<ime, MYSQL_TIMESTAMP_TIME); +} + + +int Item::save_date_in_field(Field *field) +{ + TIME ltime; + if (get_date(<ime, TIME_FUZZY_DATE)) + return set_field_to_null(field); + field->set_notnull(); + return field->store_time(<ime, MYSQL_TIMESTAMP_DATETIME); +} + Item::Item(): rsize(0), name(0), orig_name(0), name_length(0), fixed(0), @@ -1148,6 +1193,28 @@ void Item_name_const::print(String *str) /* + need a special class to adjust printing : references to aggregate functions + must not be printed as refs because the aggregate functions that are added to + the front of select list are not printed as well. +*/ +class Item_aggregate_ref : public Item_ref +{ +public: + Item_aggregate_ref(Name_resolution_context *context_arg, Item **item, + const char *table_name_arg, const char *field_name_arg) + :Item_ref(context_arg, item, table_name_arg, field_name_arg) {} + + void print (String *str) + { + if (ref) + (*ref)->print(str); + else + Item_ident::print(str); + } +}; + + +/* Move SUM items out from item tree and replace with reference SYNOPSIS @@ -1200,8 +1267,8 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, Item *new_item, *real_itm= real_item(); ref_pointer_array[el]= real_itm; - if (!(new_item= new Item_ref(&thd->lex->current_select->context, - ref_pointer_array + el, 0, name))) + if (!(new_item= new Item_aggregate_ref(&thd->lex->current_select->context, + ref_pointer_array + el, 0, name))) return; // fatal_error is set fields.push_front(real_itm); thd->change_item_tree(ref, new_item); @@ -1622,7 +1689,7 @@ void Item_field::set_field(Field *field_par) db_name= field_par->table->s->db; alias_name_used= field_par->table->alias_name_used; unsigned_flag=test(field_par->flags & UNSIGNED_FLAG); - collation.set(field_par->charset(), DERIVATION_IMPLICIT); + collation.set(field_par->charset(), field_par->derivation()); fixed= 1; } @@ -2106,12 +2173,6 @@ void Item_string::print(String *str) } -inline bool check_if_only_end_space(CHARSET_INFO *cs, char *str, char *end) -{ - return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end; -} - - double Item_string::val_real() { DBUG_ASSERT(fixed == 1); @@ -3638,10 +3699,37 @@ 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 != (Item **)not_found_item && (*res)->type() == Item::FIELD_ITEM) + if (res != (Item **)not_found_item) { - set_field((*((Item_field**)res))->field); - return 0; + if ((*res)->type() == Item::FIELD_ITEM) + { + /* + It's an Item_field referencing another Item_field in the select + list. + use the field from the Item_field in the select list and leave + the Item_field instance in place. + */ + set_field((*((Item_field**)res))->field); + return 0; + } + else + { + /* + It's not an Item_field in the select list so we must make a new + Item_ref to point to the Item in the select list and replace the + Item_field created by the parser with the new Item_ref. + */ + Item_ref *rf= new Item_ref(context, db_name,table_name,field_name); + if (!rf) + return 1; + thd->change_item_tree(reference, rf); + /* + Because Item_ref never substitutes itself with other items + in Item_ref::fix_fields(), we can safely use the original + pointer to it even after fix_fields() + */ + return rf->fix_fields(thd, reference) || rf->check_cols(1); + } } } if ((ret= fix_outer_field(thd, &from_field, reference)) < 0) @@ -4106,6 +4194,10 @@ void Item_field::make_field(Send_field *tmp_field) DBUG_ASSERT(tmp_field->table_name != 0); if (name) tmp_field->col_name=name; // Use user supplied name + if (table_name) + tmp_field->table_name= table_name; + if (db_name) + tmp_field->db_name= db_name; } @@ -4664,6 +4756,22 @@ bool Item_field::send(Protocol *protocol, String *buffer) } +void Item_field::update_null_value() +{ + /* + need to set no_errors to prevent warnings about type conversion + popping up. + */ + THD *thd= field->table->in_use; + int no_errors; + + no_errors= thd->no_errors; + thd->no_errors= 1; + Item::update_null_value(); + thd->no_errors= no_errors; +} + + Item_ref::Item_ref(Name_resolution_context *context_arg, Item **item, const char *table_name_arg, const char *field_name_arg) @@ -5547,7 +5655,7 @@ void Item_trigger_field::set_required_privilege(bool rw) } -bool Item_trigger_field::set_value(THD *thd, sp_rcontext */*ctx*/, Item **it) +bool Item_trigger_field::set_value(THD *thd, sp_rcontext * /*ctx*/, Item **it) { Item *item= sp_prepare_func_item(thd, it); @@ -6021,7 +6129,7 @@ bool Item_cache_row::null_inside() } else { - values[i]->val_int(); + values[i]->update_null_value(); if (values[i]->null_value) return 1; } diff --git a/sql/item.h b/sql/item.h index 0cfb0b01fd8..e0451febb1e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -27,19 +27,7 @@ class Item_field; /* "Declared Type Collation" A combination of collation and its derivation. -*/ - -enum Derivation -{ - DERIVATION_IGNORABLE= 5, - DERIVATION_COERCIBLE= 4, - DERIVATION_SYSCONST= 3, - DERIVATION_IMPLICIT= 2, - DERIVATION_NONE= 1, - DERIVATION_EXPLICIT= 0 -}; -/* Flags for collation aggregation modes: MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value @@ -617,9 +605,14 @@ public: my_decimal *val_decimal_from_real(my_decimal *decimal_value); my_decimal *val_decimal_from_int(my_decimal *decimal_value); my_decimal *val_decimal_from_string(my_decimal *decimal_value); + my_decimal *val_decimal_from_date(my_decimal *decimal_value); + my_decimal *val_decimal_from_time(my_decimal *decimal_value); longlong val_int_from_decimal(); double val_real_from_decimal(); + int save_time_in_field(Field *field); + int save_date_in_field(Field *field); + 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; } @@ -711,6 +704,11 @@ public: virtual bool is_null() { return 0; } /* + Make sure the null_value member has a correct value. + */ + virtual void update_null_value () { (void) val_int(); } + + /* Inform the item that there will be no distinction between its result being FALSE or NULL. @@ -1277,6 +1275,7 @@ public: bool get_date_result(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); bool is_null() { return field->is_null(); } + void update_null_value(); Item *get_tmp_table_item(THD *thd); bool collect_item_field_processor(byte * arg); bool find_item_in_field_list_processor(byte *arg); @@ -1959,6 +1958,16 @@ public: class Item_in_subselect; + +/* + An object of this class: + - Converts val_XXX() calls to ref->val_XXX_result() calls, like Item_ref. + - Sets owner->was_null=TRUE if it has returned a NULL value from any + val_XXX() function. This allows to inject an Item_ref_null_helper + object into subquery and then check if the subquery has produced a row + with NULL value. +*/ + class Item_ref_null_helper: public Item_ref { protected: diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 9a400d60ae6..29fa049b6c4 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -786,9 +786,41 @@ longlong Item_in_optimizer::val_int() { DBUG_ASSERT(fixed == 1); cache->store(args[0]); + if (cache->null_value) { - null_value= 1; + if (((Item_in_subselect*)args[1])->is_top_level_item()) + { + /* + We're evaluating "NULL IN (SELECT ...)". The result can be NULL or + FALSE, and we can return one instead of another. Just return NULL. + */ + null_value= 1; + } + else + { + if (!((Item_in_subselect*)args[1])->is_correlated && + result_for_null_param != UNKNOWN) + { + /* Use cached value from previous execution */ + null_value= result_for_null_param; + } + else + { + /* + We're evaluating "NULL IN (SELECT ...)". The result is: + FALSE if SELECT produces an empty set, or + NULL otherwise. + We disable the predicates we've pushed down into subselect, run the + subselect and see if it has produced any rows. + */ + ((Item_in_subselect*)args[1])->enable_pushed_conds= FALSE; + longlong tmp= args[1]->val_bool_result(); + result_for_null_param= null_value= + !((Item_in_subselect*)args[1])->engine->no_rows(); + ((Item_in_subselect*)args[1])->enable_pushed_conds= TRUE; + } + } return 0; } bool tmp= args[1]->val_bool_result(); @@ -2196,7 +2228,7 @@ cmp_item* cmp_item_row::make_same() cmp_item_row::~cmp_item_row() { DBUG_ENTER("~cmp_item_row"); - DBUG_PRINT("enter",("this: 0x%lx", this)); + DBUG_PRINT("enter",("this: 0x%lx", (long) this)); if (comparators) { for (uint i= 0; i < n; i++) @@ -2465,7 +2497,6 @@ void Item_func_in::fix_length_and_dec() if (cmp_type == STRING_RESULT) in_item->cmp_charset= cmp_collation.collation; } - maybe_null= args[0]->maybe_null; max_length= 1; } @@ -2971,7 +3002,7 @@ longlong Item_is_not_null_test::val_int() if (!used_tables_cache) { owner->was_null|= (!cached_value); - DBUG_PRINT("info", ("cached :%d", cached_value)); + DBUG_PRINT("info", ("cached :%ld", (long) cached_value)); DBUG_RETURN(cached_value); } if (args[0]->is_null()) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index c8439cba303..acad1e51bc9 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -100,25 +100,44 @@ public: }; class Item_cache; +#define UNKNOWN ((my_bool)-1) + + +/* + Item_in_optimizer(left_expr, Item_in_subselect(...)) + + Item_in_optimizer is used to wrap an instance of Item_in_subselect. This + class does the following: + - Evaluate the left expression and store it in Item_cache_* object (to + avoid re-evaluating it many times during subquery execution) + - Shortcut the evaluation of "NULL IN (...)" to NULL in the cases where we + don't care if the result is NULL or FALSE. + + NOTE + It is not quite clear why the above listed functionality should be + placed into a separate class called 'Item_in_optimizer'. +*/ + class Item_in_optimizer: public Item_bool_func { protected: Item_cache *cache; bool save_cache; + /* + Stores the value of "NULL IN (SELECT ...)" for uncorrelated subqueries: + UNKNOWN - "NULL in (SELECT ...)" has not yet been evaluated + FALSE - result is FALSE + TRUE - result is NULL + */ + my_bool result_for_null_param; public: Item_in_optimizer(Item *a, Item_in_subselect *b): - Item_bool_func(a, my_reinterpret_cast(Item *)(b)), cache(0), save_cache(0) + Item_bool_func(a, my_reinterpret_cast(Item *)(b)), cache(0), + save_cache(0), result_for_null_param(UNKNOWN) {} bool fix_fields(THD *, Item **); bool fix_left(THD *thd, Item **ref); bool is_null(); - /* - Item_in_optimizer item is special boolean function. On value request - (one of val, val_int or val_str methods) it evaluate left expression - of IN by storing it value in cache item (one of Item_cache* items), - then it test cache is it NULL. If left expression (cache) is NULL then - Item_in_optimizer return NULL, else it evaluate Item_in_subselect. - */ longlong val_int(); void cleanup(); const char *func_name() const { return "<in_optimizer>"; } @@ -256,9 +275,11 @@ public: class Item_maxmin_subselect; /* + trigcond<param>(arg) ::= param? arg : TRUE + The class Item_func_trig_cond is used for guarded predicates which are employed only for internal purposes. - A guarded predicates is an object consisting of an a regular or + A guarded predicate is an object consisting of an a regular or a guarded predicate P and a pointer to a boolean guard variable g. A guarded predicate P/g is evaluated to true if the value of the guard g is false, otherwise it is evaluated to the same value that @@ -276,6 +297,10 @@ class Item_maxmin_subselect; Objects of this class are built only for query execution after the execution plan has been already selected. That's why this class needs only val_int out of generic methods. + + Current uses of Item_func_trig_cond objects: + - To wrap selection conditions when executing outer joins + - To wrap condition that is pushed down into subquery */ class Item_func_trig_cond: public Item_bool_func @@ -1019,6 +1044,11 @@ public: /* Functions used by HAVING for rewriting IN subquery */ class Item_in_subselect; + +/* + This is like IS NOT NULL but it also remembers if it ever has + encountered a NULL. +*/ class Item_is_not_null_test :public Item_func_isnull { Item_in_subselect* owner; diff --git a/sql/item_func.cc b/sql/item_func.cc index 6e81b03d846..e5ac133e35e 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -900,7 +900,8 @@ void Item_func_signed::print(String *str) longlong Item_func_signed::val_int_from_str(int *error) { - char buff[MAX_FIELD_WIDTH], *end; + char buff[MAX_FIELD_WIDTH], *end, *start; + uint32 length; String tmp(buff,sizeof(buff), &my_charset_bin), *res; longlong value; @@ -916,13 +917,21 @@ longlong Item_func_signed::val_int_from_str(int *error) return 0; } null_value= 0; - end= (char*) res->ptr()+ res->length(); - value= my_strtoll10(res->ptr(), &end, error); - if (*error > 0 || end != res->ptr()+ res->length()) + start= (char *)res->ptr(); + length= res->length(); + + end= start + length; + value= my_strtoll10(start, &end, error); + if (*error > 0 || end != start+ length) + { + char err_buff[128]; + String err_tmp(err_buff,(uint32) sizeof(err_buff), system_charset_info); + err_tmp.copy(start, length, system_charset_info); push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE, ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER", - res->c_ptr()); + err_tmp.c_ptr()); + } return value; } @@ -964,7 +973,14 @@ longlong Item_func_unsigned::val_int() longlong value; int error; - if (args[0]->cast_to_int_type() != STRING_RESULT) + if (args[0]->cast_to_int_type() == DECIMAL_RESULT) + { + my_decimal tmp, *dec= args[0]->val_decimal(&tmp); + if (!(null_value= args[0]->null_value)) + my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &value); + return value; + } + else if (args[0]->cast_to_int_type() != STRING_RESULT) { value= args[0]->val_int(); null_value= args[0]->null_value; @@ -2330,7 +2346,7 @@ longlong Item_func_locate::val_int() return 0; /* start is now sufficiently valid to pass to charpos function */ - start= a->charpos(start); + start= a->charpos((int) start); if (start + b->length() > a->length()) return 0; @@ -2340,7 +2356,8 @@ longlong Item_func_locate::val_int() return start + 1; if (!cmp_collation.collation->coll->instr(cmp_collation.collation, - a->ptr()+start, a->length()-start, + a->ptr()+start, + (uint) (a->length()-start), b->ptr(), b->length(), &match, 1)) return 0; @@ -2894,6 +2911,20 @@ void Item_udf_func::cleanup() } +void Item_udf_func::print(String *str) +{ + str->append(func_name()); + str->append('('); + for (uint i=0 ; i < arg_count ; i++) + { + if (i != 0) + str->append(','); + args[i]->print_item_w_name(str); + } + str->append(')'); +} + + double Item_func_udf_float::val_real() { DBUG_ASSERT(fixed == 1); @@ -4279,7 +4310,7 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const bool Item_func_get_user_var::set_value(THD *thd, - sp_rcontext */*ctx*/, Item **it) + sp_rcontext * /*ctx*/, Item **it) { Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), *it); /* @@ -4870,6 +4901,7 @@ Item_func_sp::cleanup() result_field= NULL; } m_sp= NULL; + dummy_table->s= NULL; Item_func::cleanup(); } diff --git a/sql/item_func.h b/sql/item_func.h index f887ba6a7cd..92bc870d509 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -157,7 +157,7 @@ public: return (null_value=args[0]->get_time(ltime)); } bool is_null() { - (void) val_int(); /* Discard result. It sets null_value as side-effect. */ + update_null_value(); return null_value; } void signal_divide_by_null(); @@ -241,7 +241,7 @@ public: virtual double real_op()= 0; virtual my_decimal *decimal_op(my_decimal *)= 0; virtual String *str_op(String *)= 0; - bool is_null() { (void) val_real(); return null_value; } + bool is_null() { update_null_value(); return null_value; } }; /* function where type of result detected by first argument */ @@ -953,6 +953,7 @@ public: Item_result result_type () const { return udf.result_type(); } table_map not_null_tables() const { return 0; } bool is_expensive() { return 1; } + void print(String *str); }; @@ -1291,7 +1292,7 @@ public: Item_func_inet_aton(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "inet_aton"; } - void fix_length_and_dec() { decimals = 0; max_length = 21; maybe_null=1;} + void fix_length_and_dec() { decimals = 0; max_length = 21; maybe_null=1;unsigned_flag=1;} }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index c2f16ffac10..0b48a00012a 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -80,6 +80,20 @@ String *Item_str_func::check_well_formed_result(String *str) } +bool Item_str_func::fix_fields(THD *thd, Item **ref) +{ + bool res= Item_func::fix_fields(thd, ref); + /* + In Item_str_func::check_well_formed_result() we may set null_value + flag on the same condition as in test() below. + */ + maybe_null= (maybe_null || + test(thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); + return res; +} + + my_decimal *Item_str_func::val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); @@ -969,8 +983,8 @@ String *Item_func_insert::val_str(String *str) length= res->length() + 1; /* start and length are now sufficiently valid to pass to charpos function */ - start= res->charpos(start); - length= res->charpos(length, start); + start= res->charpos((int) start); + length= res->charpos((int) length, (uint32) start); /* Re-testing with corrected params */ if (start > res->length() + 1) @@ -978,8 +992,8 @@ String *Item_func_insert::val_str(String *str) if (length > res->length() - start) length= res->length() - start; - if (res->length() - length + res2->length() > - current_thd->variables.max_allowed_packet) + if ((ulonglong) (res->length() - length + res2->length()) > + (ulonglong) current_thd->variables.max_allowed_packet) { push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_ALLOWED_PACKET_OVERFLOWED, @@ -988,7 +1002,7 @@ String *Item_func_insert::val_str(String *str) goto null; } res=copy_if_not_alloced(str,res,res->length()); - res->replace(start,length,*res2); + res->replace((uint32) start,(uint32) length,*res2); return res; null: null_value=1; @@ -1064,7 +1078,7 @@ String *Item_func_left::val_str(String *str) return &my_empty_string; if ((res->length() <= (ulonglong) length) || - (res->length() <= (char_pos= res->charpos(length)))) + (res->length() <= (char_pos= res->charpos((int) length)))) return res; tmp_value.set(*res, 0, char_pos); @@ -1156,17 +1170,17 @@ String *Item_func_substr::val_str(String *str) return &my_empty_string; start= ((start < 0) ? res->numchars() + start : start - 1); - start= res->charpos(start); + start= res->charpos((int) start); if ((start < 0) || ((uint) start + 1 > res->length())) return &my_empty_string; - length= res->charpos(length, start); + length= res->charpos((int) length, (uint32) start); tmp_length= res->length() - start; length= min(length, tmp_length); - if (!start && res->length() == (ulonglong) length) + if (!start && (longlong) res->length() == length) return res; - tmp_value.set(*res, (ulonglong) start, (ulonglong) length); + tmp_value.set(*res, (uint32) start, (uint32) length); return &tmp_value; } @@ -2214,7 +2228,7 @@ String *Item_func_repeat::val_str(String *str) char *to; /* must be longlong to avoid truncation */ longlong tmp_count= args[1]->val_int(); - long count= tmp_count; + long count= (long) tmp_count; String *res= args[0]->val_str(str); /* Assumes that the maximum length of a String is < INT_MAX32. */ @@ -2316,7 +2330,7 @@ String *Item_func_rpad::val_str(String *str) if (count <= (res_char_length= res->numchars())) { // String to pad is big enough - res->length(res->charpos(count)); // Shorten result if longer + res->length(res->charpos((int) count)); // Shorten result if longer return (res); } pad_char_length= rpad->numchars(); @@ -2333,7 +2347,7 @@ String *Item_func_rpad::val_str(String *str) if (args[2]->null_value || !pad_char_length) goto err; res_byte_length= res->length(); /* Must be done before alloc_buffer */ - if (!(res= alloc_buffer(res,str,&tmp_value,byte_count))) + if (!(res= alloc_buffer(res,str,&tmp_value, (ulong) byte_count))) goto err; to= (char*) res->ptr()+res_byte_length; @@ -2347,7 +2361,7 @@ String *Item_func_rpad::val_str(String *str) } if (count) { - pad_byte_length= rpad->charpos(count); + pad_byte_length= rpad->charpos((int) count); memcpy(to,ptr_pad,(size_t) pad_byte_length); to+= pad_byte_length; } @@ -2419,14 +2433,14 @@ String *Item_func_lpad::val_str(String *str) if (count <= res_char_length) { - res->length(res->charpos(count)); + res->length(res->charpos((int) count)); return res; } pad_char_length= pad->numchars(); byte_count= count * collation.collation->mbmaxlen; - if (byte_count > current_thd->variables.max_allowed_packet) + if ((ulonglong) byte_count > current_thd->variables.max_allowed_packet) { push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_ALLOWED_PACKET_OVERFLOWED, @@ -2435,7 +2449,8 @@ String *Item_func_lpad::val_str(String *str) goto err; } - if (args[2]->null_value || !pad_char_length || str->alloc(byte_count)) + if (args[2]->null_value || !pad_char_length || + str->alloc((uint32) byte_count)) goto err; str->length(0); @@ -2447,7 +2462,7 @@ String *Item_func_lpad::val_str(String *str) count-= pad_char_length; } if (count > 0) - str->append(pad->ptr(), pad->charpos(count), collation.collation); + str->append(pad->ptr(), pad->charpos((int) count), collation.collation); str->append(*res); null_value= 0; @@ -2777,7 +2792,7 @@ String *Item_load_file::val_str(String *str) tmp_value.length(stat_info.st_size); my_close(file, MYF(0)); null_value = 0; - return &tmp_value; + DBUG_RETURN(&tmp_value); err: null_value = 1; @@ -3267,4 +3282,3 @@ String *Item_func_uuid::val_str(String *str) strmov(s+18, clock_seq_and_node_str); return str; } - diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 528180b803d..fd2aaf19675 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -37,6 +37,7 @@ public: enum Item_result result_type () const { return STRING_RESULT; } void left_right_max_length(); String *check_well_formed_result(String *str); + bool fix_fields(THD *thd, Item **ref); }; class Item_func_md5 :public Item_str_func @@ -525,9 +526,8 @@ public: { collation.set(cs); } String *val_str(String *); void fix_length_and_dec() - { - maybe_null=0; - max_length=arg_count * collation.collation->mbmaxlen; + { + max_length= arg_count * collation.collation->mbmaxlen; } const char *func_name() const { return "char"; } }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 0ad517609c9..bffecb3c84c 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -37,7 +37,7 @@ inline Item * and_items(Item* cond, Item *item) Item_subselect::Item_subselect(): Item_result_field(), value_assigned(0), thd(0), substitution(0), engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0), - const_item_cache(1), engine_changed(0), changed(0) + const_item_cache(1), engine_changed(0), changed(0), is_correlated(FALSE) { with_subselect= 1; reset(); @@ -54,7 +54,7 @@ void Item_subselect::init(st_select_lex *select_lex, { DBUG_ENTER("Item_subselect::init"); - DBUG_PRINT("enter", ("select_lex: 0x%x", (ulong) select_lex)); + DBUG_PRINT("enter", ("select_lex: 0x%lx", (long) select_lex)); unit= select_lex->master_unit(); if (unit->item) @@ -192,16 +192,16 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref) return res; } -bool Item_subselect::exec() +bool Item_subselect::exec(bool full_scan) { int res; - res= engine->exec(); + res= engine->exec(full_scan); if (engine_changed) { engine_changed= 0; - return exec(); + return exec(full_scan); } return (res); } @@ -391,6 +391,15 @@ enum Item_result Item_singlerow_subselect::result_type() const return engine->type(); } +/* + Don't rely on the result type to calculate field type. + Ask the engine instead. +*/ +enum_field_types Item_singlerow_subselect::field_type() const +{ + return engine->field_type(); +} + void Item_singlerow_subselect::fix_length_and_dec() { if ((max_columns= engine->cols()) == 1) @@ -441,13 +450,13 @@ bool Item_singlerow_subselect::null_inside() void Item_singlerow_subselect::bring_value() { - exec(); + exec(FALSE); } double Item_singlerow_subselect::val_real() { DBUG_ASSERT(fixed == 1); - if (!exec() && !value->null_value) + if (!exec(FALSE) && !value->null_value) { null_value= 0; return value->val_real(); @@ -462,7 +471,7 @@ double Item_singlerow_subselect::val_real() longlong Item_singlerow_subselect::val_int() { DBUG_ASSERT(fixed == 1); - if (!exec() && !value->null_value) + if (!exec(FALSE) && !value->null_value) { null_value= 0; return value->val_int(); @@ -476,7 +485,7 @@ longlong Item_singlerow_subselect::val_int() String *Item_singlerow_subselect::val_str(String *str) { - if (!exec() && !value->null_value) + if (!exec(FALSE) && !value->null_value) { null_value= 0; return value->val_str(str); @@ -491,7 +500,7 @@ String *Item_singlerow_subselect::val_str(String *str) my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value) { - if (!exec() && !value->null_value) + if (!exec(FALSE) && !value->null_value) { null_value= 0; return value->val_decimal(decimal_value); @@ -506,7 +515,7 @@ my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value) bool Item_singlerow_subselect::val_bool() { - if (!exec() && !value->null_value) + if (!exec(FALSE) && !value->null_value) { null_value= 0; return value->val_bool(); @@ -557,7 +566,8 @@ bool Item_in_subselect::test_limit(SELECT_LEX_UNIT *unit) Item_in_subselect::Item_in_subselect(Item * left_exp, st_select_lex *select_lex): - Item_exists_subselect(), optimizer(0), transformed(0), upper_item(0) + Item_exists_subselect(), optimizer(0), transformed(0), + enable_pushed_conds(TRUE), upper_item(0) { DBUG_ENTER("Item_in_subselect::Item_in_subselect"); left_expr= left_exp; @@ -602,7 +612,7 @@ void Item_exists_subselect::fix_length_and_dec() double Item_exists_subselect::val_real() { DBUG_ASSERT(fixed == 1); - if (exec()) + if (exec(FALSE)) { reset(); return 0; @@ -613,7 +623,7 @@ double Item_exists_subselect::val_real() longlong Item_exists_subselect::val_int() { DBUG_ASSERT(fixed == 1); - if (exec()) + if (exec(FALSE)) { reset(); return 0; @@ -624,7 +634,7 @@ longlong Item_exists_subselect::val_int() String *Item_exists_subselect::val_str(String *str) { DBUG_ASSERT(fixed == 1); - if (exec()) + if (exec(FALSE)) { reset(); return 0; @@ -637,7 +647,7 @@ String *Item_exists_subselect::val_str(String *str) my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); - if (exec()) + if (exec(FALSE)) { reset(); return 0; @@ -650,7 +660,7 @@ my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value) bool Item_exists_subselect::val_bool() { DBUG_ASSERT(fixed == 1); - if (exec()) + if (exec(FALSE)) { reset(); return 0; @@ -667,7 +677,8 @@ double Item_in_subselect::val_real() */ DBUG_ASSERT(0); DBUG_ASSERT(fixed == 1); - if (exec()) + null_value= 0; + if (exec(!enable_pushed_conds)) { reset(); null_value= 1; @@ -687,7 +698,8 @@ longlong Item_in_subselect::val_int() */ DBUG_ASSERT(0); DBUG_ASSERT(fixed == 1); - if (exec()) + null_value= 0; + if (exec(!enable_pushed_conds)) { reset(); null_value= 1; @@ -707,7 +719,8 @@ String *Item_in_subselect::val_str(String *str) */ DBUG_ASSERT(0); DBUG_ASSERT(fixed == 1); - if (exec()) + null_value= 0; + if (exec(!enable_pushed_conds)) { reset(); null_value= 1; @@ -726,7 +739,8 @@ String *Item_in_subselect::val_str(String *str) bool Item_in_subselect::val_bool() { DBUG_ASSERT(fixed == 1); - if (exec()) + null_value= 0; + if (exec(!enable_pushed_conds)) { reset(); null_value= 1; @@ -744,8 +758,9 @@ my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value) method should not be used */ DBUG_ASSERT(0); + null_value= 0; DBUG_ASSERT(fixed == 1); - if (exec()) + if (exec(!enable_pushed_conds)) { reset(); null_value= 1; @@ -758,7 +773,55 @@ my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value) } -/* Rewrite a single-column IN/ALL/ANY subselect. */ +/* + Rewrite a single-column IN/ALL/ANY subselect + + SYNOPSIS + Item_in_subselect::single_value_transformer() + join Join object of the subquery (i.e. 'child' join). + func Subquery comparison creator + + DESCRIPTION + Rewrite a single-column subquery using rule-based approach. The subquery + + oe $cmp$ (SELECT ie FROM ... WHERE subq_where ... HAVING subq_having) + + First, try to convert the subquery to scalar-result subquery in one of + the forms: + + - oe $cmp$ (SELECT MAX(...) ) // handled by Item_singlerow_subselect + - oe $cmp$ <max>(SELECT ...) // handled by Item_maxmin_subselect + + If that fails, the subquery will be handled with class Item_in_optimizer, + Inject the predicates into subquery, i.e. convert it to: + + - If the subquery has aggregates, GROUP BY, or HAVING, convert to + + SELECT ie FROM ... HAVING subq_having AND + trigcond(oe $cmp$ ref_or_null_helper<ie>) + + the addition is wrapped into trigger only when we want to distinguish + between NULL and FALSE results. + + - Otherwise (no aggregates/GROUP BY/HAVING) convert it to one of the + following: + + = If we don't need to distinguish between NULL and FALSE subquery: + + SELECT 1 FROM ... WHERE (oe $cmp$ ie) AND subq_where + + = If we need to distinguish between those: + + SELECT 1 FROM ... + WHERE subq_where AND trigcond((oe $cmp$ ie) OR (ie IS NULL)) + HAVING trigcond(<is_not_null_test>(ie)) + + RETURN + RES_OK - OK, either subquery was transformed, or appopriate + predicates where injected into it. + RES_REDUCE - The subquery was reduced to non-subquery + RES_ERROR - Error +*/ Item_subselect::trans_res Item_in_subselect::single_value_transformer(JOIN *join, @@ -891,8 +954,12 @@ Item_in_subselect::single_value_transformer(JOIN *join, select_lex->uncacheable|= UNCACHEABLE_DEPENDENT; /* Add the left part of a subselect to a WHERE or HAVING clause of - the right part, e.g. SELECT 1 IN (SELECT a FROM t1) => - SELECT Item_in_optimizer(1, SELECT a FROM t1 WHERE a=1) + the right part, e.g. + + SELECT 1 IN (SELECT a FROM t1) => + + SELECT Item_in_optimizer(1, SELECT a FROM t1 WHERE a=1) + HAVING is used only if the right part contains a SUM function, a GROUP BY or a HAVING clause. */ @@ -907,10 +974,15 @@ Item_in_subselect::single_value_transformer(JOIN *join, ref_pointer_array, (char *)"<ref>", this->full_name())); -#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE - if (!abort_on_null && left_expr->maybe_null) - item= new Item_cond_or(new Item_func_isnull(left_expr), item); -#endif + if (!abort_on_null && ((Item*)select_lex->item_list.head())->maybe_null) + { + /* + We can encounter "NULL IN (SELECT ...)". Wrap the added condition + within a trigger. + */ + item= new Item_func_trig_cond(item, &enable_pushed_conds); + } + /* AND and comparison functions can't be changed during fix_fields() we can assign select_lex->having here, and pass 0 as last @@ -939,19 +1011,19 @@ Item_in_subselect::single_value_transformer(JOIN *join, select_lex->item_list.push_back(new Item_int("Not_used", (longlong) 1, 21)); select_lex->ref_pointer_array[0]= select_lex->item_list.head(); + item= func->create(expr, item); if (!abort_on_null && orig_item->maybe_null) { - having= new Item_is_not_null_test(this, having); + having= + new Item_func_trig_cond(new Item_is_not_null_test(this, having), + &enable_pushed_conds); /* Item_is_not_null_test can't be changed during fix_fields() we can assign select_lex->having here, and pass 0 as last argument (reference) to fix_fields() */ - select_lex->having= - join->having= (join->having ? - new Item_cond_and(having, join->having) : - having); + select_lex->having= join->having= having; select_lex->having_fix_field= 1; /* we do not check join->having->fixed, because Item_and (from @@ -962,12 +1034,15 @@ Item_in_subselect::single_value_transformer(JOIN *join, select_lex->having_fix_field= 0; if (tmp) DBUG_RETURN(RES_ERROR); + /* + NOTE: It is important that we add this "IS NULL" here, even when + orig_item can't be NULL. This is needed so that this predicate is + only used by ref[_or_null] analyzer (and, e.g. is not used by const + propagation). + */ item= new Item_cond_or(item, new Item_func_isnull(orig_item)); -#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE - if (left_expr->maybe_null) - item= new Item_cond_or(new Item_func_isnull(left_expr), item); -#endif + item= new Item_func_trig_cond(item, &enable_pushed_conds); } item->name= (char *)in_additional_cond; /* @@ -994,13 +1069,14 @@ Item_in_subselect::single_value_transformer(JOIN *join, we can assign select_lex->having here, and pass 0 as last argument (reference) to fix_fields() */ - select_lex->having= - join->having= - func->create(expr, + Item *new_having= + func->create(expr, new Item_ref_null_helper(&select_lex->context, this, select_lex->ref_pointer_array, (char *)"<no matter>", (char *)"<result>")); + new_having= new Item_func_trig_cond(new_having, &enable_pushed_conds); + select_lex->having= join->having= new_having; select_lex->having_fix_field= 1; /* @@ -1205,6 +1281,8 @@ Item_in_subselect::row_value_transformer(JOIN *join) where_item= and_items(where_item, item); } + if (where_item) + where_item= new Item_func_trig_cond(where_item, &enable_pushed_conds); /* AND can't be changed during fix_fields() we can assign select_lex->where here, and pass 0 as last @@ -1218,6 +1296,8 @@ Item_in_subselect::row_value_transformer(JOIN *join) if (having_item) { bool res; + having_item= new Item_func_trig_cond(having_item, &enable_pushed_conds); + select_lex->having= join->having= and_items(join->having, having_item); select_lex->having->top_level_item(); /* @@ -1434,6 +1514,27 @@ bool subselect_union_engine::is_executed() const } +/* + Check if last execution of the subquery engine produced any rows + + SYNOPSIS + subselect_union_engine::no_rows() + + DESCRIPTION + Check if last execution of the subquery engine produced any rows. The + return value is undefined if last execution ended in an error. + + RETURN + TRUE - Last subselect execution has produced no rows + FALSE - Otherwise +*/ + +bool subselect_union_engine::no_rows() +{ + /* Check if we got any rows when reading UNION result from temp. table: */ + return test(!unit->fake_select_lex->join->send_records); +} + void subselect_uniquesubquery_engine::cleanup() { DBUG_ENTER("subselect_uniquesubquery_engine::cleanup"); @@ -1499,32 +1600,58 @@ int subselect_uniquesubquery_engine::prepare() return 1; } -static Item_result set_row(List<Item> &item_list, Item *item, - Item_cache **row, bool *maybe_null) + +/* + Check if last execution of the subquery engine produced any rows + + SYNOPSIS + subselect_single_select_engine::no_rows() + + DESCRIPTION + Check if last execution of the subquery engine produced any rows. The + return value is undefined if last execution ended in an error. + + RETURN + TRUE - Last subselect execution has produced no rows + FALSE - Otherwise +*/ + +bool subselect_single_select_engine::no_rows() +{ + return !item->assigned(); +} + + +/* + makes storage for the output values for the subquery and calcuates + their data and column types and their nullability. +*/ +void subselect_engine::set_row(List<Item> &item_list, Item_cache **row) { - Item_result res_type= STRING_RESULT; Item *sel_item; List_iterator_fast<Item> li(item_list); + res_type= STRING_RESULT; + res_field_type= FIELD_TYPE_VAR_STRING; for (uint i= 0; (sel_item= li++); i++) { item->max_length= sel_item->max_length; res_type= sel_item->result_type(); + res_field_type= sel_item->field_type(); item->decimals= sel_item->decimals; item->unsigned_flag= sel_item->unsigned_flag; - *maybe_null= sel_item->maybe_null; + maybe_null= sel_item->maybe_null; if (!(row[i]= Item_cache::get_cache(res_type))) - return STRING_RESULT; // we should return something + return; row[i]->setup(sel_item); } if (item_list.elements > 1) res_type= ROW_RESULT; - return res_type; } void subselect_single_select_engine::fix_length_and_dec(Item_cache **row) { DBUG_ASSERT(row || select_lex->item_list.elements==1); - res_type= set_row(select_lex->item_list, item, row, &maybe_null); + set_row(select_lex->item_list, row); item->collation.set(row[0]->collation); if (cols() != 1) maybe_null= 0; @@ -1536,13 +1663,14 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row) if (unit->first_select()->item_list.elements == 1) { - res_type= set_row(unit->types, item, row, &maybe_null); + set_row(unit->types, row); item->collation.set(row[0]->collation); } else { - bool fake= 0; - res_type= set_row(unit->types, item, row, &fake); + bool maybe_null_saved= maybe_null; + set_row(unit->types, row); + maybe_null= maybe_null_saved; } } @@ -1552,7 +1680,11 @@ void subselect_uniquesubquery_engine::fix_length_and_dec(Item_cache **row) DBUG_ASSERT(0); } -int subselect_single_select_engine::exec() +int init_read_record_seq(JOIN_TAB *tab); +int join_read_always_key_or_null(JOIN_TAB *tab); +int join_read_next_same_or_null(READ_RECORD *info); + +int subselect_single_select_engine::exec(bool full_scan) { DBUG_ENTER("subselect_single_select_engine::exec"); char const *save_where= thd->where; @@ -1590,7 +1722,43 @@ int subselect_single_select_engine::exec() if (!executed) { item->reset_value_registration(); + if (full_scan) + { + /* + We should not apply optimizations based on the condition that was + pushed down into the subquery. Those optimizations are ref[_or_null] + acceses. Change them to be full table scans. + */ + for (uint i=join->const_tables ; i < join->tables ; i++) + { + JOIN_TAB *tab=join->join_tab+i; + if (tab->keyuse && tab->keyuse->outer_ref) + { + tab->read_first_record= init_read_record_seq; + tab->read_record.record= tab->table->record[0]; + tab->read_record.thd= join->thd; + tab->read_record.ref_length= tab->table->file->ref_length; + } + } + } + join->exec(); + + if (full_scan) + { + /* Enable the optimizations back */ + for (uint i=join->const_tables ; i < join->tables ; i++) + { + JOIN_TAB *tab=join->join_tab+i; + if (tab->keyuse && tab->keyuse->outer_ref) + { + tab->read_record.record= 0; + tab->read_record.ref_length= 0; + tab->read_first_record= join_read_always_key_or_null; + tab->read_record.read_record= join_read_next_same_or_null; + } + } + } executed= 1; thd->where= save_where; thd->lex->current_select= save_select; @@ -1601,29 +1769,159 @@ int subselect_single_select_engine::exec() DBUG_RETURN(0); } -int subselect_union_engine::exec() +int subselect_union_engine::exec(bool full_scan) { char const *save_where= thd->where; + /* + Ignore the full_scan parameter: the pushed down predicates are only used + for filtering, and the caller has disabled them if necessary. + */ int res= unit->exec(); thd->where= save_where; return res; } -int subselect_uniquesubquery_engine::exec() +/* + Search for at least on row satisfying select condition + + SYNOPSIS + subselect_uniquesubquery_engine::scan_table() + + DESCRIPTION + Scan the table using sequential access until we find at least one row + satisfying select condition. + + The result of this function (info about whether a row was found) is + stored in this->empty_result_set. + + RETURN + FALSE - OK + TRUE - Error +*/ + +int subselect_uniquesubquery_engine::scan_table() { - DBUG_ENTER("subselect_uniquesubquery_engine::exec"); int error; TABLE *table= tab->table; - for (store_key **copy=tab->ref.key_copy ; *copy ; copy++) + DBUG_ENTER("subselect_uniquesubquery_engine::scan_table"); + empty_result_set= TRUE; + + if (table->file->inited) + table->file->ha_index_end(); + + table->file->ha_rnd_init(1); + table->file->extra_opt(HA_EXTRA_CACHE, + current_thd->variables.read_buff_size); + table->null_row= 0; + for (;;) + { + error=table->file->rnd_next(table->record[0]); + if (error && error != HA_ERR_END_OF_FILE) + { + error= report_error(table, error); + break; + } + /* No more rows */ + if (table->status) + break; + + if (!cond || cond->val_int()) + { + empty_result_set= FALSE; + break; + } + } + + table->file->ha_rnd_end(); + DBUG_RETURN(error != 0); +} + + +/* + Copy ref key and check for null parts in it + + SYNOPSIS + subselect_uniquesubquery_engine::copy_ref_key() + + DESCRIPTION + Copy ref key and check for null parts in it. + + RETURN + FALSE - ok, index lookup key without keys copied. + TRUE - an error occured while copying the key +*/ + +bool subselect_uniquesubquery_engine::copy_ref_key() +{ + DBUG_ENTER("subselect_uniquesubquery_engine::copy_ref_key"); + + for (store_key **copy= tab->ref.key_copy ; *copy ; copy++) { - if ((tab->ref.key_err= (*copy)->copy()) & 1) + tab->ref.key_err= (*copy)->copy(); + + /* + When there is a NULL part in the key we don't need to make index + lookup for such key thus we don't need to copy whole key. + If we later should do a sequential scan return OK. Fail otherwise. + + See also the comment for the subselect_uniquesubquery_engine::exec() + function. + */ + null_keypart= (*copy)->null_key; + bool top_level= ((Item_in_subselect *) item)->is_top_level_item(); + if (null_keypart && !top_level) + break; + if ((tab->ref.key_err) & 1 || (null_keypart && top_level)) { - table->status= STATUS_NOT_FOUND; + tab->table->status= STATUS_NOT_FOUND; DBUG_RETURN(1); } } + DBUG_RETURN(0); +} + + +/* + Execute subselect + + SYNOPSIS + subselect_uniquesubquery_engine::exec() + DESCRIPTION + Find rows corresponding to the ref key using index access. + If some part of the lookup key is NULL, then we're evaluating + NULL IN (SELECT ... ) + This is a special case, we don't need to search for NULL in the table, + instead, the result value is + - NULL if select produces empty row set + - FALSE otherwise. + + In some cases (IN subselect is a top level item, i.e. abort_on_null==TRUE) + the caller doesn't distinguish between NULL and FALSE result and we just + return FALSE. + Otherwise we make a full table scan to see if there is at least one matching row. + + NOTE + + RETURN + FALSE - ok + TRUE - an error occured while scanning +*/ + +int subselect_uniquesubquery_engine::exec(bool full_scan) +{ + DBUG_ENTER("subselect_uniquesubquery_engine::exec"); + int error; + TABLE *table= tab->table; + + /* TODO: change to use of 'full_scan' here? */ + if (copy_ref_key()) + DBUG_RETURN(1); + + if (null_keypart) + DBUG_RETURN(scan_table()); + if (!table->file->inited) table->file->ha_index_init(tab->ref.key); error= table->file->index_read(table->record[0], @@ -1652,14 +1950,68 @@ subselect_uniquesubquery_engine::~subselect_uniquesubquery_engine() } -int subselect_indexsubquery_engine::exec() +/* + Index-lookup subselect 'engine' - run the subquery + + SYNOPSIS + subselect_uniquesubquery_engine:exec() + full_scan + + DESCRIPTION + The engine is used to resolve subqueries in form + + oe IN (SELECT key FROM tbl WHERE subq_where) + + The value of the predicate is calculated as follows: + 1. If oe IS NULL, this is a special case, do a full table scan on + table tbl and search for row that satisfies subq_where. If such + row is found, return NULL, otherwise return FALSE. + 2. Make an index lookup via key=oe, search for a row that satisfies + subq_where. If found, return TRUE. + 3. If check_null==TRUE, make another lookup via key=NULL, search for a + row that satisfies subq_where. If found, return NULL, otherwise + return FALSE. + + TODO + The step #1 can be optimized further when the index has several key + parts. Consider a subquery: + + (oe1, oe2) IN (SELECT keypart1, keypart2 FROM tbl WHERE subq_where) + + and suppose we need to evaluate it for {oe1, oe2}=={const1, NULL}. + Current code will do a full table scan and obtain correct result. There + is a better option: instead of evaluating + + SELECT keypart1, keypart2 FROM tbl WHERE subq_where (1) + + and checking if it has produced any matching rows, evaluate + + SELECT keypart2 FROM tbl WHERE subq_where AND keypart1=const1 (2) + + If this query produces a row, the result is NULL (as we're evaluating + "(const1, NULL) IN { (const1, X), ... }", which has a value of UNKNOWN, + i.e. NULL). If the query produces no rows, the result is FALSE. + + We currently evaluate (1) by doing a full table scan. (2) can be + evaluated by doing a "ref" scan on "keypart1=const1", which can be much + cheaper. We can use index statistics to quickly check whether "ref" scan + will be cheaper than full table scan. + + RETURN + 0 + 1 +*/ + +int subselect_indexsubquery_engine::exec(bool full_scan) { - DBUG_ENTER("subselect_indexsubselect_engine::exec"); + DBUG_ENTER("subselect_indexsubquery_engine::exec"); int error; bool null_finding= 0; TABLE *table= tab->table; ((Item_in_subselect *) item)->value= 0; + empty_result_set= TRUE; + null_keypart= 0; if (check_null) { @@ -1668,14 +2020,12 @@ int subselect_indexsubquery_engine::exec() ((Item_in_subselect *) item)->was_null= 0; } - for (store_key **copy=tab->ref.key_copy ; *copy ; copy++) - { - if ((tab->ref.key_err= (*copy)->copy()) & 1) - { - table->status= STATUS_NOT_FOUND; - DBUG_RETURN(1); - } - } + /* Copy the ref key and check for nulls... */ + if (copy_ref_key()) + DBUG_RETURN(1); + + if (null_keypart) + DBUG_RETURN(scan_table()); if (!table->file->inited) table->file->ha_index_init(tab->ref.key); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 45df4f3880d..35ded79b75d 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -60,6 +60,9 @@ public: /* subquery is transformed */ bool changed; + /* TRUE <=> The underlying SELECT is correlated w.r.t some ancestor select */ + bool is_correlated; + enum trans_res {RES_OK, RES_REDUCE, RES_ERROR}; enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS, EXISTS_SUBS, IN_SUBS, ALL_SUBS, ANY_SUBS}; @@ -88,11 +91,11 @@ public: enum Type type() const; bool is_null() { - val_int(); + update_null_value(); return null_value; } bool fix_fields(THD *thd, Item **ref); - virtual bool exec(); + virtual bool exec(bool full_scan); virtual void fix_length_and_dec(); table_map used_tables() const; table_map not_null_tables() const { return 0; } @@ -114,6 +117,7 @@ public: single select and union subqueries only. */ bool is_evaluated() const; + bool is_uncacheable() const; /* Used by max/min subquery to initialize value presence registration @@ -155,6 +159,7 @@ public: my_decimal *val_decimal(my_decimal *); bool val_bool(); enum Item_result result_type() const; + enum_field_types field_type() const; void fix_length_and_dec(); uint cols(); @@ -215,7 +220,20 @@ public: friend class subselect_indexsubquery_engine; }; -/* IN subselect */ + +/* + IN subselect: this represents "left_exr IN (SELECT ...)" + + This class has: + - (as a descendant of Item_subselect) a "subquery execution engine" which + allows it to evaluate subqueries. (and this class participates in + execution by having was_null variable where part of execution result + is stored. + - Transformation methods (todo: more on this). + + This class is not used directly, it is "wrapped" into Item_in_optimizer + which provides some small bits of subquery evaluation. +*/ class Item_in_subselect :public Item_exists_subselect { @@ -231,12 +249,14 @@ protected: bool abort_on_null; bool transformed; public: + /* Used to trigger on/off conditions that were pushed down to subselect */ + bool enable_pushed_conds; Item_func_not_all *upper_item; // point on NOT/NOP before ALL/SOME subquery Item_in_subselect(Item * left_expr, st_select_lex *select_lex); Item_in_subselect() :Item_exists_subselect(), optimizer(0), abort_on_null(0), transformed(0), - upper_item(0) + enable_pushed_conds(TRUE), upper_item(0) {} subs_type substype() { return IN_SUBS; } @@ -256,6 +276,7 @@ public: my_decimal *val_decimal(my_decimal *); bool val_bool(); void top_level_item() { abort_on_null=1; } + inline bool is_top_level_item() { return abort_on_null; } bool test_limit(st_select_lex_unit *unit); void print(String *str); bool fix_fields(THD *thd, Item **ref); @@ -291,6 +312,7 @@ protected: THD *thd; /* pointer to current THD */ Item_subselect *item; /* item, that use this engine */ enum Item_result res_type; /* type of results */ + enum_field_types res_field_type; /* column type of the results */ bool maybe_null; /* may be null (first item in select) */ public: @@ -300,6 +322,7 @@ public: result= res; item= si; res_type= STRING_RESULT; + res_field_type= FIELD_TYPE_VAR_STRING; maybe_null= 0; } virtual ~subselect_engine() {}; // to satisfy compiler @@ -313,10 +336,32 @@ public: THD * get_thd() { return thd; } virtual int prepare()= 0; virtual void fix_length_and_dec(Item_cache** row)= 0; - virtual int exec()= 0; + /* + Execute the engine + + SYNOPSIS + exec() + full_scan TRUE - Pushed-down predicates are disabled, the engine + must disable made based on those predicates. + FALSE - Pushed-down predicates are in effect. + DESCRIPTION + Execute the engine. The result of execution is subquery value that is + either captured by previously set up select_result-based 'sink' or + stored somewhere by the exec() method itself. + + A required side effect: if full_scan==TRUE, subselect_engine->no_rows() + should return correct result. + + RETURN + 0 - OK + 1 - Either an execution error, or the engine was be "changed", and + caller should call exec() again for the new engine. + */ + virtual int exec(bool full_scan)= 0; virtual uint cols()= 0; /* return number of columns in select */ virtual uint8 uncacheable()= 0; /* query is uncacheable */ enum Item_result type() { return res_type; } + enum_field_types field_type() { return res_field_type; } virtual void exclude()= 0; bool may_be_null() { return maybe_null; }; virtual table_map upper_select_const_tables()= 0; @@ -325,6 +370,11 @@ public: virtual bool change_result(Item_subselect *si, select_subselect *result)= 0; virtual bool no_tables()= 0; virtual bool is_executed() const { return FALSE; } + /* Check if subquery produced any rows during last query execution */ + virtual bool no_rows() = 0; + +protected: + void set_row(List<Item> &item_list, Item_cache **row); }; @@ -342,7 +392,7 @@ public: void cleanup(); int prepare(); void fix_length_and_dec(Item_cache** row); - int exec(); + int exec(bool full_scan); uint cols(); uint8 uncacheable(); void exclude(); @@ -351,6 +401,7 @@ public: bool change_result(Item_subselect *si, select_subselect *result); bool no_tables(); bool is_executed() const { return executed; } + bool no_rows(); }; @@ -364,7 +415,7 @@ public: void cleanup(); int prepare(); void fix_length_and_dec(Item_cache** row); - int exec(); + int exec(bool full_scan); uint cols(); uint8 uncacheable(); void exclude(); @@ -373,6 +424,7 @@ public: bool change_result(Item_subselect *si, select_subselect *result); bool no_tables(); bool is_executed() const; + bool no_rows(); }; @@ -382,6 +434,12 @@ class subselect_uniquesubquery_engine: public subselect_engine protected: st_join_table *tab; Item *cond; + /* + TRUE<=> last execution produced empty set. Valid only when left + expression is NULL. + */ + bool empty_result_set; + bool null_keypart; /* TRUE <=> constructed search tuple has a NULL */ public: // constructor can assign THD because it will be called after JOIN::prepare @@ -395,7 +453,7 @@ public: void cleanup(); int prepare(); void fix_length_and_dec(Item_cache** row); - int exec(); + int exec(bool full_scan); uint cols() { return 1; } uint8 uncacheable() { return UNCACHEABLE_DEPENDENT; } void exclude(); @@ -403,11 +461,15 @@ public: void print (String *str); bool change_result(Item_subselect *si, select_subselect *result); bool no_tables(); + int scan_table(); + bool copy_ref_key(); + bool no_rows() { return empty_result_set; } }; class subselect_indexsubquery_engine: public subselect_uniquesubquery_engine { + /* FALSE for 'ref', TRUE for 'ref-or-null'. */ bool check_null; public: @@ -418,7 +480,7 @@ public: :subselect_uniquesubquery_engine(thd, tab_arg, subs, where), check_null(chk_null) {} - int exec(); + int exec(bool full_scan); void print (String *str); }; @@ -428,3 +490,9 @@ inline bool Item_subselect::is_evaluated() const return engine->is_executed(); } +inline bool Item_subselect::is_uncacheable() const +{ + return engine->uncacheable(); +} + + diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 77c6e17607f..7b296019709 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -322,9 +322,13 @@ void Item_sum::make_field(Send_field *tmp_field) if (args[0]->type() == Item::FIELD_ITEM && keep_field_type()) { ((Item_field*) args[0])->field->make_field(tmp_field); - tmp_field->db_name=(char*)""; - tmp_field->org_table_name=tmp_field->table_name=(char*)""; - tmp_field->org_col_name=tmp_field->col_name=name; + /* For expressions only col_name should be non-empty string. */ + char *empty_string= (char*)""; + tmp_field->db_name= empty_string; + tmp_field->org_table_name= empty_string; + tmp_field->table_name= empty_string; + tmp_field->org_col_name= empty_string; + tmp_field->col_name= name; if (maybe_null) tmp_field->flags&= ~NOT_NULL_FLAG; } @@ -893,6 +897,7 @@ bool Item_sum_distinct::setup(THD *thd) tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length, thd->variables.max_heap_table_size); + is_evaluated= FALSE; DBUG_RETURN(tree == 0); } @@ -900,6 +905,7 @@ bool Item_sum_distinct::setup(THD *thd) bool Item_sum_distinct::add() { args[0]->save_in_field(table->field[0], FALSE); + is_evaluated= FALSE; if (!table->field[0]->is_null()) { DBUG_ASSERT(tree); @@ -929,6 +935,7 @@ void Item_sum_distinct::clear() DBUG_ASSERT(tree != 0); /* we always have a tree */ null_value= 1; tree->reset(); + is_evaluated= FALSE; DBUG_VOID_RETURN; } @@ -938,6 +945,7 @@ void Item_sum_distinct::cleanup() delete tree; tree= 0; table= 0; + is_evaluated= FALSE; } Item_sum_distinct::~Item_sum_distinct() @@ -949,16 +957,20 @@ Item_sum_distinct::~Item_sum_distinct() void Item_sum_distinct::calculate_val_and_count() { - count= 0; - val.traits->set_zero(&val); - /* - We don't have a tree only if 'setup()' hasn't been called; - this is the case of sql_select.cc:return_zero_rows. - */ - if (tree) + if (!is_evaluated) { - table->field[0]->set_notnull(); - tree->walk(item_sum_distinct_walk, (void*) this); + count= 0; + val.traits->set_zero(&val); + /* + We don't have a tree only if 'setup()' hasn't been called; + this is the case of sql_select.cc:return_zero_rows. + */ + if (tree) + { + table->field[0]->set_notnull(); + tree->walk(item_sum_distinct_walk, (void*) this); + } + is_evaluated= TRUE; } } @@ -1014,9 +1026,13 @@ Item_sum_avg_distinct::fix_length_and_dec() void Item_sum_avg_distinct::calculate_val_and_count() { - Item_sum_distinct::calculate_val_and_count(); - if (count) - val.traits->div(&val, count); + if (!is_evaluated) + { + Item_sum_distinct::calculate_val_and_count(); + if (count) + val.traits->div(&val, count); + is_evaluated= TRUE; + } } @@ -1038,7 +1054,7 @@ bool Item_sum_count::add() count++; else { - (void) args[0]->val_int(); + args[0]->update_null_value(); if (!args[0]->null_value) count++; } @@ -1945,7 +1961,7 @@ void Item_sum_count::reset_field() nr=1; else { - (void) args[0]->val_int(); + args[0]->update_null_value(); if (!args[0]->null_value) nr=1; } @@ -2055,7 +2071,7 @@ void Item_sum_count::update_field() nr++; else { - (void) args[0]->val_int(); + args[0]->update_null_value(); if (!args[0]->null_value) nr++; } @@ -2478,6 +2494,7 @@ void Item_sum_count_distinct::cleanup() */ delete tree; tree= 0; + is_evaluated= FALSE; if (table) { free_tmp_table(table->in_use, table); @@ -2499,6 +2516,7 @@ void Item_sum_count_distinct::make_unique() original= 0; force_copy_fields= 1; tree= 0; + is_evaluated= FALSE; tmp_table_param= 0; always_null= FALSE; } @@ -2533,7 +2551,7 @@ bool Item_sum_count_distinct::setup(THD *thd) return TRUE; // End of memory if (item->const_item()) { - (void) item->val_int(); + item->update_null_value(); if (item->null_value) always_null=1; } @@ -2618,6 +2636,7 @@ bool Item_sum_count_distinct::setup(THD *thd) but this has to be handled - otherwise someone can crash the server with a DoS attack */ + is_evaluated= FALSE; if (! tree) return TRUE; } @@ -2634,8 +2653,11 @@ Item *Item_sum_count_distinct::copy_or_same(THD* thd) void Item_sum_count_distinct::clear() { /* tree and table can be both null only if always_null */ + is_evaluated= FALSE; if (tree) + { tree->reset(); + } else if (table) { table->file->extra(HA_EXTRA_NO_CACHE); @@ -2656,6 +2678,7 @@ bool Item_sum_count_distinct::add() if ((*field)->is_real_null(0)) return 0; // Don't count NULL + is_evaluated= FALSE; if (tree) { /* @@ -2682,12 +2705,14 @@ longlong Item_sum_count_distinct::val_int() return LL(0); if (tree) { - ulonglong count; + if (is_evaluated) + return count; if (tree->elements == 0) return (longlong) tree->elements_in_tree(); // everything fits in memory count= 0; tree->walk(count_distinct_walk, (void*) &count); + is_evaluated= TRUE; return (longlong) count; } @@ -3001,6 +3026,7 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)), String tmp2; String *result= &item->result; Item **arg= item->args, **arg_end= item->args + item->arg_count_field; + uint old_length= result->length(); if (item->no_appended) item->no_appended= FALSE; @@ -3035,8 +3061,22 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)), /* stop if length of result more than max_length */ if (result->length() > item->max_length) { + int well_formed_error; + CHARSET_INFO *cs= item->collation.collation; + const char *ptr= result->ptr(); + uint add_length; + /* + It's ok to use item->result.length() as the fourth argument + as this is never used to limit the length of the data. + Cut is done with the third argument. + */ + add_length= cs->cset->well_formed_len(cs, + ptr + old_length, + ptr + item->max_length, + result->length(), + &well_formed_error); + result->length(old_length + add_length); item->count_cut_values++; - result->length(item->max_length); item->warning_for_row= TRUE; return 1; } @@ -3226,8 +3266,7 @@ bool Item_func_group_concat::add() we can dump the row here in case of GROUP_CONCAT(DISTINCT...) instead of doing tree traverse later. */ - if (result.length() <= max_length && - !warning_for_row && + if (!warning_for_row && (!tree || (el->count == 1 && distinct && !arg_count_order))) dump_leaf_key(table->record[0] + table->s->null_bytes, 1, this); @@ -3296,7 +3335,8 @@ bool Item_func_group_concat::setup(THD *thd) DBUG_RETURN(TRUE); /* We'll convert all blobs to varchar fields in the temporary table */ - tmp_table_param->convert_blob_length= max_length; + tmp_table_param->convert_blob_length= max_length * + collation.collation->mbmaxlen; /* Push all not constant fields to the list and create a temp table */ always_null= 0; for (uint i= 0; i < arg_count_field; i++) @@ -3373,8 +3413,8 @@ bool Item_func_group_concat::setup(THD *thd) duplicate values (according to the syntax of this function). If there is no DISTINCT or ORDER BY clauses, we don't create this tree. */ - init_tree(tree, min(thd->variables.max_heap_table_size, - thd->variables.sortbuff_size/16), 0, + init_tree(tree, (uint) min(thd->variables.max_heap_table_size, + thd->variables.sortbuff_size/16), 0, tree_key_length, compare_key, 0, NULL, (void*) this); } diff --git a/sql/item_sum.h b/sql/item_sum.h index fe7edd76ecf..ad05b3c9d12 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -352,12 +352,23 @@ public: class Item_sum_num :public Item_sum { +protected: + /* + val_xxx() functions may be called several times during the execution of a + query. Derived classes that require extensive calculation in val_xxx() + maintain cache of aggregate value. This variable governs the validity of + that cache. + */ + bool is_evaluated; public: - Item_sum_num() :Item_sum() {} - Item_sum_num(Item *item_par) :Item_sum(item_par) {} - Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} - Item_sum_num(List<Item> &list) :Item_sum(list) {} - Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {} + Item_sum_num() :Item_sum(),is_evaluated(FALSE) {} + Item_sum_num(Item *item_par) + :Item_sum(item_par), is_evaluated(FALSE) {} + Item_sum_num(Item *a, Item* b) :Item_sum(a,b),is_evaluated(FALSE) {} + Item_sum_num(List<Item> &list) + :Item_sum(list), is_evaluated(FALSE) {} + Item_sum_num(THD *thd, Item_sum_num *item) + :Item_sum(thd, item),is_evaluated(item->is_evaluated) {} bool fix_fields(THD *, Item **); longlong val_int() { @@ -540,6 +551,12 @@ class Item_sum_count_distinct :public Item_sum_int */ Unique *tree; /* + Storage for the value of count between calls to val_int() so val_int() + will not recalculate on each call. Validitiy of the value is stored in + is_evaluated. + */ + longlong count; + /* Following is 0 normal object and pointer to original one for copy (to correctly free resources) */ @@ -556,14 +573,15 @@ class Item_sum_count_distinct :public Item_sum_int public: Item_sum_count_distinct(List<Item> &list) :Item_sum_int(list), table(0), field_lengths(0), tmp_table_param(0), - force_copy_fields(0), tree(0), original(0), always_null(FALSE) + force_copy_fields(0), tree(0), count(0), + original(0), always_null(FALSE) { quick_group= 0; } Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item) :Item_sum_int(thd, item), table(item->table), field_lengths(item->field_lengths), tmp_table_param(item->tmp_table_param), - force_copy_fields(0), tree(item->tree), original(item), - tree_key_length(item->tree_key_length), + force_copy_fields(0), tree(item->tree), count(item->count), + original(item), tree_key_length(item->tree_key_length), always_null(item->always_null) {} ~Item_sum_count_distinct(); @@ -600,7 +618,7 @@ public: double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *); - bool is_null() { (void) val_int(); return null_value; } + bool is_null() { update_null_value(); return null_value; } String *val_str(String*); enum_field_types field_type() const { @@ -667,7 +685,7 @@ public: { /* 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; } + bool is_null() { update_null_value(); return null_value; } enum_field_types field_type() const { return hybrid_type == DECIMAL_RESULT ? diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index d79dd2a4b44..8504434aed5 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -110,7 +110,6 @@ static bool make_datetime_with_warn(date_time_format_types format, TIME *ltime, String *str) { int warning= 0; - bool rc; if (make_datetime(format, ltime, str)) return 1; @@ -1414,17 +1413,6 @@ String *Item_date::val_str(String *str) } -int Item_date::save_in_field(Field *field, bool no_conversions) -{ - TIME ltime; - if (get_date(<ime, TIME_FUZZY_DATE)) - return set_field_to_null(field); - field->set_notnull(); - field->store_time(<ime, MYSQL_TIMESTAMP_DATE); - return 0; -} - - longlong Item_date::val_int() { DBUG_ASSERT(fixed == 1); @@ -1657,7 +1645,7 @@ double Item_func_sysdate_local::val_real() { DBUG_ASSERT(fixed == 1); store_now_in_TIME(<ime); - return (longlong) TIME_to_ulonglong_datetime(<ime); + return (double) TIME_to_ulonglong_datetime(<ime); } @@ -2499,7 +2487,8 @@ String *Item_char_typecast::val_str(String *str) { // 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); + cast_cs == &my_charset_bin ? "BINARY" : "CHAR", + (ulong) length); if (!res->alloced_length()) { // Don't change const str @@ -3333,7 +3322,9 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date) date_time_format.format.str= (char*) format->ptr(); date_time_format.format.length= format->length(); if (extract_date_time(&date_time_format, val->ptr(), val->length(), - ltime, cached_timestamp_type, 0, "datetime")) + ltime, cached_timestamp_type, 0, "datetime") || + ((fuzzy_date & TIME_NO_ZERO_DATE) && + (ltime->year == 0 || ltime->month == 0 || ltime->day == 0))) goto null_date; if (cached_timestamp_type == MYSQL_TIMESTAMP_TIME && ltime->day) { diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index e79c62e6ffb..68e8700d1b0 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -339,12 +339,20 @@ public: decimals=0; max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; } - int save_in_field(Field *to, bool no_conversions); Field *tmp_table_field(TABLE *t_arg) { return (new Field_date(maybe_null, name, t_arg, &my_charset_bin)); } bool result_as_longlong() { return TRUE; } + my_decimal *val_decimal(my_decimal *decimal_value) + { + DBUG_ASSERT(fixed == 1); + return val_decimal_from_date(decimal_value); + } + int save_in_field(Field *field, bool no_conversions) + { + return save_date_in_field(field); + } }; @@ -361,21 +369,57 @@ public: return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin)); } bool result_as_longlong() { return TRUE; } + my_decimal *val_decimal(my_decimal *decimal_value) + { + DBUG_ASSERT(fixed == 1); + return val_decimal_from_date(decimal_value); + } + int save_in_field(Field *field, bool no_conversions) + { + return save_date_in_field(field); + } +}; + + +class Item_str_timefunc :public Item_str_func +{ +public: + Item_str_timefunc() :Item_str_func() {} + Item_str_timefunc(Item *a) :Item_str_func(a) {} + Item_str_timefunc(Item *a,Item *b) :Item_str_func(a,b) {} + Item_str_timefunc(Item *a, Item *b, Item *c) :Item_str_func(a, b ,c) {} + enum_field_types field_type() const { return MYSQL_TYPE_TIME; } + void fix_length_and_dec() + { + decimals=0; + max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; + } + Field *tmp_table_field(TABLE *t_arg) + { + return (new Field_time(maybe_null, name, t_arg, &my_charset_bin)); + } + my_decimal *val_decimal(my_decimal *decimal_value) + { + DBUG_ASSERT(fixed == 1); + return val_decimal_from_time(decimal_value); + } + int save_in_field(Field *field, bool no_conversions) + { + return save_time_in_field(field); + } }; /* Abstract CURTIME function. Children should define what time zone is used */ -class Item_func_curtime :public Item_func +class Item_func_curtime :public Item_str_timefunc { longlong value; char buff[9*2+32]; uint buff_length; public: - Item_func_curtime() :Item_func() {} - Item_func_curtime(Item *a) :Item_func(a) {} - enum Item_result result_type () const { return STRING_RESULT; } - enum_field_types field_type() const { return MYSQL_TYPE_TIME; } + Item_func_curtime() :Item_str_timefunc() {} + Item_func_curtime(Item *a) :Item_str_timefunc(a) {} double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; } longlong val_int() { DBUG_ASSERT(fixed == 1); return value; } String *val_str(String *str); @@ -602,10 +646,10 @@ class Item_func_convert_tz :public Item_date_func }; -class Item_func_sec_to_time :public Item_str_func +class Item_func_sec_to_time :public Item_str_timefunc { public: - Item_func_sec_to_time(Item *item) :Item_str_func(item) {} + Item_func_sec_to_time(Item *item) :Item_str_timefunc(item) {} double val_real() { DBUG_ASSERT(fixed == 1); @@ -615,17 +659,12 @@ public: String *val_str(String *); void fix_length_and_dec() { + Item_str_timefunc::fix_length_and_dec(); collation.set(&my_charset_bin); maybe_null=1; decimals= DATETIME_DEC; - max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; } - enum_field_types field_type() const { return MYSQL_TYPE_TIME; } const char *func_name() const { return "sec_to_time"; } - Field *tmp_table_field(TABLE *t_arg) - { - return (new Field_time(maybe_null, name, t_arg, &my_charset_bin)); - } bool result_as_longlong() { return TRUE; } }; @@ -762,6 +801,15 @@ public: } bool result_as_longlong() { return TRUE; } longlong val_int(); + my_decimal *val_decimal(my_decimal *decimal_value) + { + DBUG_ASSERT(fixed == 1); + return val_decimal_from_date(decimal_value); + } + int save_in_field(Field *field, bool no_conversions) + { + return save_date_in_field(field); + } }; @@ -780,6 +828,15 @@ public: } bool result_as_longlong() { return TRUE; } longlong val_int(); + my_decimal *val_decimal(my_decimal *decimal_value) + { + DBUG_ASSERT(fixed == 1); + return val_decimal_from_time(decimal_value); + } + int save_in_field(Field *field, bool no_conversions) + { + return save_time_in_field(field); + } }; @@ -797,12 +854,21 @@ public: } bool result_as_longlong() { return TRUE; } longlong val_int(); + my_decimal *val_decimal(my_decimal *decimal_value) + { + DBUG_ASSERT(fixed == 1); + return val_decimal_from_date(decimal_value); + } + int save_in_field(Field *field, bool no_conversions) + { + return save_date_in_field(field); + } }; -class Item_func_makedate :public Item_str_func +class Item_func_makedate :public Item_date_func { public: - Item_func_makedate(Item *a,Item *b) :Item_str_func(a,b) {} + Item_func_makedate(Item *a,Item *b) :Item_date_func(a,b) {} String *val_str(String *str); const char *func_name() const { return "makedate"; } enum_field_types field_type() const { return MYSQL_TYPE_DATE; } @@ -815,8 +881,16 @@ public: { return (new Field_date(maybe_null, name, t_arg, &my_charset_bin)); } - bool result_as_longlong() { return TRUE; } longlong val_int(); + my_decimal *val_decimal(my_decimal *decimal_value) + { + DBUG_ASSERT(fixed == 1); + return val_decimal_from_date(decimal_value); + } + int save_in_field(Field *field, bool no_conversions) + { + return save_date_in_field(field); + } }; @@ -848,45 +922,46 @@ public: } void print(String *str); const char *func_name() const { return "add_time"; } + my_decimal *val_decimal(my_decimal *decimal_value) + { + DBUG_ASSERT(fixed == 1); + if (cached_field_type == MYSQL_TYPE_TIME) + return val_decimal_from_time(decimal_value); + if (cached_field_type == MYSQL_TYPE_DATETIME) + return val_decimal_from_date(decimal_value); + return Item_str_func::val_decimal(decimal_value); + } + int save_in_field(Field *field, bool no_conversions) + { + if (cached_field_type == MYSQL_TYPE_TIME) + return save_time_in_field(field); + if (cached_field_type == MYSQL_TYPE_DATETIME) + return save_date_in_field(field); + return Item_str_func::save_in_field(field, no_conversions); + } }; -class Item_func_timediff :public Item_str_func +class Item_func_timediff :public Item_str_timefunc { public: Item_func_timediff(Item *a, Item *b) - :Item_str_func(a, b) {} + :Item_str_timefunc(a, b) {} String *val_str(String *str); const char *func_name() const { return "timediff"; } - enum_field_types field_type() const { return MYSQL_TYPE_TIME; } void fix_length_and_dec() { - decimals=0; - max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; + Item_str_timefunc::fix_length_and_dec(); maybe_null= 1; } - Field *tmp_table_field(TABLE *t_arg) - { - return (new Field_time(maybe_null, name, t_arg, &my_charset_bin)); - } }; -class Item_func_maketime :public Item_str_func +class Item_func_maketime :public Item_str_timefunc { public: Item_func_maketime(Item *a, Item *b, Item *c) - :Item_str_func(a, b ,c) {} + :Item_str_timefunc(a, b ,c) {} String *val_str(String *str); const char *func_name() const { return "maketime"; } - enum_field_types field_type() const { return MYSQL_TYPE_TIME; } - void fix_length_and_dec() - { - decimals=0; - max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; - } - Field *tmp_table_field(TABLE *t_arg) - { - return (new Field_time(maybe_null, name, t_arg, &my_charset_bin)); - } }; class Item_func_microsecond :public Item_int_func diff --git a/sql/log.cc b/sql/log.cc index 960fc4f60c2..71bdecdc536 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1676,14 +1676,14 @@ bool MYSQL_LOG::write(Log_event *event_info) } trans_log->end_of_file= max_binlog_cache_size; trans_register_ha(thd, - thd->options & (OPTION_NOT_AUTOCOMMIT | - OPTION_BEGIN), + test(thd->options & (OPTION_NOT_AUTOCOMMIT | + OPTION_BEGIN)), &binlog_hton); } else if (!my_b_tell(trans_log)) trans_register_ha(thd, - thd->options & (OPTION_NOT_AUTOCOMMIT | - OPTION_BEGIN), + test(thd->options & (OPTION_NOT_AUTOCOMMIT | + OPTION_BEGIN)), &binlog_hton); file= trans_log; } diff --git a/sql/log_event.cc b/sql/log_event.cc index 271658d8054..0d7ef7e8f2a 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -727,7 +727,7 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, LOG_EVENT_MINIMAL_HEADER_LEN); LOCK_MUTEX; - DBUG_PRINT("info", ("my_b_tell=%lu", my_b_tell(file))); + DBUG_PRINT("info", ("my_b_tell: %lu", (ulong) my_b_tell(file))); if (my_b_read(file, (byte *) head, header_size)) { DBUG_PRINT("info", ("Log_event::read_log_event(IO_CACHE*,Format_desc*) \ @@ -1212,6 +1212,7 @@ bool Query_log_event::write(IO_CACHE* file) /* Store length of status variables */ status_vars_len= (uint) (start-start_of_status); + DBUG_ASSERT(status_vars_len <= MAX_SIZE_LOG_EVENT_STATUS); int2store(buf + Q_STATUS_VARS_LEN_OFFSET, status_vars_len); /* @@ -1297,7 +1298,8 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, } else time_zone_len= 0; - DBUG_PRINT("info",("Query_log_event has flags2=%lu sql_mode=%lu",flags2,sql_mode)); + DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %lu", + (ulong) flags2, sql_mode)); } #endif /* MYSQL_CLIENT */ @@ -1345,7 +1347,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, common_header_len= description_event->common_header_len; post_header_len= description_event->post_header_len[event_type-1]; - DBUG_PRINT("info",("event_len=%ld, common_header_len=%d, post_header_len=%d", + DBUG_PRINT("info",("event_len: %u common_header_len: %d post_header_len: %d", event_len, common_header_len, post_header_len)); /* @@ -1393,7 +1395,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, case Q_FLAGS2_CODE: flags2_inited= 1; flags2= uint4korr(pos); - DBUG_PRINT("info",("In Query_log_event, read flags2: %lu", flags2)); + DBUG_PRINT("info",("In Query_log_event, read flags2: %lu", (ulong) flags2)); pos+= 4; break; case Q_SQL_MODE_CODE: @@ -3137,8 +3139,8 @@ Rotate_log_event::Rotate_log_event(THD* thd_arg, #ifndef DBUG_OFF char buff[22]; DBUG_ENTER("Rotate_log_event::Rotate_log_event(THD*,...)"); - DBUG_PRINT("enter",("new_log_ident %s pos %s flags %lu", new_log_ident_arg, - llstr(pos_arg, buff), flags)); + DBUG_PRINT("enter",("new_log_ident: %s pos: %s flags: %lu", new_log_ident_arg, + llstr(pos_arg, buff), (ulong) flags)); #endif if (flags & DUP_NAME) new_log_ident= my_strdup_with_length(new_log_ident_arg, @@ -3912,7 +3914,7 @@ Slave_log_event::Slave_log_event(THD* thd_arg, memcpy(master_log, rli->group_master_log_name, master_log_len + 1); master_port = mi->port; master_pos = rli->group_master_log_pos; - DBUG_PRINT("info", ("master_log: %s pos: %d", master_log, + DBUG_PRINT("info", ("master_log: %s pos: %lu", master_log, (ulong) master_pos)); } else diff --git a/sql/log_event.h b/sql/log_event.h index f1b441dedb1..247e1962776 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -200,8 +200,26 @@ struct sql_ex_info #define EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN (4 + 4 + 4 + 1) #define EXECUTE_LOAD_QUERY_HEADER_LEN (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN) -/* - Event header offsets; +/* + Max number of possible extra bytes in a replication event compared to a + packet (i.e. a query) sent from client to master; + First, an auxiliary log_event status vars estimation: +*/ +#define MAX_SIZE_LOG_EVENT_STATUS (4 /* flags2 */ + \ + 8 /* sql mode */ + \ + 1 + 1 + 255 /* catalog */ + \ + 4 /* autoinc */ + \ + 6 /* charset */ + \ + MAX_TIME_ZONE_NAME_LENGTH) +#define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \ + LOG_EVENT_HEADER_LEN + /* write_header */ \ + QUERY_HEADER_LEN + /* write_data */ \ + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN + /*write_post_header_for_derived */ \ + MAX_SIZE_LOG_EVENT_STATUS + /* status */ \ + NAME_LEN + 1) + +/* + Event header offsets; these point to places inside the fixed header. */ diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index 1bd16940b47..f33609e0168 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -15,6 +15,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mysql_priv.h" +#include <time.h> + #ifndef MYSQL_CLIENT /* @@ -190,6 +192,23 @@ int str2my_decimal(uint mask, const char *from, uint length, } +my_decimal *date2my_decimal(TIME *ltime, my_decimal *dec) +{ + longlong date; + date = (ltime->year*100L + ltime->month)*100L + ltime->day; + if (ltime->time_type > MYSQL_TIMESTAMP_DATE) + date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second; + if (int2my_decimal(E_DEC_FATAL_ERROR, date, FALSE, dec)) + return dec; + if (ltime->second_part) + { + dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000; + dec->frac= 6; + } + return dec; +} + + #ifndef DBUG_OFF /* routines for debugging print */ diff --git a/sql/my_decimal.h b/sql/my_decimal.h index b02abacf0a3..af3edade8d6 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -295,7 +295,12 @@ int string2my_decimal(uint mask, const String *str, my_decimal *d) { return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d); } -#endif + + +my_decimal *date2my_decimal(TIME *ltime, my_decimal *dec); + + +#endif /*defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) */ inline int double2my_decimal(uint mask, double val, my_decimal *d) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index cd6c2a73ccc..55b182049b6 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -96,6 +96,17 @@ extern CHARSET_INFO *system_charset_info, *files_charset_info ; extern CHARSET_INFO *national_charset_info, *table_alias_charset; +enum Derivation +{ + DERIVATION_IGNORABLE= 5, + DERIVATION_COERCIBLE= 4, + DERIVATION_SYSCONST= 3, + DERIVATION_IMPLICIT= 2, + DERIVATION_NONE= 1, + DERIVATION_EXPLICIT= 0 +}; + + typedef struct my_locale_st { const char *name; @@ -734,7 +745,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, bool mysql_select(THD *thd, Item ***rref_pointer_array, TABLE_LIST *tables, uint wild_num, List<Item> &list, COND *conds, uint og_num, ORDER *order, ORDER *group, - Item *having, ORDER *proc_param, ulong select_type, + Item *having, ORDER *proc_param, ulonglong select_type, select_result *result, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex); void free_underlaid_joins(THD *thd, SELECT_LEX *select); @@ -941,6 +952,7 @@ 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, bool is_locked); +void mysql_ha_mark_tables_for_reopen(THD *thd, TABLE *table); /* mysql_ha_flush mode_flags bits */ #define MYSQL_HA_CLOSE_FINAL 0x00 #define MYSQL_HA_REOPEN_ON_USAGE 0x01 @@ -1471,7 +1483,7 @@ void end_read_record(READ_RECORD *info); ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder, uint s_length, SQL_SELECT *select, ha_rows max_rows, ha_rows *examined_rows); -void filesort_free_buffers(TABLE *table); +void filesort_free_buffers(TABLE *table, bool full); void change_double_for_sort(double nr,byte *to); double my_double_round(double value, int dec, bool truncate); int get_quick_record(SQL_SELECT *select); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 26a335842e3..9411ba2ef12 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -70,6 +70,12 @@ #define IF_PURIFY(A,B) (B) #endif +#if SIZEOF_CHARP == 4 +#define MAX_MEM_TABLE_SIZE ~(ulong) 0 +#else +#define MAX_MEM_TABLE_SIZE ~(ulonglong) 0 +#endif + /* stack traces are only supported on linux intel */ #if defined(__linux__) && defined(__i386__) && defined(USE_PSTACK) #define HAVE_STACK_TRACE_ON_SEGV @@ -1531,8 +1537,8 @@ static void network_init(void) if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1)) { - sql_print_error("The socket file path is too long (> %lu): %s", - sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); + sql_print_error("The socket file path is too long (> %u): %s", + (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); unireg_abort(1); } if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0) @@ -3389,8 +3395,8 @@ int main(int argc, char **argv) if (stack_size && stack_size < thread_stack) { if (global_system_variables.log_warnings) - sql_print_warning("Asked for %ld thread stack, but got %ld", - thread_stack, stack_size); + sql_print_warning("Asked for %lu thread stack, but got %ld", + thread_stack, (long) stack_size); #if defined(__ia64__) || defined(__ia64) thread_stack= stack_size*2; #else @@ -3924,7 +3930,7 @@ static void create_new_thread(THD *thd) int error; thread_created++; threads.append(thd); - DBUG_PRINT("info",(("creating thread %d"), thd->thread_id)); + DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id)); thd->connect_time = time(NULL); if ((error=pthread_create(&thd->real_id,&connection_attrib, handle_one_connection, @@ -5141,7 +5147,7 @@ master-ssl", (gptr*) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"merge", OPT_MERGE, "Enable Merge storage engine. Disable with \ --skip-merge.", - (gptr*) &opt_merge, (gptr*) &opt_merge, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0}, + (gptr*) &opt_merge, (gptr*) &opt_merge, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"myisam-recover", OPT_MYISAM_RECOVER, "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.", (gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0, @@ -5729,8 +5735,9 @@ The minimum value for this variable is 4096.", {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE, "Don't allow creation of heap tables bigger than this.", (gptr*) &global_system_variables.max_heap_table_size, - (gptr*) &max_system_variables.max_heap_table_size, 0, GET_ULONG, - REQUIRED_ARG, 16*1024*1024L, 16384, ~0L, MALLOC_OVERHEAD, 1024, 0}, + (gptr*) &max_system_variables.max_heap_table_size, 0, GET_ULL, + REQUIRED_ARG, 16*1024*1024L, 16384, MAX_MEM_TABLE_SIZE, + MALLOC_OVERHEAD, 1024, 0}, {"max_join_size", OPT_MAX_JOIN_SIZE, "Joins that are probably going to read more than max_join_size records return an error.", (gptr*) &global_system_variables.max_join_size, @@ -6005,8 +6012,8 @@ The minimum value for this variable is 4096.", {"tmp_table_size", OPT_TMP_TABLE_SIZE, "If an in-memory temporary table exceeds this size, MySQL will automatically convert it to an on-disk MyISAM table.", (gptr*) &global_system_variables.tmp_table_size, - (gptr*) &max_system_variables.tmp_table_size, 0, GET_ULONG, - REQUIRED_ARG, 32*1024*1024L, 1024, ~0L, 0, 1, 0}, + (gptr*) &max_system_variables.tmp_table_size, 0, GET_ULL, + REQUIRED_ARG, 32*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0}, {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE, "Allocation block size for transactions to be stored in binary log", (gptr*) &global_system_variables.trans_alloc_block_size, @@ -6189,6 +6196,7 @@ struct show_var_st status_vars[]= { {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_CONST}, {"Open_tables", (char*) 0, SHOW_OPENTABLES}, {"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS}, + {"Prepared_stmt_count", (char*) &prepared_stmt_count, SHOW_LONG_CONST}, #ifdef HAVE_QUERY_CACHE {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_CONST}, {"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_CONST}, @@ -6358,6 +6366,7 @@ static void mysql_init_variables(void) binlog_cache_use= binlog_cache_disk_use= 0; max_used_connections= slow_launch_threads = 0; mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0; + prepared_stmt_count= 0; errmesg= 0; mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS; bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list)); diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 1601f7e5177..3037007ae35 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -597,7 +597,10 @@ net_real_write(NET *net,const char *packet,ulong len) } #endif /* HAVE_COMPRESS */ - /* DBUG_DUMP("net",packet,len); */ +#ifdef DEBUG_DATA_PACKETS + DBUG_DUMP("data",packet,len); +#endif + #ifndef NO_ALARM thr_alarm_init(&alarmed); if (net_blocking) @@ -810,7 +813,7 @@ my_real_read(NET *net, ulong *complen) { my_bool interrupted = vio_should_retry(net->vio); - DBUG_PRINT("info",("vio_read returned %d, errno: %d", + DBUG_PRINT("info",("vio_read returned %ld, errno: %d", length, vio_errno(net->vio))); #if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2)) || defined(MYSQL_SERVER) /* diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 96239315026..f062e0d2a0d 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -878,7 +878,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT() file->extra(HA_EXTRA_NO_KEYREAD); if (free_file) { - DBUG_PRINT("info", ("Freeing separate handler %p (free=%d)", file, + DBUG_PRINT("info", ("Freeing separate handler 0x%lx (free: %d)", (long) file, free_file)); file->reset(); file->external_lock(current_thd, F_UNLCK); @@ -1836,9 +1836,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, double scan_time; DBUG_ENTER("SQL_SELECT::test_quick_select"); DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu", - keys_to_use.to_ulonglong(), (ulong) prev_tables, + (ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables, (ulong) const_tables)); - DBUG_PRINT("info", ("records=%lu", (ulong)head->file->records)); + DBUG_PRINT("info", ("records: %lu", (ulong) head->file->records)); delete quick; quick=0; needed_reg.clear_all(); @@ -1924,7 +1924,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, key_parts->null_bit= key_part_info->null_bit; key_parts->image_type = (key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW; - key_parts->flag= key_part_info->key_part_flag; + key_parts->flag= (uint8) key_part_info->key_part_flag; } param.real_keynr[param.keys++]=idx; } @@ -2102,7 +2102,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records) n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(records))); if (busy_blocks < 1.0) busy_blocks= 1.0; - DBUG_PRINT("info",("sweep: nblocks=%g, busy_blocks=%g", n_blocks, + DBUG_PRINT("info",("sweep: nblocks: %g, busy_blocks: %g", n_blocks, busy_blocks)); /* Disabled: Bail out if # of blocks to read is bigger than # of blocks in @@ -2126,7 +2126,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records) result= busy_blocks; } } - DBUG_PRINT("info",("returning cost=%g", result)); + DBUG_PRINT("return",("cost: %g", result)); DBUG_RETURN(result); } @@ -2220,7 +2220,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, ha_rows roru_total_records; double roru_intersect_part= 1.0; DBUG_ENTER("get_best_disjunct_quick"); - DBUG_PRINT("info", ("Full table scan cost =%g", read_time)); + DBUG_PRINT("info", ("Full table scan cost: %g", read_time)); if (!(range_scans= (TRP_RANGE**)alloc_root(param->mem_root, sizeof(TRP_RANGE*)* @@ -2264,7 +2264,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, non_cpk_scan_records += (*cur_child)->records; } - DBUG_PRINT("info", ("index_merge scans cost=%g", imerge_cost)); + DBUG_PRINT("info", ("index_merge scans cost %g", imerge_cost)); if (imerge_too_expensive || (imerge_cost > read_time) || (non_cpk_scan_records+cpk_scan_records >= param->table->file->records) && read_time != DBL_MAX) @@ -2877,7 +2877,7 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info, DBUG_PRINT("info", ("Current out_rows= %g", info->out_rows)); DBUG_PRINT("info", ("Adding scan on %s", info->param->table->key_info[ror_scan->keynr].name)); - DBUG_PRINT("info", ("is_cpk_scan=%d",is_cpk_scan)); + DBUG_PRINT("info", ("is_cpk_scan: %d",is_cpk_scan)); selectivity_mult = ror_scan_selectivity(info, ror_scan); if (selectivity_mult == 1.0) @@ -3703,7 +3703,8 @@ static SEL_TREE *get_func_mm_tree(PARAM *param, Item_func *cond_func, for (uint idx= 0; idx < param->keys; idx++) { SEL_ARG *new_interval, *last_val; - if (((new_interval= tree2->keys[idx])) && + if (((new_interval= tree2->keys[idx])) && + (tree->keys[idx]) && ((last_val= tree->keys[idx]->last()))) { new_interval->min_value= last_val->max_value; @@ -6240,7 +6241,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, key_part->length= key_info->key_part[part].length; key_part->store_length= key_info->key_part[part].store_length; key_part->null_bit= key_info->key_part[part].null_bit; - key_part->flag= key_info->key_part[part].key_part_flag; + key_part->flag= (uint8) key_info->key_part[part].key_part_flag; } if (insert_dynamic(&quick->ranges,(gptr)&range)) goto err; @@ -7445,7 +7446,7 @@ static TRP_GROUP_MIN_MAX * get_best_group_min_max(PARAM *param, SEL_TREE *tree) { THD *thd= param->thd; - JOIN *join= thd->lex->select_lex.join; + JOIN *join= thd->lex->current_select->join; TABLE *table= param->table; bool have_min= FALSE; /* TRUE if there is a MIN function. */ bool have_max= FALSE; /* TRUE if there is a MAX function. */ @@ -7466,7 +7467,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) DBUG_ENTER("get_best_group_min_max"); /* Perform few 'cheap' tests whether this access method is applicable. */ - if (!join || (thd->lex->sql_command != SQLCOM_SELECT)) + if (!join) DBUG_RETURN(NULL); /* This is not a select statement. */ if ((join->tables != 1) || /* The query must reference one table. */ ((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */ @@ -8280,8 +8281,8 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, *records= num_groups; DBUG_PRINT("info", - ("table rows=%u, keys/block=%u, keys/group=%u, result rows=%u, blocks=%u", - table_records, keys_per_block, keys_per_group, *records, + ("table rows: %u keys/block: %u keys/group: %u result rows: %lu blocks: %u", + table_records, keys_per_block, keys_per_group, (ulong) *records, num_blocks)); DBUG_VOID_RETURN; } @@ -8316,7 +8317,7 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows, DBUG_ENTER("TRP_GROUP_MIN_MAX::make_quick"); quick= new QUICK_GROUP_MIN_MAX_SELECT(param->table, - param->thd->lex->select_lex.join, + param->thd->lex->current_select->join, have_min, have_max, min_max_arg_part, group_prefix_len, used_key_parts, index_info, index, read_cost, records, diff --git a/sql/password.c b/sql/password.c index 506e1aa36a2..594096b6ec9 100644 --- a/sql/password.c +++ b/sql/password.c @@ -406,7 +406,7 @@ make_scrambled_password(char *to, const char *password) mysql_sha1_result(&sha1_context, hash_stage2); /* convert hash_stage2 to hex string */ *to++= PVERSION41_CHAR; - octet2hex(to, hash_stage2, SHA1_HASH_SIZE); + octet2hex(to, (char*) hash_stage2, SHA1_HASH_SIZE); } @@ -520,5 +520,5 @@ void get_salt_from_password(uint8 *hash_stage2, const char *password) void make_password_from_salt(char *to, const uint8 *hash_stage2) { *to++= PVERSION41_CHAR; - octet2hex(to, hash_stage2, SHA1_HASH_SIZE); + octet2hex(to, (char*) hash_stage2, SHA1_HASH_SIZE); } diff --git a/sql/protocol.cc b/sql/protocol.cc index 5de24ebdcb3..e7a8d493341 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -46,7 +46,7 @@ bool Protocol_prep::net_store_data(const char *from, uint length) packet->realloc(packet_length+9+length)) return 1; char *to=(char*) net_store_length((char*) packet->ptr()+packet_length, - (ulonglong) length); + length); memcpy(to,from,length); packet->length((uint) (to+length-packet->ptr())); return 0; @@ -280,8 +280,8 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) } buff[0]=0; // No fields - pos=net_store_length(buff+1,(ulonglong) affected_rows); - pos=net_store_length(pos, (ulonglong) id); + pos=net_store_length(buff+1,affected_rows); + pos=net_store_length(pos, id); if (thd->client_capabilities & CLIENT_PROTOCOL_41) { DBUG_PRINT("info", @@ -456,7 +456,7 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err) ulonglong for bigger numbers. */ -char *net_store_length(char *pkg, uint length) +static char *net_store_length_fast(char *pkg, uint length) { uchar *packet=(uchar*) pkg; if (length < 251) @@ -479,7 +479,7 @@ char *net_store_length(char *pkg, uint length) char *net_store_data(char *to,const char *from, uint length) { - to=net_store_length(to,length); + to=net_store_length_fast(to,length); memcpy(to,from,length); return to+length; } @@ -488,7 +488,7 @@ char *net_store_data(char *to,int32 from) { char buff[20]; uint length=(uint) (int10_to_str(from,buff,10)-buff); - to=net_store_length(to,length); + to=net_store_length_fast(to,length); memcpy(to,buff,length); return to+length; } @@ -497,7 +497,7 @@ char *net_store_data(char *to,longlong from) { char buff[22]; uint length=(uint) (longlong10_to_str(from,buff,10)-buff); - to=net_store_length(to,length); + to=net_store_length_fast(to,length); memcpy(to,buff,length); return to+length; } @@ -561,7 +561,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags) if (flags & SEND_NUM_ROWS) { // Packet with number of elements - char *pos=net_store_length(buff, (uint) list->elements); + char *pos=net_store_length(buff, list->elements); (void) my_net_write(&thd->net, buff,(uint) (pos-buff)); } diff --git a/sql/protocol.h b/sql/protocol.h index 85c22724b74..7e2bc1516ec 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -166,7 +166,6 @@ void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L, const char *info=0); void send_eof(THD *thd); bool send_old_password_request(THD *thd); -char *net_store_length(char *packet,uint length); char *net_store_data(char *to,const char *from, uint length); char *net_store_data(char *to,int32 from); char *net_store_data(char *to,longlong from); diff --git a/sql/records.cc b/sql/records.cc index b352f9f395a..78473659b22 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -20,7 +20,7 @@ #include "mysql_priv.h" static int rr_quick(READ_RECORD *info); -static int rr_sequential(READ_RECORD *info); +int rr_sequential(READ_RECORD *info); static int rr_from_tempfile(READ_RECORD *info); static int rr_unpack_from_tempfile(READ_RECORD *info); static int rr_unpack_from_buffer(READ_RECORD *info); @@ -184,6 +184,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, } /* init_read_record */ + void end_read_record(READ_RECORD *info) { /* free cache if used */ if (info->cache) @@ -193,7 +194,7 @@ void end_read_record(READ_RECORD *info) } if (info->table) { - filesort_free_buffers(info->table); + filesort_free_buffers(info->table,0); (void) info->file->extra(HA_EXTRA_NO_CACHE); if (info->read_record != rr_quick) // otherwise quick_range does it (void) info->file->ha_index_or_rnd_end(); @@ -289,7 +290,7 @@ static int rr_index(READ_RECORD *info) } -static int rr_sequential(READ_RECORD *info) +int rr_sequential(READ_RECORD *info) { int tmp; while ((tmp=info->file->rnd_next(info->record))) diff --git a/sql/set_var.cc b/sql/set_var.cc index 55c62a9a5a5..23afef742a6 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -121,7 +121,6 @@ static KEY_CACHE *create_key_cache(const char *name, uint length); void fix_sql_mode_var(THD *thd, enum_var_type type); static byte *get_error_count(THD *thd); static byte *get_warning_count(THD *thd); -static byte *get_prepared_stmt_count(THD *thd); static byte *get_have_innodb(THD *thd); static byte *get_tmpdir(THD *thd); @@ -248,7 +247,7 @@ sys_var_thd_ulong sys_max_delayed_threads("max_delayed_threads", fix_max_connections); sys_var_thd_ulong sys_max_error_count("max_error_count", &SV::max_error_count); -sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size", +sys_var_thd_ulonglong sys_max_heap_table_size("max_heap_table_size", &SV::max_heap_table_size); sys_var_thd_ulong sys_pseudo_thread_id("pseudo_thread_id", &SV::pseudo_thread_id, @@ -415,7 +414,7 @@ sys_var_thd_enum sys_tx_isolation("tx_isolation", &SV::tx_isolation, &tx_isolation_typelib, fix_tx_isolation); -sys_var_thd_ulong sys_tmp_table_size("tmp_table_size", +sys_var_thd_ulonglong sys_tmp_table_size("tmp_table_size", &SV::tmp_table_size); sys_var_bool_ptr sys_timed_mutexes("timed_mutexes", &timed_mutexes); @@ -567,9 +566,6 @@ static sys_var_readonly sys_warning_count("warning_count", OPT_SESSION, SHOW_LONG, get_warning_count); -static sys_var_readonly sys_prepared_stmt_count("prepared_stmt_count", - OPT_GLOBAL, SHOW_LONG, - get_prepared_stmt_count); /* alias for last_insert_id() to be compatible with Sybase */ #ifdef HAVE_REPLICATION @@ -701,7 +697,6 @@ sys_var *sys_variables[]= &sys_optimizer_prune_level, &sys_optimizer_search_depth, &sys_preload_buff_size, - &sys_prepared_stmt_count, &sys_pseudo_thread_id, &sys_query_alloc_block_size, &sys_query_cache_size, @@ -1008,7 +1003,6 @@ struct show_var_st init_vars[]= { {"pid_file", (char*) pidfile_name, SHOW_CHAR}, {"port", (char*) &mysqld_port, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, - {sys_prepared_stmt_count.name, (char*) &sys_prepared_stmt_count, SHOW_SYS}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size, SHOW_SYS}, @@ -2836,7 +2830,7 @@ static bool set_option_autocommit(THD *thd, set_var *var) { /* The test is negative as the flag we use is NOT autocommit */ - ulong org_options=thd->options; + ulonglong org_options= thd->options; if (var->save_result.ulong_value != 0) thd->options&= ~((sys_var_thd_bit*) var->var)->bit_flag; @@ -2946,15 +2940,6 @@ static byte *get_have_innodb(THD *thd) } -static byte *get_prepared_stmt_count(THD *thd) -{ - pthread_mutex_lock(&LOCK_prepared_stmt_count); - thd->sys_var_tmp.ulong_value= prepared_stmt_count; - pthread_mutex_unlock(&LOCK_prepared_stmt_count); - return (byte*) &thd->sys_var_tmp.ulong_value; -} - - /* Get the tmpdir that was specified or chosen by default diff --git a/sql/slave.cc b/sql/slave.cc index e3497a4f0ac..d0396444ace 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -247,7 +247,7 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log, bool look_for_description_event) { DBUG_ENTER("init_relay_log_pos"); - DBUG_PRINT("info", ("pos=%lu", pos)); + DBUG_PRINT("info", ("pos: %lu", (long) pos)); *errmsg=0; pthread_mutex_t *log_lock=rli->relay_log.get_log_lock(); @@ -1513,7 +1513,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, TABLE_LIST tables; int error= 1; handler *file; - ulong save_options; + ulonglong save_options; NET *net= &mysql->net; DBUG_ENTER("create_table_from_dump"); @@ -2895,6 +2895,13 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; thd->security_ctx->skip_grants(); my_net_init(&thd->net, 0); +/* + Adding MAX_LOG_EVENT_HEADER_LEN to the max_allowed_packet on all + slave threads, since a replication event can become this much larger + than the corresponding packet (query) sent from client to master. +*/ + thd->variables.max_allowed_packet= global_system_variables.max_allowed_packet + + MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */ thd->net.read_timeout = slave_net_timeout; thd->slave_thread = 1; set_slave_thread_options(thd); @@ -3080,7 +3087,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) return packet_error; } - DBUG_PRINT("info",( "len=%u, net->read_pos[4] = %d\n", + DBUG_PRINT("info",( "len: %lu net->read_pos[4]: %d\n", len, mysql->net.read_pos[4])); return len - 1; } @@ -3347,9 +3354,9 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) const char *errmsg; /* We were in a transaction which has been rolled back because of a - deadlock (currently, InnoDB deadlock detected by InnoDB) or lock - wait timeout (innodb_lock_wait_timeout exceeded); let's seek back to - BEGIN log event and retry it all again. + Sonera deadlock. if lock wait timeout (innodb_lock_wait_timeout exceeded) + there is no rollback since 5.0.13 (ref: manual). + let's seek back to BEGIN log event and retry it all again. We have to not only seek but also a) init_master_info(), to seek back to hot relay log's start for later (for when we will come back to this hot log after re-processing the @@ -3371,6 +3378,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) else { exec_res= 0; + end_trans(thd, ROLLBACK); /* chance for concurrent connection to get more locks */ safe_sleep(thd, min(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE), (CHECK_KILLED_FUNC)sql_slave_killed, (void*)rli); @@ -3388,9 +3396,17 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) "the slave_transaction_retries variable.", slave_trans_retries); } - if (!((thd->options & OPTION_BEGIN) && opt_using_transactions)) - rli->trans_retries= 0; // restart from fresh - } + else if (!((thd->options & OPTION_BEGIN) && opt_using_transactions)) + { + /* + Only reset the retry counter if the event succeeded or + failed with a non-transient error. On a successful event, + the execution will proceed as usual; in the case of a + non-transient error, the slave will stop with an error. + */ + rli->trans_retries= 0; // restart from fresh + } + } return exec_res; } else @@ -3474,11 +3490,19 @@ slave_begin: thd->proc_info = "Connecting to master"; // we can get killed during safe_connect if (!safe_connect(thd, mysql, mi)) + { sql_print_information("Slave I/O thread: connected to master '%s@%s:%d',\ replication started in log '%s' at position %s", mi->user, - mi->host, mi->port, - IO_RPL_LOG_NAME, - llstr(mi->master_log_pos,llbuff)); + mi->host, mi->port, + IO_RPL_LOG_NAME, + llstr(mi->master_log_pos,llbuff)); + /* + Adding MAX_LOG_EVENT_HEADER_LEN to the max_packet_size on the I/O + thread, since a replication event can become this much larger than + the corresponding packet (query) sent from client to master. + */ + mysql->net.max_packet_size= thd->net.max_packet_size+= MAX_LOG_EVENT_HEADER; + } else { sql_print_information("Slave I/O thread killed while connecting to master"); @@ -4116,7 +4140,7 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev) /* Safe copy as 'rev' has been "sanitized" in Rotate_log_event's ctor */ memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1); mi->master_log_pos= rev->pos; - DBUG_PRINT("info", ("master_log_pos: '%s' %d", + DBUG_PRINT("info", ("master_log_pos: '%s' %lu", mi->master_log_name, (ulong) mi->master_log_pos)); #ifndef DBUG_OFF /* @@ -4233,7 +4257,7 @@ static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf, int error = process_io_create_file(mi,(Create_file_log_event*)ev); delete ev; mi->master_log_pos += inc_pos; - DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos)); + DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); pthread_mutex_unlock(&mi->data_lock); my_free((char*)tmp_buf, MYF(0)); DBUG_RETURN(error); @@ -4260,7 +4284,7 @@ static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf, } delete ev; mi->master_log_pos+= inc_pos; - DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos)); + DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); pthread_mutex_unlock(&mi->data_lock); DBUG_RETURN(0); } @@ -4316,7 +4340,7 @@ static int queue_binlog_ver_3_event(MASTER_INFO *mi, const char *buf, delete ev; mi->master_log_pos+= inc_pos; err: - DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos)); + DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); pthread_mutex_unlock(&mi->data_lock); DBUG_RETURN(0); } @@ -4486,7 +4510,8 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len) rli->ign_master_log_pos_end= mi->master_log_pos; } rli->relay_log.signal_update(); // the slave SQL thread needs to re-check - DBUG_PRINT("info", ("master_log_pos: %d, event originating from the same server, ignored", (ulong) mi->master_log_pos)); + DBUG_PRINT("info", ("master_log_pos: %lu event originating from the same server, ignored", + (ulong) mi->master_log_pos)); } else { @@ -4494,7 +4519,7 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len) if (likely(!(rli->relay_log.appendv(buf,event_len,0)))) { mi->master_log_pos+= inc_pos; - DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos)); + DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); rli->relay_log.harvest_bytes_written(&rli->log_space_total); } else diff --git a/sql/sp.cc b/sql/sp.cc index 283f43f55b2..188db4546c9 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -494,17 +494,10 @@ db_create_routine(THD *thd, int type, sp_head *sp) char definer[USER_HOST_BUFF_SIZE]; char old_db_buf[NAME_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; - bool dbchanged; DBUG_ENTER("db_create_routine"); DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length, sp->m_name.str)); - if ((ret= sp_use_new_db(thd, sp->m_db, &old_db, 0, &dbchanged))) - { - ret= SP_NO_DB_ERROR; - goto done; - } - if (!(table= open_proc_table_for_update(thd))) ret= SP_OPEN_TABLE_FAILED; else @@ -539,17 +532,17 @@ db_create_routine(THD *thd, int type, sp_head *sp) table->field[MYSQL_PROC_FIELD_NAME]-> store(sp->m_name.str, sp->m_name.length, system_charset_info); table->field[MYSQL_PROC_FIELD_TYPE]-> - store((longlong)type); + store((longlong)type, 1); table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]-> store(sp->m_name.str, sp->m_name.length, system_charset_info); if (sp->m_chistics->daccess != SP_DEFAULT_ACCESS) table->field[MYSQL_PROC_FIELD_ACCESS]-> - store((longlong)sp->m_chistics->daccess); + store((longlong)sp->m_chistics->daccess, 1); table->field[MYSQL_PROC_FIELD_DETERMINISTIC]-> - store((longlong)(sp->m_chistics->detistic ? 1 : 2)); + store((longlong)(sp->m_chistics->detistic ? 1 : 2), 1); if (sp->m_chistics->suid != SP_IS_DEFAULT_SUID) table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]-> - store((longlong)sp->m_chistics->suid); + store((longlong)sp->m_chistics->suid, 1); table->field[MYSQL_PROC_FIELD_PARAM_LIST]-> store(sp->m_params.str, sp->m_params.length, system_charset_info); if (sp->m_type == TYPE_ENUM_FUNCTION) @@ -566,7 +559,7 @@ db_create_routine(THD *thd, int type, sp_head *sp) ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time(); ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time(); table->field[MYSQL_PROC_FIELD_SQL_MODE]-> - store((longlong)thd->variables.sql_mode); + store((longlong)thd->variables.sql_mode, 1); if (sp->m_chistics->comment.str) table->field[MYSQL_PROC_FIELD_COMMENT]-> store(sp->m_chistics->comment.str, sp->m_chistics->comment.length, @@ -629,8 +622,6 @@ db_create_routine(THD *thd, int type, sp_head *sp) done: close_thread_tables(thd); - if (dbchanged) - (void) mysql_change_db(thd, old_db.str, 1); DBUG_RETURN(ret); } @@ -672,7 +663,6 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) { TABLE *table; int ret; - bool opened; DBUG_ENTER("db_update_routine"); DBUG_PRINT("enter", ("type: %d name: %.*s", type, name->m_name.length, name->m_name.str)); @@ -686,10 +676,10 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time(); if (chistics->suid != SP_IS_DEFAULT_SUID) table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]-> - store((longlong)chistics->suid); + store((longlong)chistics->suid, 1); if (chistics->daccess != SP_DEFAULT_ACCESS) table->field[MYSQL_PROC_FIELD_ACCESS]-> - store((longlong)chistics->daccess); + store((longlong)chistics->daccess, 1); if (chistics->comment.str) table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment.str, chistics->comment.length, diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index fea6a67f32c..f5912caddaf 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -124,7 +124,6 @@ void sp_cache_clear(sp_cache **cp) void sp_cache_insert(sp_cache **cp, sp_head *sp) { sp_cache *c; - ulong v; if (!(c= *cp)) { diff --git a/sql/sp_head.cc b/sql/sp_head.cc index a06bfe28a6f..152bc87aead 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -444,9 +444,12 @@ 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_recursion_level(0), m_next_cached_sp(0), - m_first_instance(this), m_first_free_instance(this), m_last_cached_sp(this), m_cont_level(0) { + m_first_instance= this; + m_first_free_instance= this; + m_last_cached_sp= this; + m_return_field_def.charset = NULL; extern byte * @@ -1648,7 +1651,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) Item_null *null_item= new Item_null(); if (!null_item || - nctx->set_variable(thd, i, (struct Item **)&null_item)) + nctx->set_variable(thd, i, (Item **)&null_item)) { err_status= TRUE; break; @@ -2789,7 +2792,7 @@ void sp_instr_freturn::print(String *str) { /* freturn type expr... */ - if (str->reserve(UINT_MAX+8+32)) // Add some for the expr. too + if (str->reserve(1024+8+32)) // Add some for the expr. too return; str->qs_append(STRING_WITH_LEN("freturn ")); str->qs_append((uint)m_type); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 724cf88d373..ab39cb250f6 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1898,7 +1898,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, table->field[next_field+2]->store((longlong) mqh.conn_per_hour, TRUE); if (table->s->fields >= 36 && (mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS)) - table->field[next_field+3]->store((longlong) mqh.user_conn); + table->field[next_field+3]->store((longlong) mqh.user_conn, TRUE); mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour; } if (old_row_exists) @@ -3726,7 +3726,7 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant, GRANT_COLUMN *grant_column; ulong want_access= grant->want_privilege & ~grant->privilege; DBUG_ENTER("check_grant_column"); - DBUG_PRINT("enter", ("table: %s want_access: %u", table_name, want_access)); + DBUG_PRINT("enter", ("table: %s want_access: %lu", table_name, want_access)); if (!want_access) DBUG_RETURN(0); // Already checked diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0f6715fc078..0a7abc87061 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -519,7 +519,15 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) DBUG_PRINT("info", ("thd->open_tables: %p", thd->open_tables)); - found_old_table= 0; + + /* + End open index scans and table scans and remove references to the tables + from the handler tables hash. After this preparation it is safe to close + the tables. + */ + mysql_ha_mark_tables_for_reopen(thd, thd->open_tables); + + found_old_table= 0; while (thd->open_tables) found_old_table|=close_thread_table(thd, &thd->open_tables); thd->some_tables_deleted=0; @@ -686,7 +694,7 @@ void close_temporary_tables(THD *thd) /* We always quote db,table names though it is slight overkill */ if (found_user_tables && - !(was_quote_show= (thd->options & OPTION_QUOTE_SHOW_CREATE))) + !(was_quote_show= test(thd->options & OPTION_QUOTE_SHOW_CREATE))) { thd->options |= OPTION_QUOTE_SHOW_CREATE; } @@ -1483,6 +1491,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table->file->ft_handler= 0; if (table->timestamp_field) table->timestamp_field_type= table->timestamp_field->get_auto_set_type(); + table->pos_in_table_list= table_list; table_list->updatable= 1; // It is not derived table nor non-updatable VIEW DBUG_ASSERT(table->key_read == 0); DBUG_RETURN(table); @@ -2767,6 +2776,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db, if (thd->slave_thread) slave_open_temp_tables++; } + tmp_table->pos_in_table_list= 0; DBUG_RETURN(tmp_table); } @@ -3306,6 +3316,12 @@ find_field_in_tables(THD *thd, Item_ident *item, { if (found == WRONG_GRANT) return (Field*) 0; + + /* + Only views fields should be marked as dependent, not an underlying + fields. + */ + if (!table_ref->belong_to_view) { SELECT_LEX *current_sel= thd->lex->current_select; SELECT_LEX *last_select= table_ref->select_lex; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index ff033b69f98..2c77e0ef230 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -527,7 +527,8 @@ void Query_cache_query::init_n_lock() my_rwlock_init(&lock, NULL); lock_writing(); DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx", - ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block)))); + (long) (((byte*) this) - + ALIGN_SIZE(sizeof(Query_cache_block))))); DBUG_VOID_RETURN; } @@ -536,7 +537,8 @@ void Query_cache_query::unlock_n_destroy() { DBUG_ENTER("Query_cache_query::unlock_n_destroy"); DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx", - ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block)))); + (long) (((byte*) this) - + ALIGN_SIZE(sizeof(Query_cache_block))))); /* The following call is not needed on system where one can destroy an active semaphore @@ -702,6 +704,7 @@ void query_cache_abort(NET *net) void query_cache_end_of_result(THD *thd) { + Query_cache_block *query_block; DBUG_ENTER("query_cache_end_of_result"); /* See the comment on double-check locking usage above. */ @@ -717,13 +720,9 @@ void query_cache_end_of_result(THD *thd) if (unlikely(query_cache.query_cache_size == 0 || query_cache.flush_in_progress)) - { - STRUCT_UNLOCK(&query_cache.structure_guard_mutex); - DBUG_VOID_RETURN; - } + goto end; - Query_cache_block *query_block= ((Query_cache_block*) - thd->net.query_cache_query); + query_block= ((Query_cache_block*) thd->net.query_cache_query); if (query_block) { DUMP(&query_cache); @@ -742,27 +741,25 @@ void query_cache_end_of_result(THD *thd) header->query())); query_cache.wreck(__LINE__, ""); - STRUCT_UNLOCK(&query_cache.structure_guard_mutex); - - DBUG_VOID_RETURN; + /* + We do not need call of BLOCK_UNLOCK_WR(query_block); here because + query_cache.wreck() switched query cache off but left content + untouched for investigation (it is debugging method). + */ + goto end; } #endif header->found_rows(current_thd->limit_found_rows); header->result()->type= Query_cache_block::RESULT; header->writer(0); thd->net.query_cache_query= 0; + BLOCK_UNLOCK_WR(query_block); DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1);); - STRUCT_UNLOCK(&query_cache.structure_guard_mutex); - - BLOCK_UNLOCK_WR(query_block); - } - else - { - // Cache was flushed or resized and query was deleted => do nothing - STRUCT_UNLOCK(&query_cache.structure_guard_mutex); } +end: + STRUCT_UNLOCK(&query_cache.structure_guard_mutex); DBUG_VOID_RETURN; } @@ -879,8 +876,8 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu", flags.character_set_client_num, flags.character_set_results_num, flags.collation_connection_num, - flags.limit, - (ulong)flags.time_zone, + (ulong) flags.limit, + (ulong) flags.time_zone, flags.sql_mode, flags.max_sort_length, flags.group_concat_max_len)); @@ -909,7 +906,7 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu", if (thd->db_length) { memcpy(thd->query+thd->query_length+1, thd->db, thd->db_length); - DBUG_PRINT("qcache", ("database : %s length %u", + DBUG_PRINT("qcache", ("database: %s length: %u", thd->db, thd->db_length)); } else @@ -1055,7 +1052,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) (pre-space is removed in dispatch_command) First '/' looks like comment before command it is not - frequently appeared in real lihe, consequently we can + frequently appeared in real life, consequently we can check all such queries, too. */ if ((my_toupper(system_charset_info, sql[i]) != 'S' || @@ -1084,7 +1081,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) if (thd->db_length) { memcpy(sql+query_length+1, thd->db, thd->db_length); - DBUG_PRINT("qcache", ("database: '%s' length %u", + DBUG_PRINT("qcache", ("database: '%s' length: %u", thd->db, thd->db_length)); } else @@ -1122,8 +1119,8 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu", flags.character_set_client_num, flags.character_set_results_num, flags.collation_connection_num, - flags.limit, - (ulong)flags.time_zone, + (ulong) flags.limit, + (ulong) flags.time_zone, flags.sql_mode, flags.max_sort_length, flags.group_concat_max_len)); @@ -1237,9 +1234,9 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu", if (engine_data != table->engine_data()) { DBUG_PRINT("qcache", - ("Handler require invalidation queries of %s.%s %lld-%lld", - table_list.db, table_list.alias, - engine_data, table->engine_data())); + ("Handler require invalidation queries of %s.%s %lu-%lu", + table_list.db, table_list.alias, + (ulong) engine_data, (ulong) table->engine_data())); invalidate_table((byte *) table->db(), table->key_length()); } else @@ -1260,10 +1257,10 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu", #ifndef EMBEDDED_LIBRARY do { - DBUG_PRINT("qcache", ("Results (len %lu, used %lu, headers %lu)", + DBUG_PRINT("qcache", ("Results (len: %lu used: %lu headers: %lu)", result_block->length, result_block->used, - result_block->headers_len()+ - ALIGN_SIZE(sizeof(Query_cache_result)))); + (ulong) (result_block->headers_len()+ + ALIGN_SIZE(sizeof(Query_cache_result))))); Query_cache_result *result = result_block->result(); if (net_real_write(&thd->net, result->data(), @@ -1345,7 +1342,7 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) for (; tables_used; tables_used= tables_used->next) { invalidate_table((byte*) tables_used->key, tables_used->key_length); - DBUG_PRINT("qcache", (" db %s, table %s", tables_used->key, + DBUG_PRINT("qcache", ("db: %s table: %s", tables_used->key, tables_used->key+ strlen(tables_used->key)+1)); } @@ -2037,7 +2034,7 @@ Query_cache::append_result_data(Query_cache_block **current_block, { DBUG_ENTER("Query_cache::append_result_data"); DBUG_PRINT("qcache", ("append %lu bytes to 0x%lx query", - data_len, query_block)); + data_len, (long) query_block)); if (query_block->query()->add(data_len) > query_cache_limit) { @@ -2356,7 +2353,7 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used, { char key[MAX_DBKEY_LENGTH]; uint key_length; - DBUG_PRINT("qcache", ("view %s, db %s", + DBUG_PRINT("qcache", ("view: %s db: %s", tables_used->view_name.str, tables_used->view_db.str)); key_length= (uint) (strmov(strmov(key, tables_used->view_db.str) + 1, @@ -2477,11 +2474,11 @@ Query_cache::insert_table(uint key_len, char *key, table_block->table()->engine_data() != engine_data) { DBUG_PRINT("qcache", - ("Handler require invalidation queries of %s.%s %lld-%lld", + ("Handler require invalidation queries of %s.%s %lu-%lu", table_block->table()->db(), table_block->table()->table(), - engine_data, - table_block->table()->engine_data())); + (ulong) engine_data, + (ulong) table_block->table()->engine_data())); /* as far as we delete all queries with this table, table block will be deleted, too @@ -2979,7 +2976,7 @@ static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used, table_count++; if (tables_used->view) { - DBUG_PRINT("qcache", ("view %s, db %s", + DBUG_PRINT("qcache", ("view: %s db: %s", tables_used->view_name.str, tables_used->view_db.str)); *tables_type|= HA_CACHE_TBL_NONTRANSACT; @@ -3044,10 +3041,10 @@ Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex, OPTION_TO_QUERY_CACHE))) && lex->safe_to_cache_query) { - DBUG_PRINT("qcache", ("options %lx %lx, type %u", - OPTION_TO_QUERY_CACHE, - lex->select_lex.options, - (int) thd->variables.query_cache_type)); + DBUG_PRINT("qcache", ("options: %lx %lx type: %u", + (long) OPTION_TO_QUERY_CACHE, + (long) lex->select_lex.options, + (int) thd->variables.query_cache_type)); if (!(table_count= process_and_count_tables(tables_used, tables_type))) DBUG_RETURN(0); @@ -3063,10 +3060,10 @@ Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex, } DBUG_PRINT("qcache", - ("not interesting query: %d or not cacheable, options %lx %lx, type %u", + ("not interesting query: %d or not cacheable, options %lx %lx type: %u", (int) lex->sql_command, - OPTION_TO_QUERY_CACHE, - lex->select_lex.options, + (long) OPTION_TO_QUERY_CACHE, + (long) lex->select_lex.options, (int) thd->variables.query_cache_type)); DBUG_RETURN(0); } @@ -3529,7 +3526,7 @@ uint Query_cache::filename_2_table_key (char *key, const char *path, #if defined(DBUG_OFF) && !defined(USE_QUERY_CACHE_INTEGRITY_CHECK) -void wreck(uint line, const char *message) {} +void wreck(uint line, const char *message) { query_cache_size = 0; } void bins_dump() {} void cache_dump() {} void queries_dump() {} @@ -3541,6 +3538,17 @@ my_bool in_blocks(Query_cache_block * point) { return 0; } #else + +/* + Debug method which switch query cache off but left content for + investigation. + + SYNOPSIS + Query_cache::wreck() + line line of the wreck() call + message message for logging +*/ + void Query_cache::wreck(uint line, const char *message) { THD *thd=current_thd; @@ -3655,7 +3663,8 @@ void Query_cache::queries_dump() DBUG_PRINT("qcache", ("F:%u C:%u L:%lu T:'%s' (%u) '%s' '%s'", flags.client_long_flag, flags.character_set_client_num, - (ulong)flags.limit, flags.time_zone->get_name(), + (ulong)flags.limit, + flags.time_zone->get_name()->ptr(), len, str, strend(str)+1)); DBUG_PRINT("qcache", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong) block, (ulong) block->next, (ulong) block->prev, @@ -3763,8 +3772,8 @@ my_bool Query_cache::check_integrity(bool locked) (((long)first_block) % (long)ALIGN_SIZE(1))) { DBUG_PRINT("error", - ("block 0x%lx do not aligned by %d", (ulong) block, - ALIGN_SIZE(1))); + ("block 0x%lx do not aligned by %d", (long) block, + (int) ALIGN_SIZE(1))); result = 1; } // Check memory allocation @@ -3875,9 +3884,8 @@ my_bool Query_cache::check_integrity(bool locked) break; } default: - DBUG_PRINT("error", - ("block 0x%lx have incorrect type %u", - block, block->type)); + DBUG_PRINT("error", ("block 0x%lx have incorrect type %u", + (long) block, block->type)); result = 1; } @@ -3975,8 +3983,8 @@ my_bool Query_cache::check_integrity(bool locked) } while (block != bins[i].free_blocks); if (count != bins[i].number) { - DBUG_PRINT("error", ("bin[%d].number is %d, but bin have %d blocks", - bins[i].number, count)); + DBUG_PRINT("error", ("bins[%d].number = %d, but bin have %d blocks", + i, bins[i].number, count)); result = 1; } } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ba2f525a4a4..c66baaedf9f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -712,7 +712,7 @@ void THD::add_changed_table(const char *key, long key_length) { list_include(prev_changed, curr, changed_table_dup(key, key_length)); DBUG_PRINT("info", - ("key_length %u %u", key_length, (*prev_changed)->key_length)); + ("key_length %ld %u", key_length, (*prev_changed)->key_length)); DBUG_VOID_RETURN; } else if (cmp == 0) @@ -722,7 +722,7 @@ void THD::add_changed_table(const char *key, long key_length) { list_include(prev_changed, curr, changed_table_dup(key, key_length)); DBUG_PRINT("info", - ("key_length %u %u", key_length, + ("key_length %ld %u", key_length, (*prev_changed)->key_length)); DBUG_VOID_RETURN; } @@ -734,7 +734,7 @@ void THD::add_changed_table(const char *key, long key_length) } } *prev_changed = changed_table_dup(key, key_length); - DBUG_PRINT("info", ("key_length %u %u", key_length, + DBUG_PRINT("info", ("key_length %ld %u", key_length, (*prev_changed)->key_length)); DBUG_VOID_RETURN; } @@ -1510,53 +1510,21 @@ bool select_exists_subselect::send_data(List<Item> &items) int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u) { - List_iterator_fast<Item> li(list); - List_iterator_fast<my_var> gl(var_list); - Item *item; - - local_vars.empty(); // Clear list if SP unit= u; - row_count= 0; - + if (var_list.elements != list.elements) { my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0)); return 1; - } - while ((item=li++)) - { - my_var *mv= gl++; - if (mv->local) - { - 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); - /* - Item_func_set_user_var can't substitute something else on its place => - 0 can be passed as last argument (reference on item) - Item_func_set_user_var can't be fixed after creation, so we do not - check var->fixed - */ - var->fix_fields(thd, 0); - var->fix_length_and_dec(); - vars.push_back(var); - } - } + } return 0; } void select_dumpvar::cleanup() { - vars.empty(); - row_count=0; + row_count= 0; } @@ -1865,13 +1833,10 @@ Statement_map::~Statement_map() bool select_dumpvar::send_data(List<Item> &items) { - List_iterator_fast<Item_func_set_user_var> li(vars); - List_iterator_fast<Item_splocal> var_li(local_vars); - List_iterator_fast<my_var> my_li(var_list); + List_iterator_fast<my_var> var_li(var_list); List_iterator<Item> it(items); - Item_func_set_user_var *xx; - Item_splocal *yy; - my_var *zz; + Item *item; + my_var *mv; DBUG_ENTER("select_dumpvar::send_data"); if (unit->offset_limit_cnt) @@ -1884,24 +1849,19 @@ bool select_dumpvar::send_data(List<Item> &items) my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0)); DBUG_RETURN(1); } - while ((zz=my_li++) && (it++)) + while ((mv= var_li++) && (item= it++)) { - if (zz->local) + if (mv->local) { - if ((yy=var_li++)) - { - if (thd->spcont->set_variable(current_thd, yy->get_var_idx(), - it.ref())) - DBUG_RETURN(1); - } + if (thd->spcont->set_variable(thd, mv->offset, &item)) + DBUG_RETURN(1); } else { - if ((xx=li++)) - { - xx->check(0); - xx->update(); - } + Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item); + suv->fix_fields(thd, 0); + suv->check(0); + suv->update(); } } DBUG_RETURN(0); diff --git a/sql/sql_class.h b/sql/sql_class.h index c7bdfbd7ea7..716b689994a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -495,6 +495,8 @@ struct system_variables { ulonglong myisam_max_extra_sort_file_size; ulonglong myisam_max_sort_file_size; + ulonglong max_heap_table_size; + ulonglong tmp_table_size; ha_rows select_limit; ha_rows max_join_size; ulong auto_increment_increment, auto_increment_offset; @@ -503,7 +505,6 @@ struct system_variables ulong long_query_time; ulong max_allowed_packet; ulong max_error_count; - ulong max_heap_table_size; ulong max_length_for_sort_data; ulong max_sort_length; ulong max_tmp_tables; @@ -527,7 +528,6 @@ struct system_variables ulong div_precincrement; ulong sortbuff_size; ulong table_type; - ulong tmp_table_size; ulong tx_isolation; ulong completion_type; /* Determines which non-standard SQL behaviour should be enabled */ @@ -1102,6 +1102,12 @@ public: struct st_mysql_data **data_tail; void clear_data_list(); struct st_mysql_data *alloc_new_dataset(); + /* + In embedded server it points to the statement that is processed + in the current query. We store some results directly in statement + fields then. + */ + struct st_mysql_stmt *current_stmt; #endif NET net; // client connection descriptor MEM_ROOT warn_root; // For warnings and errors @@ -2068,7 +2074,8 @@ class user_var_entry class Unique :public Sql_alloc { DYNAMIC_ARRAY file_ptrs; - ulong max_elements, max_in_memory_size; + ulong max_elements; + ulonglong max_in_memory_size; IO_CACHE file; TREE tree; byte *record_pointers; @@ -2078,13 +2085,13 @@ class Unique :public Sql_alloc public: ulong elements; Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg, - uint size_arg, ulong max_in_memory_size_arg); + uint size_arg, ulonglong max_in_memory_size_arg); ~Unique(); ulong elements_in_tree() { return tree.elements_in_tree; } inline bool unique_add(void *ptr) { DBUG_ENTER("unique_add"); - DBUG_PRINT("info", ("tree %u - %u", tree.elements_in_tree, max_elements)); + DBUG_PRINT("info", ("tree %u - %lu", tree.elements_in_tree, max_elements)); if (tree.elements_in_tree > max_elements && flush()) DBUG_RETURN(1); DBUG_RETURN(!tree_insert(&tree, ptr, 0, tree.custom_arg)); @@ -2092,13 +2099,13 @@ public: bool get(TABLE *table); static double get_use_cost(uint *buffer, uint nkeys, uint key_size, - ulong max_in_memory_size); + ulonglong max_in_memory_size); inline static int get_cost_calc_buff_size(ulong nkeys, uint key_size, - ulong max_in_memory_size) + ulonglong max_in_memory_size) { - register ulong max_elems_in_tree= + register ulonglong max_elems_in_tree= (1 + max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size)); - return sizeof(uint)*(1 + nkeys/max_elems_in_tree); + return (int) (sizeof(uint)*(1 + nkeys/max_elems_in_tree)); } void reset(); @@ -2189,9 +2196,7 @@ class select_dumpvar :public select_result_interceptor { ha_rows row_count; public: List<my_var> var_list; - List<Item_func_set_user_var> vars; - List<Item_splocal> local_vars; - select_dumpvar(void) { var_list.empty(); local_vars.empty(); vars.empty(); row_count=0;} + select_dumpvar() { var_list.empty(); row_count= 0;} ~select_dumpvar() {} int prepare(List<Item> &list, SELECT_LEX_UNIT *u); bool send_data(List<Item> &items); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 43d09d288e5..1dd9406109c 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1172,7 +1172,7 @@ err: bool mysql_change_db(THD *thd, const char *name, bool no_access_check) { - int path_length, db_length; + int db_length; char *db_name; bool system_db= 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index e13e7728708..b665113dd18 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -326,7 +326,7 @@ cleanup: { thd->row_count_func= deleted; send_ok(thd,deleted); - DBUG_PRINT("info",("%d records deleted",deleted)); + DBUG_PRINT("info",("%ld records deleted",(long) deleted)); } DBUG_RETURN(error >= 0 || thd->net.report_error); } @@ -902,7 +902,7 @@ end: trunc_by_del: /* Probably InnoDB table */ - ulong save_options= thd->options; + ulonglong save_options= thd->options; table_list->lock_type= TL_WRITE; thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT); ha_enable_transaction(thd, FALSE); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 0193d4d5355..4c0916c389f 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -338,7 +338,6 @@ 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; @@ -748,3 +747,41 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags) DBUG_RETURN(0); } + + +/* + Mark tables for reopen. + + SYNOPSIS + mysql_ha_mark_tables_for_reopen() + thd Thread identifier. + table Table list to mark for reopen. + + DESCRIPTION + For each table found in the handler hash mark it as closed + (ready for reopen) and end all index/table scans. + + NOTE + The caller must lock LOCK_open. +*/ + +void mysql_ha_mark_tables_for_reopen(THD *thd, TABLE *table) +{ + DBUG_ENTER("mysql_ha_mark_tables_for_reopen"); + + safe_mutex_assert_owner(&LOCK_open); + for (; table; table= table->next) + { + TABLE_LIST *hash_tables; + if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, + (byte*) table->alias, + strlen(table->alias) + 1))) + { + /* Mark table as ready for reopen. */ + hash_tables->table= NULL; + /* End open index/table scans. */ + table->file->ha_index_or_rnd_end(); + } + } + DBUG_VOID_RETURN; +} diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index f39cf39f08e..3de842c8551 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -162,6 +162,7 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc; lex->select_lex.group_list.empty(); lex->select_lex.order_list.empty(); + lex->select_lex.udf_list.empty(); lex->current_select= &lex->select_lex; lex->yacc_yyss=lex->yacc_yyvs=0; lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE); @@ -1165,6 +1166,7 @@ void st_select_lex::init_select() braces= 0; when_list.empty(); expr_list.empty(); + udf_list.empty(); interval_list.empty(); use_index.empty(); ftfunc_list_alloc.empty(); @@ -1178,7 +1180,7 @@ void st_select_lex::init_select() select_limit= 0; /* denotes the default limit = HA_POS_ERROR */ offset_limit= 0; /* denotes the default offset = 0 */ with_sum_func= 0; - + is_correlated= 0; } /* @@ -1372,6 +1374,8 @@ void st_select_lex::mark_as_dependent(SELECT_LEX *last) SELECT_LEX_UNIT *munit= s->master_unit(); munit->uncacheable|= UNCACHEABLE_DEPENDENT; } + is_correlated= TRUE; + this->master_unit()->item->is_correlated= TRUE; } bool st_select_lex_node::set_braces(bool value) { return 1; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 398e5666c7f..be12467d097 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -397,7 +397,7 @@ protected: TABLE *table; /* temporary table using for appending UNION results */ select_result *result; - ulong found_rows_for_union; + ulonglong found_rows_for_union; bool res; public: bool prepared, // prepare phase already performed for UNION (unit) @@ -470,7 +470,7 @@ public: void set_thd(THD *thd_arg) { thd= thd_arg; } friend void lex_start(THD *thd, uchar *buf, uint length); - friend int subselect_union_engine::exec(); + friend int subselect_union_engine::exec(bool); List<Item> *get_unit_column_types(); }; @@ -562,6 +562,8 @@ public: query processing end even if we use temporary table */ bool subquery_in_having; + /* TRUE <=> this SELECT is correlated w.r.t. some ancestor select */ + bool is_correlated; /* This variable is required to ensure proper work of subqueries and stored procedures. Generally, one should use the states of @@ -581,6 +583,8 @@ public: /* exclude this select from check of unique_table() */ bool exclude_from_table_unique_test; + List<udf_func> udf_list; /* udf function calls stack */ + void init_query(); void init_select(); st_select_lex_unit* master_unit(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e3734026858..c9d95287c90 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -381,9 +381,9 @@ int check_user(THD *thd, enum enum_server_command command, NO_ACCESS)) // authentication is OK { DBUG_PRINT("info", - ("Capabilities: %d packet_length: %ld Host: '%s' " + ("Capabilities: %lu packet_length: %ld Host: '%s' " "Login user: '%s' Priv_user: '%s' Using password: %s " - "Access: %u db: '%s'", + "Access: %lu db: '%s'", thd->client_capabilities, thd->max_client_packet_length, thd->main_security_ctx.host_or_ip, @@ -956,7 +956,7 @@ static int check_connection(THD *thd) if (thd->client_capabilities & CLIENT_IGNORE_SPACE) thd->variables.sql_mode|= MODE_IGNORE_SPACE; #ifdef HAVE_OPENSSL - DBUG_PRINT("info", ("client capabilities: %d", thd->client_capabilities)); + DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities)); if (thd->client_capabilities & CLIENT_SSL) { /* Do the SSL layering. */ @@ -1112,7 +1112,7 @@ pthread_handler_t handle_one_connection(void *arg) of handle_one_connection, which is thd. We need to know the start of the stack so that we could check for stack overruns. */ - DBUG_PRINT("info", ("handle_one_connection called by thread %d\n", + DBUG_PRINT("info", ("handle_one_connection called by thread %lu\n", thd->thread_id)); /* now that we've called my_thread_init(), it is safe to call DBUG_* */ @@ -1764,7 +1764,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (alloc_query(thd, packet, packet_length)) break; // fatal error is set char *packet_end= thd->query + thd->query_length; - mysql_log.write(thd,command, "%.*b", thd->query_length, thd->query); + /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */ + const char *format= "%.*b"; + mysql_log.write(thd,command, format, thd->query_length, thd->query); DBUG_PRINT("query",("%-.4096s",thd->query)); if (!(specialflag & SPECIAL_NO_PRIOR)) @@ -2503,7 +2505,23 @@ mysql_execute_command(THD *thd) { /* we warn the slave SQL thread */ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); - reset_one_shot_variables(thd); + if (thd->one_shot_set) + { + /* + It's ok to check thd->one_shot_set here: + + The charsets in a MySQL 5.0 slave can change by both a binlogged + SET ONE_SHOT statement and the event-internal charset setting, + and these two ways to change charsets do not seems to work + together. + + At least there seems to be problems in the rli cache for + charsets if we are using ONE_SHOT. Note that this is normally no + problem because either the >= 5.0 slave reads a 4.1 binlog (with + ONE_SHOT) *or* or 5.0 binlog (without ONE_SHOT) but never both." + */ + reset_one_shot_variables(thd); + } DBUG_RETURN(0); } } @@ -2515,12 +2533,13 @@ mysql_execute_command(THD *thd) tables. Except for the replication thread and the 'super' users. */ if (opt_readonly && - !(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))) + !(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_DROP_TABLE) && lex->drop_temporary) && + ((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); @@ -2881,6 +2900,12 @@ mysql_execute_command(THD *thd) goto end_with_restore_list; #ifndef HAVE_READLINK + if (lex->create_info.data_file_name) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, + "DATA DIRECTORY option ignored"); + if (lex->create_info.index_file_name) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, + "INDEX DIRECTORY option ignored"); lex->create_info.data_file_name=lex->create_info.index_file_name=0; #else /* Fix names if symlinked tables */ @@ -3435,8 +3460,12 @@ end_with_restore_list: if (first_table->lock_type == TL_WRITE_CONCURRENT_INSERT && thd->lock) { + /* INSERT ... SELECT should invalidate only the very first table */ + TABLE_LIST *save_table= first_table->next_local; + first_table->next_local= 0; mysql_unlock_tables(thd, thd->lock); query_cache_invalidate3(thd, first_table, 1); + first_table->next_local= save_table; thd->lock=0; } delete result; @@ -4017,8 +4046,9 @@ end_with_restore_list: case SQLCOM_FLUSH: { bool write_to_binlog; - if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, all_tables)) + if (check_global_access(thd,RELOAD_ACL)) goto error; + /* reload_acl_and_cache() will tell us if we are allowed to write to the binlog or not. @@ -4039,7 +4069,8 @@ end_with_restore_list: } } send_ok(thd); - } + } + break; } case SQLCOM_KILL: @@ -4221,26 +4252,38 @@ end_with_restore_list: { uint namelen; char *name; - int result; + int result= SP_INTERNAL_ERROR; DBUG_ASSERT(lex->sphead != 0); DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */ - - if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0, - is_schema_db(lex->sphead->m_db.str))) + /* + Verify that the database name is allowed, optionally + lowercase it. + */ + if (check_db_name(lex->sphead->m_db.str)) { - delete lex->sphead; - lex->sphead= 0; - goto error; + my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str); + goto create_sp_error; } - if (end_active_trans(thd)) + /* + Check that a database directory with this name + exists. Design note: This won't work on virtual databases + like information_schema. + */ + if (check_db_dir_existence(lex->sphead->m_db.str)) { - delete lex->sphead; - lex->sphead= 0; - goto error; + my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str); + goto create_sp_error; } + if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0, + is_schema_db(lex->sphead->m_db.str))) + goto create_sp_error; + + if (end_active_trans(thd)) + goto create_sp_error; + name= lex->sphead->name(&namelen); #ifdef HAVE_DLOPEN if (lex->sphead->m_type == TYPE_ENUM_FUNCTION) @@ -4249,10 +4292,8 @@ end_with_restore_list: if (udf) { - my_error(ER_UDF_EXISTS, MYF(0), name); - delete lex->sphead; - lex->sphead= 0; - goto error; + my_error(ER_UDF_EXISTS, MYF(0), name); + goto create_sp_error; } } #endif @@ -4260,7 +4301,7 @@ end_with_restore_list: /* If the definer is not specified, this means that CREATE-statement missed DEFINER-clause. DEFINER-clause can be missed in two cases: - + - The user submitted a statement w/o the clause. This is a normal case, we should assign CURRENT_USER as definer. @@ -4269,7 +4310,7 @@ end_with_restore_list: CURRENT_USER as definer here, but also we should mark this routine as NON-SUID. This is essential for the sake of backward compatibility. - + The problem is the slave thread is running under "special" user (@), that actually does not exist. In the older versions we do not fail execution of a stored routine if its definer does not exist and @@ -4294,13 +4335,9 @@ end_with_restore_list: if (ps_arena) thd->restore_active_arena(ps_arena, &original_arena); + /* Error has been already reported. */ if (res) - { - /* Error has been already reported. */ - delete lex->sphead; - lex->sphead= 0; - goto error; - } + goto create_sp_error; if (thd->slave_thread) lex->sphead->m_chistics->suid= SP_IS_NOT_SUID; @@ -4311,7 +4348,7 @@ end_with_restore_list: that the current user has SUPER privilege (in order to create a stored routine under another user one must have SUPER privilege). */ - + else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) || my_strcasecmp(system_charset_info, lex->definer->host.str, @@ -4320,9 +4357,7 @@ end_with_restore_list: if (check_global_access(thd, SUPER_ACL)) { my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); - delete lex->sphead; - lex->sphead= 0; - goto error; + goto create_sp_error; } } @@ -4342,54 +4377,51 @@ end_with_restore_list: #endif /* NO_EMBEDDED_ACCESS_CHECKS */ res= (result= lex->sphead->create(thd)); - if (result == SP_OK) - { + switch (result) { + case SP_OK: #ifndef NO_EMBEDDED_ACCESS_CHECKS /* only add privileges if really neccessary */ if (sp_automatic_privileges && !opt_noacl && check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS, - lex->sphead->m_db.str, name, + lex->sphead->m_db.str, name, lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1)) { - close_thread_tables(thd); if (sp_grant_privileges(thd, lex->sphead->m_db.str, name, lex->sql_command == SQLCOM_CREATE_PROCEDURE)) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_PROC_AUTO_GRANT_FAIL, - ER(ER_PROC_AUTO_GRANT_FAIL)); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_PROC_AUTO_GRANT_FAIL, + ER(ER_PROC_AUTO_GRANT_FAIL)); + close_thread_tables(thd); } #endif - lex->unit.cleanup(); - delete lex->sphead; - lex->sphead= 0; - send_ok(thd); - } - else - { - switch (result) { - case SP_WRITE_ROW_FAILED: - my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name); - break; - case SP_NO_DB_ERROR: - my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str); - break; - case SP_BAD_IDENTIFIER: - my_error(ER_TOO_LONG_IDENT, MYF(0), name); - break; - case SP_BODY_TOO_LONG: - my_error(ER_TOO_LONG_BODY, MYF(0), name); - break; - default: - my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name); - break; - } - lex->unit.cleanup(); - delete lex->sphead; - lex->sphead= 0; - goto error; - } break; - } + case SP_WRITE_ROW_FAILED: + my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name); + break; + case SP_BAD_IDENTIFIER: + my_error(ER_TOO_LONG_IDENT, MYF(0), name); + break; + case SP_BODY_TOO_LONG: + my_error(ER_TOO_LONG_BODY, MYF(0), name); + break; + default: + my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name); + break; + } /* end switch */ + + /* + Capture all errors within this CASE and + clean up the environment. + */ +create_sp_error: + lex->unit.cleanup(); + delete lex->sphead; + lex->sphead= 0; + if (result != SP_OK ) + goto error; + send_ok(thd); + break; /* break super switch */ + } /* end case group bracket */ case SQLCOM_CALL: { sp_head *sp; @@ -6119,7 +6151,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->alias= alias_str; if (lower_case_table_names && table->table.length) - my_casedn_str(files_charset_info, table->table.str); + table->table.length= my_casedn_str(files_charset_info, table->table.str); ptr->table_name=table->table.str; ptr->table_name_length=table->table.length; ptr->lock_type= lock_type; @@ -6708,7 +6740,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, tmp_write_to_binlog= 0; mysql_log.new_file(1); mysql_slow_log.new_file(1); - mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE); + if( mysql_bin_log.is_open() ) + { + mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE); + } #ifdef HAVE_REPLICATION pthread_mutex_lock(&LOCK_active_mi); rotate_relay_log(active_mi); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 6517afa5432..8c0235e9768 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1664,7 +1664,7 @@ static bool check_prepared_statement(Prepared_statement *stmt, enum enum_sql_command sql_command= lex->sql_command; int res= 0; DBUG_ENTER("check_prepared_statement"); - DBUG_PRINT("enter",("command: %d, param_count: %ld", + DBUG_PRINT("enter",("command: %d, param_count: %u", sql_command, stmt->param_count)); lex->first_lists_tables_same(); @@ -1877,9 +1877,12 @@ void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length) thd->stmt_map.erase(stmt); } else - mysql_log.write(thd, COM_STMT_PREPARE, "[%lu] %.*b", stmt->id, + { + const char *format= "[%lu] %.*b"; + mysql_log.write(thd, COM_STMT_PREPARE, format, stmt->id, stmt->query_length, stmt->query); + } /* check_prepared_statemnt sends the metadata packet in case of success */ DBUG_VOID_RETURN; } @@ -2261,8 +2264,11 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length) if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); if (error == 0) - mysql_log.write(thd, COM_STMT_EXECUTE, "[%lu] %.*b", stmt->id, + { + const char *format= "[%lu] %.*b"; + mysql_log.write(thd, COM_STMT_EXECUTE, format, stmt->id, thd->query_length, thd->query); + } DBUG_VOID_RETURN; @@ -2873,7 +2879,6 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) { Statement stmt_backup; Query_arena *old_stmt_arena; - Item *old_free_list; bool error= TRUE; statistic_increment(thd->status_var.com_stmt_execute, &LOCK_status); diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index c87a8696bbc..8beb9839177 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -257,7 +257,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, static TABLE_LIST * rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error) { - TABLE_LIST *ren_table,*new_table, *tmp_table; + TABLE_LIST *ren_table, *new_table; DBUG_ENTER("rename_tables"); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index e1933d42f9e..8da8bbe25ca 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -430,6 +430,12 @@ impossible position"; goto err; } packet->set("\0", 1, &my_charset_bin); + /* + Adding MAX_LOG_EVENT_HEADER_LEN, since a binlog event can become + this larger than the corresponding packet (query) sent + from client to master. + */ + thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER; /* We can set log_lock now, it does not move (it's a member of @@ -1101,7 +1107,7 @@ bool change_master(THD* thd, MASTER_INFO* mi) { mi->master_log_pos= lex_mi->pos; } - DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos)); + DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); if (lex_mi->host) strmake(mi->host, lex_mi->host, sizeof(mi->host)-1); @@ -1218,7 +1224,7 @@ bool change_master(THD* thd, MASTER_INFO* mi) } } mi->rli.group_master_log_pos = mi->master_log_pos; - DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos)); + DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); /* Coordinates in rli were spoilt by the 'if (need_relay_log_purge)' block, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 75cfff4cbb6..3d2f46a9982 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -82,7 +82,7 @@ static store_key *get_store_key(THD *thd, static bool make_simple_join(JOIN *join,TABLE *tmp_table); static void make_outerjoin_info(JOIN *join); static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item); -static void make_join_readinfo(JOIN *join,uint options); +static void make_join_readinfo(JOIN *join, ulonglong options); static bool only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables); static void update_depend_map(JOIN *join); static void update_depend_map(JOIN *join, ORDER *order); @@ -90,7 +90,7 @@ static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond, bool change_list, bool *simple_order); static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables, List<Item> &fields, bool send_row, - uint select_options, const char *info, + ulonglong select_options, const char *info, Item *having); static COND *build_equal_items(THD *thd, COND *cond, COND_EQUAL *inherited, @@ -114,7 +114,7 @@ static bool resolve_nested_join (TABLE_LIST *table); 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, - ulong options); + ulonglong options); static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table, Procedure *proc); @@ -158,8 +158,8 @@ static int join_read_prev_same(READ_RECORD *info); static int join_read_prev(READ_RECORD *info); static int join_ft_read_first(JOIN_TAB *tab); static int join_ft_read_next(READ_RECORD *info); -static int join_read_always_key_or_null(JOIN_TAB *tab); -static int join_read_next_same_or_null(READ_RECORD *info); +int join_read_always_key_or_null(JOIN_TAB *tab); +int join_read_next_same_or_null(READ_RECORD *info); static COND *make_cond_for_table(COND *cond,table_map table, table_map used_table); static Item* part_of_refkey(TABLE *form,Field *field); @@ -512,11 +512,12 @@ err: DBUG_RETURN(-1); /* purecov: inspected */ } + /* test if it is known for optimisation IN subquery - SYNOPSYS - JOIN::test_in_subselect + SYNOPSIS + JOIN::test_in_subselect() where - pointer for variable in which conditions should be stored if subquery is known @@ -551,6 +552,35 @@ bool JOIN::test_in_subselect(Item **where) /* + Check if the passed HAVING clause is a clause added by subquery optimizer + + SYNOPSIS + is_having_subq_predicates() + having Having clause + + RETURN + TRUE The passed HAVING clause was added by the subquery optimizer + FALSE Otherwise +*/ + +bool is_having_subq_predicates(Item *having) +{ + if (having->type() == Item::FUNC_ITEM) + { + if (((Item_func *) having)->functype() == Item_func::ISNOTNULLTEST_FUNC) + return TRUE; + if (((Item_func *) having)->functype() == Item_func::TRIG_COND_FUNC) + { + having= ((Item_func*)having)->arguments()[0]; + if (((Item_func *) having)->functype() == Item_func::ISNOTNULLTEST_FUNC) + return TRUE; + } + return TRUE; + } + return FALSE; +} + +/* global select optimisation. return 0 - success 1 - error @@ -1018,9 +1048,7 @@ JOIN::optimize() } } else if (join_tab[0].type == JT_REF_OR_NULL && join_tab[0].ref.items[0]->name == in_left_expr_name && - having->type() == Item::FUNC_ITEM && - ((Item_func *) having)->functype() == - Item_func::ISNOTNULLTEST_FUNC) + is_having_subq_predicates(having)) { join_tab[0].type= JT_INDEX_SUBQUERY; error= 0; @@ -1273,14 +1301,14 @@ JOIN::reinit() exec_tmp_table1->file->extra(HA_EXTRA_RESET_STATE); exec_tmp_table1->file->delete_all_rows(); free_io_cache(exec_tmp_table1); - filesort_free_buffers(exec_tmp_table1); + filesort_free_buffers(exec_tmp_table1,0); } if (exec_tmp_table2) { exec_tmp_table2->file->extra(HA_EXTRA_RESET_STATE); exec_tmp_table2->file->delete_all_rows(); free_io_cache(exec_tmp_table2); - filesort_free_buffers(exec_tmp_table2); + filesort_free_buffers(exec_tmp_table2,0); } if (items0) set_items_ref_array(items0); @@ -1443,6 +1471,7 @@ JOIN::exec() curr_join->examined_rows= 0; if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) && + !thd->lex->describe && get_schema_tables_result(curr_join)) { DBUG_VOID_RETURN; @@ -1945,7 +1974,7 @@ bool mysql_select(THD *thd, Item ***rref_pointer_array, TABLE_LIST *tables, uint wild_num, List<Item> &fields, COND *conds, uint og_num, ORDER *order, ORDER *group, - Item *having, ORDER *proc_param, ulong select_options, + Item *having, ORDER *proc_param, ulonglong select_options, select_result *result, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex) { @@ -2519,6 +2548,9 @@ typedef struct key_field_t { // Used when finding key fields when val IS NULL. */ bool null_rejecting; + + /* TRUE<=> This ref access is an outer subquery reference access */ + bool outer_ref; } KEY_FIELD; /* Values in optimize */ @@ -2817,6 +2849,7 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond, cond->functype() == Item_func::MULT_EQUAL_FUNC) && ((*value)->type() == Item::FIELD_ITEM) && ((Item_field*)*value)->field->maybe_null()); + (*key_fields)->outer_ref= FALSE; (*key_fields)++; } @@ -2875,7 +2908,7 @@ add_key_equal_fields(KEY_FIELD **key_fields, uint and_level, } static void -add_key_fields(KEY_FIELD **key_fields,uint *and_level, +add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, COND *cond, table_map usable_tables, SARGABLE_PARAM **sargables) { @@ -2888,28 +2921,56 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level, { Item *item; while ((item=li++)) - add_key_fields(key_fields,and_level,item,usable_tables,sargables); + add_key_fields(join, key_fields, and_level, item, usable_tables, + sargables); for (; org_key_fields != *key_fields ; org_key_fields++) org_key_fields->level= *and_level; } else { (*and_level)++; - add_key_fields(key_fields,and_level,li++,usable_tables,sargables); + add_key_fields(join, key_fields, and_level, li++, usable_tables, + sargables); Item *item; while ((item=li++)) { KEY_FIELD *start_key_fields= *key_fields; (*and_level)++; - add_key_fields(key_fields,and_level,item,usable_tables,sargables); + add_key_fields(join, key_fields, and_level, item, usable_tables, + sargables); *key_fields=merge_key_fields(org_key_fields,start_key_fields, *key_fields,++(*and_level)); } } return; } - /* If item is of type 'field op field/constant' add it to key_fields */ + /* + Subquery optimization: check if the encountered condition is one + added by condition push down into subquery. + */ + { + if (cond->type() == Item::FUNC_ITEM && + ((Item_func*)cond)->functype() == Item_func::TRIG_COND_FUNC) + { + cond= ((Item_func*)cond)->arguments()[0]; + if (!join->group_list && !join->order && + join->unit->item && + join->unit->item->substype() == Item_subselect::IN_SUBS && + !join->unit->first_select()->next_select()) + { + KEY_FIELD *save= *key_fields; + add_key_fields(join, key_fields, and_level, cond, usable_tables, + sargables); + // Indicate that this ref access candidate is for subquery lookup: + for (; save != *key_fields; save++) + save->outer_ref= TRUE; + } + return; + } + } + + /* If item is of type 'field op field/constant' add it to key_fields */ if (cond->type() != Item::FUNC_ITEM) return; Item_func *cond_func= (Item_func*) cond; @@ -3083,6 +3144,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field) keyuse.used_tables=key_field->val->used_tables(); keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL; keyuse.null_rejecting= key_field->null_rejecting; + keyuse.outer_ref= key_field->outer_ref; VOID(insert_dynamic(keyuse_array,(gptr) &keyuse)); } } @@ -3205,7 +3267,7 @@ sort_keyuse(KEYUSE *a,KEYUSE *b) Here we can add 'ref' access candidates for t1 and t2, but not for t3. */ -static void add_key_fields_for_nj(TABLE_LIST *nested_join_table, +static void add_key_fields_for_nj(JOIN *join, TABLE_LIST *nested_join_table, KEY_FIELD **end, uint *and_level, SARGABLE_PARAM **sargables) { @@ -3217,12 +3279,13 @@ static void add_key_fields_for_nj(TABLE_LIST *nested_join_table, while ((table= li++)) { if (table->nested_join) - add_key_fields_for_nj(table, end, and_level, sargables); + add_key_fields_for_nj(join, table, end, and_level, sargables); else if (!table->on_expr) tables |= table->table->map; } - add_key_fields(end, and_level, nested_join_table->on_expr, tables, sargables); + add_key_fields(join, end, and_level, nested_join_table->on_expr, tables, + sargables); } @@ -3297,7 +3360,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, return TRUE; if (cond) { - add_key_fields(&end,&and_level,cond,normal_tables,sargables); + add_key_fields(join_tab->join, &end, &and_level, cond, normal_tables, + sargables); for (; field != end ; field++) { add_key_part(keyuse,field); @@ -3319,8 +3383,9 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, into account as well. */ if (*join_tab[i].on_expr_ref) - add_key_fields(&end,&and_level,*join_tab[i].on_expr_ref, - join_tab[i].table->map,sargables); + add_key_fields(join_tab->join, &end, &and_level, + *join_tab[i].on_expr_ref, + join_tab[i].table->map, sargables); } /* Process ON conditions for the nested joins */ @@ -3330,7 +3395,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, while ((table= li++)) { if (table->nested_join) - add_key_fields_for_nj(table, &end, &and_level, sargables); + add_key_fields_for_nj(join_tab->join, table, &end, &and_level, + sargables); } } @@ -4057,7 +4123,7 @@ choose_plan(JOIN *join, table_map join_tables) { uint search_depth= join->thd->variables.optimizer_search_depth; uint prune_level= join->thd->variables.optimizer_prune_level; - bool straight_join= join->select_options & SELECT_STRAIGHT_JOIN; + bool straight_join= test(join->select_options & SELECT_STRAIGHT_JOIN); DBUG_ENTER("choose_plan"); join->cur_embedding_map= 0; @@ -4659,8 +4725,6 @@ static void find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, double read_time) { - ha_rows rec; - double tmp; THD *thd= join->thd; if (!rest_tables) { @@ -5714,7 +5778,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) } static void -make_join_readinfo(JOIN *join, uint options) +make_join_readinfo(JOIN *join, ulonglong options) { uint i; @@ -6094,7 +6158,7 @@ void JOIN::cleanup(bool full) if (tables > const_tables) // Test for not-const tables { free_io_cache(table[const_tables]); - filesort_free_buffers(table[const_tables]); + filesort_free_buffers(table[const_tables],full); } if (full) @@ -6369,7 +6433,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, static int return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables, - List<Item> &fields, bool send_row, uint select_options, + List<Item> &fields, bool send_row, ulonglong select_options, const char *info, Item *having) { DBUG_ENTER("return_zero_rows"); @@ -6920,7 +6984,6 @@ static COND *build_equal_items_for_cond(COND *cond, Item_equal *item_equal; uint members; COND_EQUAL cond_equal; - COND *new_cond; cond_equal.upper_levels= inherited; if (cond->type() == Item::COND_ITEM) @@ -8560,6 +8623,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, item->collation.collation); else new_field= item->make_string_field(table); + new_field->set_derivation(item->collation.derivation); break; case DECIMAL_RESULT: new_field= new Field_new_decimal(item->max_length, maybe_null, item->name, @@ -8735,7 +8799,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, (make_copy_field ? 0 : copy_func), modify_item, convert_blob_length); case Item::TYPE_HOLDER: - return ((Item_type_holder *)item)->make_field_by_type(table); + result= ((Item_type_holder *)item)->make_field_by_type(table); + result->set_derivation(item->collation.derivation); + return result; default: // Dosen't have to be stored return 0; } @@ -9251,13 +9317,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, param->recinfo=recinfo; store_record(table,s->default_values); // Make empty default record - if (thd->variables.tmp_table_size == ~(ulong) 0) // No limit + if (thd->variables.tmp_table_size == ~ (ulonglong) 0) // No limit table->s->max_rows= ~(ha_rows) 0; else - table->s->max_rows= (((table->s->db_type == DB_TYPE_HEAP) ? - min(thd->variables.tmp_table_size, - thd->variables.max_heap_table_size) : - thd->variables.tmp_table_size)/ table->s->reclength); + table->s->max_rows= (ha_rows) (((table->s->db_type == DB_TYPE_HEAP) ? + min(thd->variables.tmp_table_size, + thd->variables.max_heap_table_size) : + thd->variables.tmp_table_size)/ + table->s->reclength); set_if_bigger(table->s->max_rows,1); // For dummy start options /* Push the LIMIT clause to the temporary table creation, so that we @@ -9559,7 +9626,7 @@ static bool open_tmp_table(TABLE *table) static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, - ulong options) + ulonglong options) { int error; MI_KEYDEF keydef; @@ -9965,7 +10032,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) if (join->result->send_eof()) rc= 1; // Don't send error } - DBUG_PRINT("info",("%ld records output",join->send_records)); + DBUG_PRINT("info",("%ld records output", (long) join->send_records)); } else rc= -1; @@ -10791,6 +10858,13 @@ join_init_quick_read_record(JOIN_TAB *tab) } +int rr_sequential(READ_RECORD *info); +int init_read_record_seq(JOIN_TAB *tab) +{ + tab->read_record.read_record= rr_sequential; + return tab->read_record.file->ha_rnd_init(1); +} + static int test_if_quick_select(JOIN_TAB *tab) { @@ -10919,7 +10993,7 @@ join_ft_read_next(READ_RECORD *info) Reading of key with key reference and one part that may be NULL */ -static int +int join_read_always_key_or_null(JOIN_TAB *tab) { int res; @@ -10935,7 +11009,7 @@ join_read_always_key_or_null(JOIN_TAB *tab) } -static int +int join_read_next_same_or_null(READ_RECORD *info) { int error; @@ -12203,6 +12277,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, /* Fill schema tables with data before filesort if it's necessary */ if ((join->select_lex->options & OPTION_SCHEMA_TABLE) && + !thd->lex->describe && get_schema_tables_result(join)) goto err; @@ -13531,9 +13606,16 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, if (real_pos->type() == Item::FIELD_ITEM) { Item_field *item; - pos= real_pos; - if (!(item= new Item_field(thd, ((Item_field*) pos)))) + if (!(item= new Item_field(thd, ((Item_field*) real_pos)))) goto err; + if (pos->type() == Item::REF_ITEM) + { + /* preserve the names of the ref when dereferncing */ + Item_ref *ref= (Item_ref *) pos; + item->db_name= ref->db_name; + item->table_name= ref->table_name; + item->name= ref->name; + } pos= item; if (item->field->flags & BLOB_FLAG) { diff --git a/sql/sql_select.h b/sql/sql_select.h index 30b8f834ddf..629b44538d8 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -36,6 +36,8 @@ typedef struct keyuse_t { satisfied if val has NULL 'value'. */ bool null_rejecting; + /* TRUE<=> This ref access is an outer subquery reference access */ + bool outer_ref; } KEYUSE; class store_key; @@ -455,10 +457,11 @@ class store_key :public Sql_alloc Field *to_field; // Store data here char *null_ptr; char err; - public: +public: + bool null_key; /* TRUE <=> the value of the key has a null part */ enum store_key_result { STORE_KEY_OK, STORE_KEY_FATAL, STORE_KEY_CONV }; store_key(THD *thd, Field *field_arg, char *ptr, char *null, uint length) - :null_ptr(null),err(0) + :null_ptr(null), err(0), null_key(0) { if (field_arg->type() == FIELD_TYPE_BLOB) { @@ -496,6 +499,7 @@ class store_key_field: public store_key enum store_key_result copy() { copy_field.do_copy(©_field); + null_key= to_field->is_null(); return err != 0 ? STORE_KEY_FATAL : STORE_KEY_OK; } const char *name() const { return field_name; } @@ -516,8 +520,8 @@ public: enum store_key_result copy() { int res= item->save_in_field(to_field, 1); + null_key= to_field->is_null() || item->null_value; return (err != 0 || res > 2 ? STORE_KEY_FATAL : (store_key_result) res); - } const char *name() const { return "func"; } }; @@ -547,6 +551,7 @@ public: err= res; } } + null_key= to_field->is_null() || item->null_value; return (err > 2 ? STORE_KEY_FATAL : (store_key_result) err); } const char *name() const { return "const"; } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index f107a57fe2b..ee310ea6fe4 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -464,7 +464,6 @@ bool mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create_info) { Security_context *sctx= thd->security_ctx; - int length; char buff[2048]; String buffer(buff, sizeof(buff), system_charset_info); #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -2367,7 +2366,6 @@ int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond) INDEX_FIELD_VALUES idx_field_vals; List<char> files; char *file_name; - uint length; bool with_i_schema; HA_CREATE_INFO create; TABLE *table= tables->table; @@ -2939,7 +2937,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, restore_record(table, s->default_values); if (!wild || !wild[0] || !wild_compare(sp_name.ptr(), wild, 0)) { - int enum_idx= proc_table->field[5]->val_int(); + int enum_idx= (int) proc_table->field[5]->val_int(); table->field[3]->store(sp_name.ptr(), sp_name.length(), cs); get_field(thd->mem_root, proc_table->field[3], &tmp_string); table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs); @@ -3105,7 +3103,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables, show_table->field[key_part->fieldnr-1]->key_length())) { table->field[10]->store((longlong) key_part->length / - key_part->field->charset()->mbmaxlen); + key_part->field->charset()->mbmaxlen, 1); table->field[10]->set_notnull(); } uint flags= key_part->field ? key_part->field->flags : 0; @@ -3979,7 +3977,7 @@ bool get_schema_tables_result(JOIN *join) table_list->table->file->extra(HA_EXTRA_RESET_STATE); table_list->table->file->delete_all_rows(); free_io_cache(table_list->table); - filesort_free_buffers(table_list->table); + filesort_free_buffers(table_list->table,1); table_list->table->null_row= 0; } else diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 7aaca809113..85ff1fddc45 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -854,6 +854,162 @@ outp: } +/* + copy a string, + with optional character set conversion, + with optional left padding (for binary -> UCS2 conversion) + + SYNOPSIS + well_formed_copy_nhars() + to Store result here + to_length Maxinum length of "to" string + to_cs Character set of "to" string + from Copy from here + from_length Length of from string + from_cs From character set + nchars Copy not more that nchars characters + well_formed_error_pos Return position when "from" is not well formed + or NULL otherwise. + cannot_convert_error_pos Return position where a not convertable + character met, or NULL otherwise. + from_end_pos Return position where scanning of "from" + string stopped. + NOTES + + RETURN + length of bytes copied to 'to' +*/ + + +uint32 +well_formed_copy_nchars(CHARSET_INFO *to_cs, + char *to, uint to_length, + CHARSET_INFO *from_cs, + const char *from, uint from_length, + uint nchars, + const char **well_formed_error_pos, + const char **cannot_convert_error_pos, + const char **from_end_pos) +{ + uint res; + + if ((to_cs == &my_charset_bin) || + (from_cs == &my_charset_bin) || + (to_cs == from_cs) || + my_charset_same(from_cs, to_cs)) + { + if (to_length < to_cs->mbminlen || !nchars) + { + *from_end_pos= from; + *cannot_convert_error_pos= NULL; + *well_formed_error_pos= NULL; + return 0; + } + + if (to_cs == &my_charset_bin) + { + res= min(min(nchars, to_length), from_length); + memmove(to, from, res); + *from_end_pos= from + res; + *well_formed_error_pos= NULL; + *cannot_convert_error_pos= NULL; + } + else + { + int well_formed_error; + uint from_offset; + + if ((from_offset= (from_length % to_cs->mbminlen)) && + (from_cs == &my_charset_bin)) + { + /* + Copying from BINARY to UCS2 needs to prepend zeros sometimes: + INSERT INTO t1 (ucs2_column) VALUES (0x01); + 0x01 -> 0x0001 + */ + uint pad_length= to_cs->mbminlen - from_offset; + bzero(to, pad_length); + memmove(to + pad_length, from, from_offset); + nchars--; + from+= from_offset; + from_length-= from_offset; + to+= to_cs->mbminlen; + to_length-= to_cs->mbminlen; + } + + set_if_smaller(from_length, to_length); + res= to_cs->cset->well_formed_len(to_cs, from, from + from_length, + nchars, &well_formed_error); + memmove(to, from, res); + *from_end_pos= from + res; + *well_formed_error_pos= well_formed_error ? from + res : NULL; + *cannot_convert_error_pos= NULL; + if (from_offset) + res+= to_cs->mbminlen; + } + } + else + { + int cnvres; + my_wc_t wc; + int (*mb_wc)(struct charset_info_st *, my_wc_t *, + const uchar *, const uchar *)= from_cs->cset->mb_wc; + int (*wc_mb)(struct charset_info_st *, my_wc_t, + uchar *s, uchar *e)= to_cs->cset->wc_mb; + const uchar *from_end= (const uchar*) from + from_length; + uchar *to_end= (uchar*) to + to_length; + char *to_start= to; + *well_formed_error_pos= NULL; + *cannot_convert_error_pos= NULL; + + for ( ; nchars; nchars--) + { + const char *from_prev= from; + if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, from_end)) > 0) + from+= cnvres; + else if (cnvres == MY_CS_ILSEQ) + { + if (!*well_formed_error_pos) + *well_formed_error_pos= from; + from++; + wc= '?'; + } + else if (cnvres > MY_CS_TOOSMALL) + { + /* + A correct multibyte sequence detected + But it doesn't have Unicode mapping. + */ + if (!*cannot_convert_error_pos) + *cannot_convert_error_pos= from; + from+= (-cnvres); + wc= '?'; + } + else + break; // Not enough characters + +outp: + if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0) + to+= cnvres; + else if (cnvres == MY_CS_ILUNI && wc != '?') + { + if (!*cannot_convert_error_pos) + *cannot_convert_error_pos= from_prev; + wc= '?'; + goto outp; + } + else + break; + } + *from_end_pos= from; + res= to - to_start; + } + return (uint32) res; +} + + + + void String::print(String *str) { char *st= (char*)Ptr, *end= st+str_length; diff --git a/sql/sql_string.h b/sql/sql_string.h index 0659f684afe..2be2cca5427 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -32,6 +32,14 @@ String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, const char *from, uint32 from_length, CHARSET_INFO *from_cs, uint *errors); +uint32 well_formed_copy_nchars(CHARSET_INFO *to_cs, + char *to, uint to_length, + CHARSET_INFO *from_cs, + const char *from, uint from_length, + uint nchars, + const char **well_formed_error_pos, + const char **cannot_convert_error_pos, + const char **from_end_pos); class String { @@ -355,3 +363,9 @@ public: return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length); } }; + +static inline bool check_if_only_end_space(CHARSET_INFO *cs, char *str, + char *end) +{ + return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end; +} diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1d71bf2497f..d036750de7f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -37,7 +37,9 @@ static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end); static int copy_data_between_tables(TABLE *from,TABLE *to, List<create_field> &create, bool ignore, uint order_num, ORDER *order, - ha_rows *copied,ha_rows *deleted); + ha_rows *copied,ha_rows *deleted, + enum enum_enable_or_disable keys_onoff); + static bool prepare_blob_field(THD *thd, create_field *sql_field); static bool check_engine(THD *thd, const char *table_name, enum db_type *new_engine); @@ -2267,7 +2269,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, goto send_result; } - table->table->pos_in_table_list= table; if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify) { char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE]; @@ -2935,6 +2936,54 @@ err: /* + Manages enabling/disabling of indexes for ALTER TABLE + + SYNOPSIS + alter_table_manage_keys() + table Target table + indexes_were_disabled Whether the indexes of the from table + were disabled + keys_onoff ENABLE | DISABLE | LEAVE_AS_IS + + RETURN VALUES + FALSE OK + TRUE Error +*/ + +static +bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, + enum enum_enable_or_disable keys_onoff) +{ + int error= 0; + DBUG_ENTER("alter_table_manage_keys"); + DBUG_PRINT("enter", ("table=%p were_disabled=%d on_off=%d", + table, indexes_were_disabled, keys_onoff)); + + switch (keys_onoff) { + case ENABLE: + error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + break; + case LEAVE_AS_IS: + if (!indexes_were_disabled) + break; + /* fall-through: disabled indexes */ + case DISABLE: + error= table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + } + + if (error == HA_ERR_WRONG_COMMAND) + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), table->s->table_name); + error= 0; + } else if (error) + table->file->print_error(error, MYF(0)); + + DBUG_RETURN(error); +} + + +/* Alter table */ @@ -3587,8 +3636,20 @@ view_err: new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; new_table->next_number_field=new_table->found_next_number_field; error=copy_data_between_tables(table, new_table, create_list, ignore, - order_num, order, &copied, &deleted); + order_num, order, &copied, &deleted, + alter_info->keys_onoff); } + else if (!new_table) + { + VOID(pthread_mutex_lock(&LOCK_open)); + wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + table->file->external_lock(thd, F_WRLCK); + alter_table_manage_keys(table, table->file->indexes_are_disabled(), + alter_info->keys_onoff); + table->file->external_lock(thd, F_UNLCK); + VOID(pthread_mutex_unlock(&LOCK_open)); + } + thd->last_insert_id=next_insert_id; // Needed for correct log thd->count_cuted_fields= CHECK_FIELD_IGNORE; @@ -3816,7 +3877,8 @@ copy_data_between_tables(TABLE *from,TABLE *to, bool ignore, uint order_num, ORDER *order, ha_rows *copied, - ha_rows *deleted) + ha_rows *deleted, + enum enum_enable_or_disable keys_onoff) { int error; Copy_field *copy,*copy_end; @@ -3849,6 +3911,9 @@ copy_data_between_tables(TABLE *from,TABLE *to, if (to->file->external_lock(thd, F_WRLCK)) DBUG_RETURN(-1); + /* We need external lock before we can disable/enable keys */ + alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff); + /* We can abort alter table for any table type */ thd->no_trans_update= 0; thd->abort_on_warning= !ignore && test(thd->variables.sql_mode & @@ -4061,8 +4126,6 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) } else { - t->pos_in_table_list= table; - if (t->file->table_flags() & HA_HAS_CHECKSUM && !(check_opt->flags & T_EXTEND)) protocol->store((ulonglong)t->file->checksum()); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 95734d31411..3569733d064 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -107,7 +107,9 @@ const LEX_STRING trg_event_type_names[]= }; -static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig); +static int +add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists, + TABLE_LIST ** table); class Handle_old_incorrect_sql_modes_hook: public Unknown_key_hook { @@ -156,6 +158,13 @@ private: */ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) { + /* + FIXME: The code below takes too many different paths depending on the + 'create' flag, so that the justification for a single function + 'mysql_create_or_drop_trigger', compared to two separate functions + 'mysql_create_trigger' and 'mysql_drop_trigger' is not apparent. + This is a good candidate for a minor refactoring. + */ TABLE *table; bool result= TRUE; String stmt_query; @@ -181,10 +190,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) DBUG_RETURN(TRUE); } - if (!create && - !(tables= add_table_for_trigger(thd, thd->lex->spname))) - DBUG_RETURN(TRUE); - /* We don't allow creating triggers on tables in the 'mysql' schema */ @@ -194,9 +199,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) DBUG_RETURN(TRUE); } - /* We should have only one table in table list. */ - DBUG_ASSERT(tables->next_global == 0); - /* TODO: We should check if user has TRIGGER privilege for table here. Now we just require SUPER privilege for creating/dropping because @@ -211,7 +213,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) 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. Because triggers have the same - nature as functions regarding binlogging: their body is implicitely + nature as functions regarding binlogging: their body is implicitly binlogged, so they share the same danger, so trust_function_creators applies to them too. */ @@ -222,24 +224,52 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) DBUG_RETURN(TRUE); } - /* We do not allow creation of triggers on temporary tables. */ - if (create && find_temporary_table(thd, tables->db, tables->table_name)) - { - my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias); - DBUG_RETURN(TRUE); - } - /* We don't want perform our operations while global read lock is held - so we have to wait until its end and then prevent it from occuring + so we have to wait until its end and then prevent it from occurring again until we are done. (Acquiring LOCK_open is not enough because - global read lock is held without helding LOCK_open). + global read lock is held without holding LOCK_open). */ if (wait_if_global_read_lock(thd, 0, 1)) DBUG_RETURN(TRUE); VOID(pthread_mutex_lock(&LOCK_open)); + if (!create) + { + bool if_exists= thd->lex->drop_if_exists; + + if (add_table_for_trigger(thd, thd->lex->spname, if_exists, & tables)) + goto end; + + if (!tables) + { + DBUG_ASSERT(if_exists); + /* + Since the trigger does not exist, there is no associated table, + and therefore : + - no TRIGGER privileges to check, + - no trigger to drop, + - no table to lock/modify, + so the drop statement is successful. + */ + result= FALSE; + /* Still, we need to log the query ... */ + stmt_query.append(thd->query, thd->query_length); + goto end; + } + } + + /* We should have only one table in table list. */ + DBUG_ASSERT(tables->next_global == 0); + + /* We do not allow creation of triggers on temporary tables. */ + if (create && find_temporary_table(thd, tables->db, tables->table_name)) + { + my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias); + goto end; + } + if (lock_table_names(thd, tables)) goto end; @@ -326,7 +356,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, char dir_buff[FN_REFLEN], file_buff[FN_REFLEN], trigname_buff[FN_REFLEN], trigname_path[FN_REFLEN]; LEX_STRING dir, file, trigname_file; - LEX_STRING *trg_def, *name; + LEX_STRING *trg_def; LEX_STRING definer_user; LEX_STRING definer_host; ulonglong *trg_sql_mode; @@ -849,7 +879,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, DBUG_RETURN(1); List_iterator_fast<LEX_STRING> it(triggers->definitions_list); - LEX_STRING *trg_create_str, *trg_name_str; + LEX_STRING *trg_create_str; ulonglong *trg_sql_mode; if (triggers->definition_modes_list.is_empty() && @@ -966,7 +996,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, goto err_with_lex_cleanup; } - lex.sphead->set_info(0, 0, &lex.sp_chistics, *trg_sql_mode); + lex.sphead->set_info(0, 0, &lex.sp_chistics, (ulong) *trg_sql_mode); triggers->bodies[lex.trg_chistics.event] [lex.trg_chistics.action_time]= lex.sphead; @@ -1145,13 +1175,17 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event, mysql_table_for_trigger() thd - current thread context trig - identifier for trigger + if_exists - treat a not existing trigger as a warning if TRUE + table - pointer to TABLE_LIST object for the table trigger (output) RETURN VALUE - 0 - error - # - pointer to TABLE_LIST object for the table + 0 Success + 1 Error */ -static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) +static int +add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists, + TABLE_LIST **table) { LEX *lex= thd->lex; char path_buff[FN_REFLEN]; @@ -1162,6 +1196,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) path_buff, &trigname.trigger_table); DBUG_ENTER("add_table_for_trigger"); + DBUG_ASSERT(table != NULL); strxnmov(path_buff, FN_REFLEN, mysql_data_home, "/", trig->m_db.str, "/", trig->m_name.str, trigname_file_ext, NullS); @@ -1170,30 +1205,45 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) if (access(path_buff, F_OK)) { + if (if_exists) + { + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_TRG_DOES_NOT_EXIST, + ER(ER_TRG_DOES_NOT_EXIST)); + *table= NULL; + DBUG_RETURN(0); + } + my_error(ER_TRG_DOES_NOT_EXIST, MYF(0)); - DBUG_RETURN(0); + DBUG_RETURN(1); } if (!(parser= sql_parse_prepare(&path, thd->mem_root, 1))) - DBUG_RETURN(0); + DBUG_RETURN(1); if (!is_equal(&trigname_file_type, parser->type())) { my_error(ER_WRONG_OBJECT, MYF(0), trig->m_name.str, trigname_file_ext+1, "TRIGGERNAME"); - DBUG_RETURN(0); + DBUG_RETURN(1); } if (parser->parse((gptr)&trigname, thd->mem_root, trigname_file_parameters, 1, &trigger_table_hook)) - DBUG_RETURN(0); + DBUG_RETURN(1); /* 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, trig->m_db.str, - trigname.trigger_table.str, TL_IGNORE)); + *table= sp_add_to_query_tables(thd, lex, trig->m_db.str, + trigname.trigger_table.str, TL_IGNORE); + + if (! *table) + DBUG_RETURN(1); + + DBUG_RETURN(0); } @@ -1287,7 +1337,6 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, { char path_buff[FN_REFLEN]; LEX_STRING *def, *on_table_name, new_def; - ulonglong *sql_mode; ulong save_sql_mode= thd->variables.sql_mode; List_iterator_fast<LEX_STRING> it_def(definitions_list); List_iterator_fast<LEX_STRING> it_on_table_name(on_table_names_list); @@ -1301,7 +1350,7 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, while ((def= it_def++)) { on_table_name= it_on_table_name++; - thd->variables.sql_mode= *(it_mode++); + thd->variables.sql_mode= (ulong) *(it_mode++); /* Construct CREATE TRIGGER statement with new table name. */ buff.length(0); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index d431b671f18..3b6aa5f1aa2 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -118,7 +118,7 @@ int mysql_update(THD *thd, enum enum_duplicates handle_duplicates, bool ignore) { bool using_limit= limit != HA_POS_ERROR; - bool safe_update= thd->options & OPTION_SAFE_UPDATES; + bool safe_update= test(thd->options & OPTION_SAFE_UPDATES); bool used_key_is_modified, transactional_table; bool can_compare_record; int res; @@ -569,7 +569,7 @@ int mysql_update(THD *thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; send_ok(thd, (ulong) thd->row_count_func, thd->insert_id_used ? thd->last_insert_id : 0L,buff); - DBUG_PRINT("info",("%d records updated",updated)); + DBUG_PRINT("info",("%ld records updated", (long) updated)); } thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */ thd->abort_on_warning= 0; @@ -667,7 +667,7 @@ static table_map get_table_map(List<Item> *items) while ((item= (Item_field *) item_it++)) map|= item->used_tables(); - DBUG_PRINT("info",("table_map: 0x%08x", map)); + DBUG_PRINT("info", ("table_map: 0x%08lx", (long) map)); return map; } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 52b6c2c38c0..53844eb0fd2 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -197,7 +197,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) lex->definer= &view->definer; } if (lex->create_view_algorithm == VIEW_ALGORITHM_UNDEFINED) - lex->create_view_algorithm= decoy.algorithm; + lex->create_view_algorithm= (uint8) decoy.algorithm; if (lex->create_view_suid == VIEW_SUID_DEFAULT) lex->create_view_suid= decoy.view_suid ? VIEW_SUID_DEFINER : VIEW_SUID_INVOKER; @@ -563,7 +563,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, LEX_STRING *name; int i; - for (i= 0; name= names++; i++) + for (i= 0; (name= names++); i++) { buff.append(i ? ", " : "("); append_identifier(thd, &buff, name->str, name->length); @@ -1477,7 +1477,6 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) TABLE *table; Field_translator *trans, *end_of_trans; KEY *key_info, *key_info_end; - uint i; DBUG_ENTER("check_key_in_view"); /* diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6f24a42c07c..a362d1ce4ea 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -761,7 +761,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <item_list> expr_list udf_expr_list udf_expr_list2 when_list - ident_list ident_list_arg + ident_list ident_list_arg opt_expr_list %type <var_type> option_type opt_var_type opt_var_ident_type @@ -1626,7 +1626,6 @@ sp_decl: uint num_vars= pctx->context_var_count(); 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) { @@ -4701,7 +4700,7 @@ simple_expr: { $$= new Item_func_trim($5,$3); } | TRUNCATE_SYM '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,1); } - | ident '.' ident '(' udf_expr_list ')' + | ident '.' ident '(' opt_expr_list ')' { LEX *lex= Lex; sp_name *name= new sp_name($1, $3); @@ -4718,27 +4717,27 @@ simple_expr: { #ifdef HAVE_DLOPEN udf_func *udf= 0; + LEX *lex= Lex; if (using_udf_functions && (udf= find_udf($1.str, $1.length)) && udf->type == UDFTYPE_AGGREGATE) { - LEX *lex= Lex; if (lex->current_select->inc_in_sum_expr()) { yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } } - $<udf>$= udf; + lex->current_select->udf_list.push_front(udf); #endif } udf_expr_list ')' { #ifdef HAVE_DLOPEN - udf_func *udf= $<udf>3; - SELECT_LEX *sel= Select; + udf_func *udf; + LEX *lex= Lex; - if (udf) + if (NULL != (udf= lex->current_select->udf_list.pop())) { if (udf->type == UDFTYPE_AGGREGATE) Select->in_sum_expr--; @@ -4965,12 +4964,29 @@ udf_expr_list3: udf_expr: remember_name expr remember_end select_alias { + udf_func *udf= Select->udf_list.head(); + /* + Use Item::name as a storage for the attribute value of user + defined function argument. It is safe to use Item::name + because the syntax will not allow having an explicit name here. + See WL#1017 re. udf attributes. + */ if ($4.str) { + if (!udf) + { + /* + Disallow using AS to specify explicit names for the arguments + of stored routine calls + */ + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } + $2->is_autogenerated_name= FALSE; $2->set_name($4.str, $4.length, system_charset_info); } - else + else if (udf) $2->set_name($1, (uint) ($3 - $1), YYTHD->charset()); $$= $2; } @@ -5131,6 +5147,11 @@ cast_type: | DECIMAL_SYM float_options { $$=ITEM_CAST_DECIMAL; Lex->charset= NULL; } ; +opt_expr_list: + /* empty */ { $$= NULL; } + | expr_list { $$= $1;} + ; + expr_list: { Select->expr_list.push_front(new List<Item>); } expr_list2 @@ -6098,11 +6119,12 @@ drop: lex->sql_command= SQLCOM_DROP_VIEW; lex->drop_if_exists= $3; } - | DROP TRIGGER_SYM sp_name + | DROP TRIGGER_SYM if_exists sp_name { LEX *lex= Lex; lex->sql_command= SQLCOM_DROP_TRIGGER; - lex->spname= $3; + lex->drop_if_exists= $3; + lex->spname= $4; } ; @@ -7031,6 +7053,8 @@ load_data_lock: Ignore this option in SP to avoid problem with query cache */ if (Lex->sphead != 0) + $$= YYTHD->update_lock_default; + else #endif $$= TL_WRITE_CONCURRENT_INSERT; } diff --git a/sql/strfunc.cc b/sql/strfunc.cc index c822d10af46..d03d88ee051 100644 --- a/sql/strfunc.cc +++ b/sql/strfunc.cc @@ -150,7 +150,7 @@ uint find_type2(TYPELIB *typelib, const char *x, uint length, CHARSET_INFO *cs) int pos; const char *j; DBUG_ENTER("find_type2"); - DBUG_PRINT("enter",("x: '%.*s' lib: 0x%lx", length, x, typelib)); + DBUG_PRINT("enter",("x: '%.*s' lib: 0x%lx", length, x, (long) typelib)); if (!typelib->count) { diff --git a/sql/table.cc b/sql/table.cc index d72379efb32..1305ed9cc24 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -88,7 +88,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, MEM_ROOT **root_ptr, *old_root; TABLE_SHARE *share; DBUG_ENTER("openfrm"); - DBUG_PRINT("enter",("name: '%s' form: 0x%lx",name,outparam)); + DBUG_PRINT("enter",("name: '%s' form: 0x%lx", name, (long) outparam)); error= 1; disk_buff= NULL; @@ -730,6 +730,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, if (key_part->fieldnr) { // Should always be true ! Field *field=key_part->field=outparam->field[key_part->fieldnr-1]; + key_part->type= field->key_type(); if (field->null_ptr) { key_part->null_offset=(uint) ((byte*) field->null_ptr - @@ -2458,7 +2459,18 @@ bool st_table_list::prepare_view_securety_context(THD *thd) } else { - my_error(ER_NO_SUCH_USER, MYF(0), definer.user.str, definer.host.str); + if (thd->security_ctx->master_access & SUPER_ACL) + { + my_error(ER_NO_SUCH_USER, MYF(0), definer.user.str, definer.host.str); + + } + else + { + my_error(ER_ACCESS_DENIED_ERROR, MYF(0), + thd->security_ctx->priv_user, + thd->security_ctx->priv_host, + (thd->password ? ER(ER_YES) : ER(ER_NO))); + } DBUG_RETURN(TRUE); } } @@ -3032,6 +3044,23 @@ void st_table_list::reinit_before_use(THD *thd) embedding->nested_join->join_list.head() == embedded); } +/* + Return subselect that contains the FROM list this table is taken from + + SYNOPSIS + st_table_list::containing_subselect() + + RETURN + Subselect item for the subquery that contains the FROM list + this table is taken from if there is any + 0 - otherwise + +*/ + +Item_subselect *st_table_list::containing_subselect() +{ + return (select_lex ? select_lex->master_unit()->item : 0); +} /***************************************************************************** ** Instansiate templates diff --git a/sql/table.h b/sql/table.h index 5136ac2c4db..f0190353328 100644 --- a/sql/table.h +++ b/sql/table.h @@ -18,6 +18,7 @@ /* Structs that defines the TABLE */ class Item; /* Needed by ORDER */ +class Item_subselect; class GRANT_TABLE; class st_select_lex_unit; class st_select_lex; @@ -68,6 +69,9 @@ enum frm_type_enum typedef struct st_filesort_info { IO_CACHE *io_cache; /* If sorted through filebyte */ + uchar **sort_keys; /* Buffer for sorting keys */ + byte *buffpek; /* Buffer for buffpek structures */ + uint buffpek_len; /* Max number of buffpeks in the buffer */ byte *addon_buf; /* Pointer to a buffer if sorted with fields */ uint addon_length; /* Length of the buffer */ struct st_sort_addon_field *addon_field; /* Pointer to the fields info */ @@ -678,6 +682,7 @@ typedef struct st_table_list procedure. */ void reinit_before_use(THD *thd); + Item_subselect *containing_subselect(); private: bool prep_check_option(THD *thd, uint8 check_opt_type); diff --git a/sql/tztime.cc b/sql/tztime.cc index bd8e43075c4..4becf4a9fcc 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -949,13 +949,12 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, */ if (shift) { - if (local_t > (TIMESTAMP_MAX_VALUE - shift*86400L + - sp->revtis[i].rt_offset - saved_seconds)) + if (local_t > (my_time_t) (TIMESTAMP_MAX_VALUE - shift*86400L + + sp->revtis[i].rt_offset - saved_seconds)) { DBUG_RETURN(0); /* my_time_t overflow */ } - else - local_t+= shift*86400L; + local_t+= shift*86400L; } if (sp->revtis[i].rt_type) @@ -1730,9 +1729,9 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) tz_leapcnt++; DBUG_PRINT("info", - ("time_zone_leap_second table: tz_leapcnt=%u tt_time=%lld offset=%ld", - tz_leapcnt, (longlong)tz_lsis[tz_leapcnt-1].ls_trans, - tz_lsis[tz_leapcnt-1].ls_corr)); + ("time_zone_leap_second table: tz_leapcnt: %u tt_time: %lu offset=%ld", + tz_leapcnt, (ulong) tz_lsis[tz_leapcnt-1].ls_trans, + tz_lsis[tz_leapcnt-1].ls_corr)); res= table->file->index_next(table->record[0]); } @@ -2042,8 +2041,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) tz_info->timecnt++; DBUG_PRINT("info", - ("time_zone_transition table: tz_id=%u tt_time=%lld tt_id=%u", - tzid, (longlong)ttime, ttid)); + ("time_zone_transition table: tz_id: %u tt_time: %lu tt_id: %u", + tzid, (ulong) ttime, ttid)); res= table->file->index_next_same(table->record[0], (byte*)table->field[0]->ptr, 4); diff --git a/sql/udf_example.c b/sql/udf_example.c index a4f7eddd302..bbab47e253d 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1087,12 +1087,13 @@ my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message) strmov(message, "IS_CONST accepts only one argument"); return 1; } - initid->ptr= (args->args[0] != NULL) ? 1 : 0; + initid->ptr= (char*)((args->args[0] != NULL) ? 1 : 0); return 0; } -char * is_const(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long - *length, char *is_null, char *error) +char * is_const(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), + char *result, unsigned long *length, + char *is_null, char *error __attribute__((unused))) { if (initid->ptr != 0) { sprintf(result, "const"); diff --git a/sql/uniques.cc b/sql/uniques.cc index ad074f8b2b0..c7bdbdeb207 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -55,18 +55,19 @@ int unique_write_to_ptrs(gptr key, element_count count, Unique *unique) } Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg, - uint size_arg, ulong max_in_memory_size_arg) + uint size_arg, ulonglong max_in_memory_size_arg) :max_in_memory_size(max_in_memory_size_arg), size(size_arg), elements(0) { my_b_clear(&file); - init_tree(&tree, max_in_memory_size / 16, 0, size, comp_func, 0, NULL, - comp_func_fixed_arg); + init_tree(&tree, (ulong) (max_in_memory_size / 16), 0, size, comp_func, 0, + NULL, comp_func_fixed_arg); /* If the following fail's the next add will also fail */ my_init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16); /* If you change the following, change it in get_max_elements function, too. */ - max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size); + max_elements= (ulong) (max_in_memory_size / + ALIGN_SIZE(sizeof(TREE_ELEMENT)+size)); VOID(open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME))); } @@ -260,15 +261,15 @@ static double get_merge_many_buffs_cost(uint *buffer, */ double Unique::get_use_cost(uint *buffer, uint nkeys, uint key_size, - ulong max_in_memory_size) + ulonglong max_in_memory_size) { ulong max_elements_in_tree; ulong last_tree_elems; int n_full_trees; /* number of trees in unique - 1 */ double result; - max_elements_in_tree= - max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size); + max_elements_in_tree= ((ulong) max_in_memory_size / + ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size)); n_full_trees= nkeys / max_elements_in_tree; last_tree_elems= nkeys % max_elements_in_tree; @@ -386,9 +387,11 @@ C_MODE_END /* DESCRIPTION + Function is very similar to merge_buffers, but instead of writing sorted unique keys to the output file, it invokes walk_action for each key. This saves I/O if you need to pass through all unique keys only once. + SYNOPSIS merge_walk() All params are 'IN' (but see comment for begin, end): @@ -416,7 +419,7 @@ C_MODE_END <> 0 error */ -static bool merge_walk(uchar *merge_buffer, uint merge_buffer_size, +static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size, uint key_length, BUFFPEK *begin, BUFFPEK *end, tree_walk_action walk_action, void *walk_action_arg, qsort_cmp2 compare, void *compare_arg, @@ -425,14 +428,15 @@ static bool merge_walk(uchar *merge_buffer, uint merge_buffer_size, BUFFPEK_COMPARE_CONTEXT compare_context = { compare, compare_arg }; QUEUE queue; if (end <= begin || - merge_buffer_size < key_length * (end - begin + 1) || - init_queue(&queue, end - begin, offsetof(BUFFPEK, key), 0, + merge_buffer_size < (ulong) (key_length * (end - begin + 1)) || + init_queue(&queue, (uint) (end - begin), offsetof(BUFFPEK, key), 0, buffpek_compare, &compare_context)) return 1; /* we need space for one key when a piece of merge buffer is re-read */ merge_buffer_size-= key_length; uchar *save_key_buff= merge_buffer + merge_buffer_size; - uint max_key_count_per_piece= merge_buffer_size/(end-begin)/key_length; + uint max_key_count_per_piece= (uint) (merge_buffer_size/(end-begin) / + key_length); /* if piece_size is aligned reuse_freed_buffer will always hit */ uint piece_size= max_key_count_per_piece * key_length; uint bytes_read; /* to hold return value of read_to_buffer */ @@ -548,6 +552,9 @@ end: bool Unique::walk(tree_walk_action action, void *walk_action_arg) { + int res; + uchar *merge_buffer; + if (elements == 0) /* the whole tree is in memory */ return tree_walk(&tree, action, walk_action_arg, left_root_right); @@ -556,15 +563,14 @@ bool Unique::walk(tree_walk_action action, void *walk_action_arg) return 1; if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0)) return 1; - uchar *merge_buffer= (uchar *) my_malloc(max_in_memory_size, MYF(0)); - if (merge_buffer == 0) + if (!(merge_buffer= (uchar *) my_malloc((ulong) max_in_memory_size, MYF(0)))) return 1; - int res= merge_walk(merge_buffer, max_in_memory_size, size, - (BUFFPEK *) file_ptrs.buffer, - (BUFFPEK *) file_ptrs.buffer + file_ptrs.elements, - action, walk_action_arg, - tree.compare, tree.custom_arg, &file); - x_free(merge_buffer); + res= merge_walk(merge_buffer, (ulong) max_in_memory_size, size, + (BUFFPEK *) file_ptrs.buffer, + (BUFFPEK *) file_ptrs.buffer + file_ptrs.elements, + action, walk_action_arg, + tree.compare, tree.custom_arg, &file); + my_free((char*) merge_buffer, MYF(0)); return res; } @@ -615,7 +621,7 @@ bool Unique::get(TABLE *table) sort_param.sort_form=table; sort_param.rec_length= sort_param.sort_length= sort_param.ref_length= size; - sort_param.keys= max_in_memory_size / sort_param.sort_length; + sort_param.keys= (uint) (max_in_memory_size / sort_param.sort_length); sort_param.not_killable=1; if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) * diff --git a/sql/unireg.cc b/sql/unireg.cc index 768a288ca19..8568b09e498 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -394,16 +394,16 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, pos[6]=pos[7]=0; // For the future pos+=8; key_parts+=key->key_parts; - DBUG_PRINT("loop",("flags: %d key_parts: %d at 0x%lx", - key->flags,key->key_parts, - key->key_part)); + DBUG_PRINT("loop", ("flags: %d key_parts: %d at 0x%lx", + key->flags, key->key_parts, + (long) key->key_part)); for (key_part=key->key_part,key_part_end=key_part+key->key_parts ; key_part != key_part_end ; key_part++) { uint offset; - DBUG_PRINT("loop",("field: %d startpos: %lu length: %ld", + DBUG_PRINT("loop",("field: %d startpos: %lu length: %d", key_part->fieldnr, key_part->offset + data_offset, key_part->length)); int2store(pos,key_part->fieldnr+1+FIELD_NAME_USED); diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 0bd5a1fda76..3e8b05580f6 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -211,9 +211,10 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)), /* This function is used for all conversion functions */ -static void my_case_str_bin(CHARSET_INFO *cs __attribute__((unused)), +static uint my_case_str_bin(CHARSET_INFO *cs __attribute__((unused)), char *str __attribute__((unused))) { + return 0; } static uint my_case_bin(CHARSET_INFO *cs __attribute__((unused)), diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 394111be3bc..3ef245015d7 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -21,40 +21,44 @@ #ifdef USE_MB -void my_caseup_str_mb(CHARSET_INFO * cs, char *str) +uint my_caseup_str_mb(CHARSET_INFO * cs, char *str) { register uint32 l; - register uchar *map=cs->to_upper; + register uchar *map= cs->to_upper; + char *str_orig= str; while (*str) { /* Pointing after the '\0' is safe here. */ - if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen))) - str+=l; + if ((l= my_ismbchar(cs, str, str + cs->mbmaxlen))) + str+= l; else { - *str=(char) map[(uchar)*str]; + *str= (char) map[(uchar)*str]; str++; } } + return str - str_orig; } -void my_casedn_str_mb(CHARSET_INFO * cs, char *str) +uint my_casedn_str_mb(CHARSET_INFO * cs, char *str) { register uint32 l; - register uchar *map=cs->to_lower; + register uchar *map= cs->to_lower; + char *str_orig= str; while (*str) { /* Pointing after the '\0' is safe here. */ - if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen))) - str+=l; + if ((l= my_ismbchar(cs, str, str + cs->mbmaxlen))) + str+= l; else { - *str=(char) map[(uchar)*str]; + *str= (char) map[(uchar)*str]; str++; } } + return str - str_orig; } uint my_caseup_mb(CHARSET_INFO * cs, char *src, uint srclen, diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index e40a1948dcf..fc9cbfc9d21 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -188,20 +188,26 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length, } -void my_caseup_str_8bit(CHARSET_INFO * cs,char *str) +uint my_caseup_str_8bit(CHARSET_INFO * cs,char *str) { - register uchar *map=cs->to_upper; - while ((*str = (char) map[(uchar) *str]) != 0) + register uchar *map= cs->to_upper; + char *str_orig= str; + while ((*str= (char) map[(uchar) *str]) != 0) str++; + return str - str_orig; } -void my_casedn_str_8bit(CHARSET_INFO * cs,char *str) + +uint my_casedn_str_8bit(CHARSET_INFO * cs,char *str) { - register uchar *map=cs->to_lower; - while ((*str = (char) map[(uchar)*str]) != 0) + register uchar *map= cs->to_lower; + char *str_orig= str; + while ((*str= (char) map[(uchar) *str]) != 0) str++; + return str - str_orig; } + uint my_caseup_8bit(CHARSET_INFO * cs, char *src, uint srclen, char *dst __attribute__((unused)), uint dstlen __attribute__((unused))) @@ -1497,7 +1503,7 @@ my_strntoull10rnd_8bit(CHARSET_INFO *cs __attribute__((unused)), else { *error= 0; - return (ulonglong) (longlong) (long) -ul; + return (ulonglong) (longlong) -(long) ul; } } else @@ -1648,7 +1654,7 @@ ret_sign: return (ulonglong) LONGLONG_MIN; } *error= 0; - return (ulonglong) -ull; + return (ulonglong) -(longlong) ull; } else { diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 4a60220f73e..3c69a314b45 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -159,13 +159,13 @@ static void my_hash_sort_ucs2(CHARSET_INFO *cs, const uchar *s, uint slen, } -static void my_caseup_str_ucs2(CHARSET_INFO * cs __attribute__((unused)), +static uint my_caseup_str_ucs2(CHARSET_INFO * cs __attribute__((unused)), char * s __attribute__((unused))) { + return 0; } - static uint my_casedn_ucs2(CHARSET_INFO *cs, char *src, uint srclen, char *dst __attribute__((unused)), uint dstlen __attribute__((unused))) @@ -188,9 +188,11 @@ static uint my_casedn_ucs2(CHARSET_INFO *cs, char *src, uint srclen, return srclen; } -static void my_casedn_str_ucs2(CHARSET_INFO *cs __attribute__((unused)), + +static uint my_casedn_str_ucs2(CHARSET_INFO *cs __attribute__((unused)), char * s __attribute__((unused))) { + return 0; } diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index ae2c04fb068..a21fe4961ec 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2045,6 +2045,52 @@ static int my_utf8_uni(CHARSET_INFO *cs __attribute__((unused)), return MY_CS_ILSEQ; } + +/* + The same as above, but without range check + for example, for a null-terminated string +*/ +static int my_utf8_uni_no_range(CHARSET_INFO *cs __attribute__((unused)), + my_wc_t * pwc, const uchar *s) +{ + unsigned char c; + + c= s[0]; + if (c < 0x80) + { + *pwc = c; + return 1; + } + + if (c < 0xc2) + return MY_CS_ILSEQ; + + if (c < 0xe0) + { + if (!((s[1] ^ 0x80) < 0x40)) + return MY_CS_ILSEQ; + + *pwc = ((my_wc_t) (c & 0x1f) << 6) | (my_wc_t) (s[1] ^ 0x80); + return 2; + } + + if (c < 0xf0) + { + if (!((s[1] ^ 0x80) < 0x40 && + (s[2] ^ 0x80) < 0x40 && + (c >= 0xe1 || s[1] >= 0xa0))) + return MY_CS_ILSEQ; + + *pwc= ((my_wc_t) (c & 0x0f) << 12) | + ((my_wc_t) (s[1] ^ 0x80) << 6) | + (my_wc_t) (s[2] ^ 0x80); + + return 3; + } + return MY_CS_ILSEQ; +} + + static int my_uni_utf8 (CHARSET_INFO *cs __attribute__((unused)) , my_wc_t wc, uchar *r, uchar *e) { @@ -2091,6 +2137,34 @@ static int my_uni_utf8 (CHARSET_INFO *cs __attribute__((unused)) , } +/* + The same as above, but without range check. +*/ +static int my_uni_utf8_no_range(CHARSET_INFO *cs __attribute__((unused)), + my_wc_t wc, uchar *r) +{ + int count; + + if (wc < 0x80) + count= 1; + else if (wc < 0x800) + count= 2; + else if (wc < 0x10000) + count= 3; + else + return MY_CS_ILUNI; + + switch (count) + { + /* Fall through all cases!!! */ + case 3: r[2]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0x800; + case 2: r[1]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0xc0; + case 1: r[0]= (uchar) wc; + } + return count; +} + + static uint my_caseup_utf8(CHARSET_INFO *cs, char *src, uint srclen, char *dst, uint dstlen) { @@ -2141,10 +2215,26 @@ static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen, } -static void my_caseup_str_utf8(CHARSET_INFO * cs, char * s) +static uint my_caseup_str_utf8(CHARSET_INFO *cs, char *src) { - uint len= (uint) strlen(s); - my_caseup_utf8(cs, s, len, s, len); + my_wc_t wc; + int srcres, dstres; + char *dst= src, *dst0= src; + MY_UNICASE_INFO **uni_plane= cs->caseinfo; + DBUG_ASSERT(cs->caseup_multiply == 1); + + while (*src && + (srcres= my_utf8_uni_no_range(cs, &wc, (uchar *) src)) > 0) + { + int plane= (wc>>8) & 0xFF; + wc= uni_plane[plane] ? uni_plane[plane][wc & 0xFF].toupper : wc; + if ((dstres= my_uni_utf8_no_range(cs, wc, (uchar*) dst)) <= 0) + break; + src+= srcres; + dst+= dstres; + } + *dst= '\0'; + return (uint) (dst - dst0); } @@ -2170,10 +2260,43 @@ static uint my_casedn_utf8(CHARSET_INFO *cs, char *src, uint srclen, return (uint) (dst - dst0); } -static void my_casedn_str_utf8(CHARSET_INFO *cs, char * s) + +static uint my_casedn_str_utf8(CHARSET_INFO *cs, char *src) { - uint len= (uint) strlen(s); - my_casedn_utf8(cs, s, len, s, len); + my_wc_t wc; + int srcres, dstres; + char *dst= src, *dst0= src; + MY_UNICASE_INFO **uni_plane= cs->caseinfo; + DBUG_ASSERT(cs->casedn_multiply == 1); + + while (*src && + (srcres= my_utf8_uni_no_range(cs, &wc, (uchar *) src)) > 0) + { + int plane= (wc>>8) & 0xFF; + wc= uni_plane[plane] ? uni_plane[plane][wc & 0xFF].tolower : wc; + if ((dstres= my_uni_utf8_no_range(cs, wc, (uchar*) dst)) <= 0) + break; + src+= srcres; + dst+= dstres; + } + + /* + In rare cases lower string can be shorter than + the original string, for example: + + "U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE" + (which is 0xC4B0 in utf8, i.e. two bytes) + + is converted into + + "U+0069 LATIN SMALL LETTER I" + (which is 0x69 in utf8, i.e. one byte) + + So, we need to put '\0' terminator after converting. + */ + + *dst= '\0'; + return (uint) (dst - dst0); } diff --git a/strings/decimal.c b/strings/decimal.c index 5a0bc0968b6..6b7a2266194 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1036,7 +1036,7 @@ int decimal2ulonglong(decimal_t *from, ulonglong *to) x=x*DIG_BASE + *buf++; if (unlikely(y > ((ulonglong) ULONGLONG_MAX/DIG_BASE) || x < y)) { - *to=y; + *to=ULONGLONG_MAX; return E_DEC_OVERFLOW; } } @@ -1348,7 +1348,7 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) } from+=i; *buf=x ^ mask; - if (((uint32)*buf) >= powers10[intg0x+1]) + if (((ulonglong)*buf) >= (ulonglong) powers10[intg0x+1]) goto err; if (buf > to->buf || *buf != 0) buf++; diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index eefc4f55d35..6000773144c 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -194,6 +194,8 @@ necessary to develop MySQL client applications. %package shared Summary: MySQL - Shared libraries Group: Applications/Databases +Provides: mysql-shared +Obsoletes: mysql-shared %description shared This package contains the shared libraries (*.so*) which certain @@ -342,7 +344,10 @@ then cp -fp config.log "$MYSQL_MAXCONFLOG_DEST" fi -make -i test-force-pl || true +( cd mysql-test + perl ./mysql-test-run.pl --force --report-features + perl ./mysql-test-run.pl --force --ps-protocol + true ) # Save mysqld-max ./libtool --mode=execute cp sql/mysqld sql/mysqld-max @@ -401,7 +406,10 @@ then cp -fp config.log "$MYSQL_CONFLOG_DEST" fi -make -i test-force-pl || true +( cd mysql-test + perl ./mysql-test-run.pl --force --report-features + perl ./mysql-test-run.pl --force --ps-protocol + true ) %install RBR=$RPM_BUILD_ROOT @@ -745,6 +753,17 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Thu Nov 16 2006 Joerg Bruehe <joerg@mysql.com> + +- Explicitly note that the "MySQL-shared" RPMs (as built by MySQL AB) + replace "mysql-shared" (as distributed by SuSE) to allow easy upgrading + (bug#22081). + +* Wed Nov 15 2006 Joerg Bruehe <joerg@mysql.com> + +- Switch from "make test*" to explicit calls of the test suite, + so that "report features" can be used. + * Mon Jul 10 2006 Joerg Bruehe <joerg@mysql.com> - Fix a typing error in the "make" target for the Perl script to run the tests. diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index da7fde469ad..c596a589d55 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13686,7 +13686,8 @@ static void test_bug11172() hired.year, hired.month, hired.day); } DIE_UNLESS(rc == MYSQL_NO_DATA); - mysql_stmt_free_result(stmt) || mysql_stmt_reset(stmt); + if (!mysql_stmt_free_result(stmt)) + mysql_stmt_reset(stmt); } mysql_stmt_close(stmt); mysql_rollback(mysql); @@ -14828,6 +14829,8 @@ static void test_opt_reconnect() } +#ifndef EMBEDDED_LIBRARY + static void test_bug12744() { MYSQL_STMT *prep_stmt = NULL; @@ -14859,6 +14862,8 @@ static void test_bug12744() client_connect(0); } +#endif /* EMBEDDED_LIBRARY */ + /* Bug #16143: mysql_stmt_sqlstate returns an empty string instead of '00000' */ static void test_bug16143() @@ -15308,6 +15313,151 @@ static void test_bug21726() /* + BUG#23383: mysql_affected_rows() returns different values than + mysql_stmt_affected_rows() + + Test that both mysql_affected_rows() and mysql_stmt_affected_rows() + return -1 on error, 0 when no rows were affected, and (positive) row + count when some rows were affected. +*/ +static void test_bug23383() +{ + const char *insert_query= "INSERT INTO t1 VALUES (1), (2)"; + const char *update_query= "UPDATE t1 SET i= 4 WHERE i = 3"; + MYSQL_STMT *stmt; + my_ulonglong row_count; + int rc; + + DBUG_ENTER("test_bug23383"); + myheader("test_bug23383"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t1 (i INT UNIQUE)"); + myquery(rc); + + rc= mysql_query(mysql, insert_query); + myquery(rc); + row_count= mysql_affected_rows(mysql); + DIE_UNLESS(row_count == 2); + + rc= mysql_query(mysql, insert_query); + DIE_UNLESS(rc != 0); + row_count= mysql_affected_rows(mysql); + DIE_UNLESS(row_count == (my_ulonglong)-1); + + rc= mysql_query(mysql, update_query); + myquery(rc); + row_count= mysql_affected_rows(mysql); + DIE_UNLESS(row_count == 0); + + rc= mysql_query(mysql, "DELETE FROM t1"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + DIE_UNLESS(stmt != 0); + + rc= mysql_stmt_prepare(stmt, insert_query, strlen(insert_query)); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + row_count= mysql_stmt_affected_rows(stmt); + DIE_UNLESS(row_count == 2); + + rc= mysql_stmt_execute(stmt); + DIE_UNLESS(rc != 0); + row_count= mysql_stmt_affected_rows(stmt); + DIE_UNLESS(row_count == (my_ulonglong)-1); + + rc= mysql_stmt_prepare(stmt, update_query, strlen(update_query)); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + row_count= mysql_stmt_affected_rows(stmt); + DIE_UNLESS(row_count == 0); + + rc= mysql_stmt_close(stmt); + check_execute(stmt, rc); + + rc= mysql_query(mysql, "DROP TABLE t1"); + myquery(rc); + + DBUG_VOID_RETURN; +} + + +/* + BUG#21635: MYSQL_FIELD struct's member strings seem to misbehave for + expression cols + + Check that for MIN(), MAX(), COUNT() only MYSQL_FIELD::name is set + to either expression or its alias, and db, org_table, table, + org_name fields are empty strings. +*/ +static void test_bug21635() +{ + const char *expr[]= + { + "MIN(i)", "MIN(i)", + "MIN(i) AS A1", "A1", + "MAX(i)", "MAX(i)", + "MAX(i) AS A2", "A2", + "COUNT(i)", "COUNT(i)", + "COUNT(i) AS A3", "A3", + }; + char query[MAX_TEST_QUERY_LENGTH]; + char *query_end; + MYSQL_RES *result; + MYSQL_FIELD *field; + unsigned int field_count, i; + int rc; + + DBUG_ENTER("test_bug21635"); + myheader("test_bug21635"); + + query_end= strxmov(query, "SELECT ", NullS); + for (i= 0; i < sizeof(expr) / sizeof(*expr) / 2; ++i) + query_end= strxmov(query_end, expr[i * 2], ", ", NullS); + query_end= strxmov(query_end - 2, " FROM t1 GROUP BY i", NullS); + DIE_UNLESS(query_end - query < MAX_TEST_QUERY_LENGTH); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + rc= mysql_query(mysql, "CREATE TABLE t1 (i INT)"); + myquery(rc); + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)"); + myquery(rc); + + rc= mysql_real_query(mysql, query, query_end - query); + myquery(rc); + + result= mysql_use_result(mysql); + DIE_UNLESS(result); + + field_count= mysql_field_count(mysql); + for (i= 0; i < field_count; ++i) + { + field= mysql_fetch_field_direct(result, i); + printf("%s -> %s ... ", expr[i * 2], field->name); + fflush(stdout); + DIE_UNLESS(field->db[0] == 0 && field->org_table[0] == 0 && + field->table[0] == 0 && field->org_name[0] == 0); + DIE_UNLESS(strcmp(field->name, expr[i * 2 + 1]) == 0); + puts("OK"); + } + + mysql_free_result(result); + rc= mysql_query(mysql, "DROP TABLE t1"); + myquery(rc); + + DBUG_VOID_RETURN; +} + + +/* Read and parse arguments and MySQL options from my.cnf */ @@ -15583,6 +15733,8 @@ static struct my_tests_st my_tests[]= { { "test_bug15752", test_bug15752 }, { "test_bug21206", test_bug21206 }, { "test_bug21726", test_bug21726 }, + { "test_bug23383", test_bug23383 }, + { "test_bug21635", test_bug21635 }, { 0, 0 } }; diff --git a/vio/viosocket.c b/vio/viosocket.c index 21b3dae906a..cae0cf70db4 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -33,7 +33,7 @@ int vio_read(Vio * vio, gptr buf, int size) { int r; DBUG_ENTER("vio_read"); - DBUG_PRINT("enter", ("sd: %d, buf: 0x%lx, size: %d", vio->sd, buf, size)); + DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size)); /* Ensure nobody uses vio_read_buff and vio_read simultaneously */ DBUG_ASSERT(vio->read_end == vio->read_pos); @@ -64,7 +64,7 @@ int vio_read_buff(Vio *vio, gptr buf, int size) int rc; #define VIO_UNBUFFERED_READ_MIN_SIZE 2048 DBUG_ENTER("vio_read_buff"); - DBUG_PRINT("enter", ("sd: %d, buf: 0x%lx, size: %d", vio->sd, buf, size)); + DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size)); if (vio->read_pos < vio->read_end) { @@ -102,7 +102,7 @@ int vio_write(Vio * vio, const gptr buf, int size) { int r; DBUG_ENTER("vio_write"); - DBUG_PRINT("enter", ("sd: %d, buf: 0x%lx, size: %d", vio->sd, buf, size)); + DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size)); #ifdef __WIN__ r = send(vio->sd, buf, size,0); #else @@ -227,7 +227,7 @@ int vio_keepalive(Vio* vio, my_bool set_keep_alive) int r=0; uint opt = 0; DBUG_ENTER("vio_keepalive"); - DBUG_PRINT("enter", ("sd: %d, set_keep_alive: %d", vio->sd, (int) + DBUG_PRINT("enter", ("sd: %d set_keep_alive: %d", vio->sd, (int) set_keep_alive)); if (vio->type != VIO_TYPE_NAMEDPIPE) { @@ -411,7 +411,7 @@ int vio_read_pipe(Vio * vio, gptr buf, int size) { DWORD length; DBUG_ENTER("vio_read_pipe"); - DBUG_PRINT("enter", ("sd: %d, buf: 0x%lx, size: %d", vio->sd, buf, size)); + DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size)); if (!ReadFile(vio->hPipe, buf, size, &length, NULL)) DBUG_RETURN(-1); @@ -425,7 +425,7 @@ int vio_write_pipe(Vio * vio, const gptr buf, int size) { DWORD length; DBUG_ENTER("vio_write_pipe"); - DBUG_PRINT("enter", ("sd: %d, buf: 0x%lx, size: %d", vio->sd, buf, size)); + DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size)); if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL)) DBUG_RETURN(-1); @@ -470,7 +470,7 @@ int vio_read_shared_memory(Vio * vio, gptr buf, int size) char *current_postion; DBUG_ENTER("vio_read_shared_memory"); - DBUG_PRINT("enter", ("sd: %d, buf: 0x%lx, size: %d", vio->sd, buf, size)); + DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size)); remain_local = size; current_postion=buf; @@ -531,7 +531,7 @@ int vio_write_shared_memory(Vio * vio, const gptr buf, int size) char *current_postion; DBUG_ENTER("vio_write_shared_memory"); - DBUG_PRINT("enter", ("sd: %d, buf: 0x%lx, size: %d", vio->sd, buf, size)); + DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size)); remain = size; current_postion = buf; diff --git a/vio/viossl.c b/vio/viossl.c index b5fd0e11c02..806f6fc356a 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -87,8 +87,8 @@ int vio_ssl_read(Vio *vio, gptr buf, int size) { int r; DBUG_ENTER("vio_ssl_read"); - DBUG_PRINT("enter", ("sd: %d, buf: 0x%lx, size: %d, ssl_: 0x%lx", - vio->sd, buf, size, vio->ssl_arg)); + DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d ssl: 0x%lx", + vio->sd, (long) buf, size, (long) vio->ssl_arg)); r= SSL_read((SSL*) vio->ssl_arg, buf, size); #ifndef DBUG_OFF @@ -104,7 +104,7 @@ int vio_ssl_write(Vio *vio, const gptr buf, int size) { int r; DBUG_ENTER("vio_ssl_write"); - DBUG_PRINT("enter", ("sd: %d, buf: 0x%lx, size: %d", vio->sd, buf, size)); + DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size)); r= SSL_write((SSL*) vio->ssl_arg, buf, size); #ifndef DBUG_OFF @@ -126,14 +126,18 @@ int vio_ssl_close(Vio *vio) { switch ((r= SSL_shutdown(ssl))) { - case 1: /* Shutdown successful */ + case 1: + /* Shutdown successful */ + break; + case 0: + /* + Shutdown not yet finished - since the socket is going to + be closed there is no need to call SSL_shutdown() a second + time to wait for the other side to respond + */ break; - case 0: /* Shutdown not yet finished, call it again */ - if ((r= SSL_shutdown(ssl) >= 0)) - break; - /* Fallthrough */ default: /* Shutdown failed */ - DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %s", + DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %d", SSL_get_error(ssl, r))); break; } @@ -151,8 +155,8 @@ int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout) my_bool net_blocking; enum enum_vio_type old_type; DBUG_ENTER("sslaccept"); - DBUG_PRINT("enter", ("sd: %d ptr: %p, timeout: %d", - vio->sd, ptr, timeout)); + DBUG_PRINT("enter", ("sd: %d ptr: 0x%lx, timeout: %ld", + vio->sd, (long) ptr, timeout)); old_type= vio->type; net_blocking= vio_is_blocking(vio); @@ -168,7 +172,7 @@ int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout) DBUG_RETURN(1); } vio->ssl_arg= (void*)ssl; - DBUG_PRINT("info", ("ssl_: %p timeout: %ld", ssl, timeout)); + DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout)); SSL_clear(ssl); SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); SSL_set_fd(ssl, vio->sd); @@ -226,8 +230,8 @@ int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout) enum enum_vio_type old_type; DBUG_ENTER("sslconnect"); - DBUG_PRINT("enter", ("sd: %d, ptr: %p, ctx: %p", - vio->sd, ptr, ptr->ssl_context)); + DBUG_PRINT("enter", ("sd: %d ptr: 0x%lx ctx: 0x%lx", + vio->sd, (long) ptr, (long) ptr->ssl_context)); old_type= vio->type; net_blocking= vio_is_blocking(vio); @@ -242,7 +246,7 @@ int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout) DBUG_RETURN(1); } vio->ssl_arg= (void*)ssl; - DBUG_PRINT("info", ("ssl: %p, timeout: %ld", ssl, timeout)); + DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout)); SSL_clear(ssl); SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); SSL_set_fd(ssl, vio->sd); diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 34ce1fefaa9..014ce25d754 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -79,8 +79,8 @@ static int vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file) { DBUG_ENTER("vio_set_cert_stuff"); - DBUG_PRINT("enter", ("ctx: %p, cert_file: %s, key_file: %s", - ctx, cert_file, key_file)); + DBUG_PRINT("enter", ("ctx: 0x%lx cert_file: %s key_file: %s", + (long) ctx, cert_file, key_file)); if (cert_file) { if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) @@ -128,7 +128,7 @@ vio_verify_callback(int ok, X509_STORE_CTX *ctx) X509 *err_cert; DBUG_ENTER("vio_verify_callback"); - DBUG_PRINT("enter", ("ok: %d, ctx: %p", ok, ctx)); + DBUG_PRINT("enter", ("ok: %d ctx: 0x%lx", ok, (long) ctx)); err_cert= X509_STORE_CTX_get_current_cert(ctx); X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); @@ -139,7 +139,7 @@ vio_verify_callback(int ok, X509_STORE_CTX *ctx) err= X509_STORE_CTX_get_error(ctx); depth= X509_STORE_CTX_get_error_depth(ctx); - DBUG_PRINT("error",("verify error: %d, '%s'",err, + DBUG_PRINT("error",("verify error: %d '%s'",err, X509_verify_cert_error_string(err))); /* Approve cert if depth is greater then "verify_depth", currently |